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_main.c < prev    next >
C/C++ Source or Header  |  1994-07-23  |  38KB  |  1,582 lines

  1. #if !defined(lint) && !defined(SABER)
  2. static char sccsid[] = "@(#)ns_main.c    4.55 (Berkeley) 7/1/91";
  3. static char rcsid[] = "$Id: ns_main.c,v 4.9.1.19 1994/07/23 23:23:56 vixie Exp $";
  4. #endif /* not lint */
  5.  
  6. /*
  7.  * ++Copyright++ 1986, 1989, 1990
  8.  * -
  9.  * Copyright (c) 1986, 1989, 1990
  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. #if !defined(lint) && !defined(SABER)
  62. char copyright[] =
  63. "@(#) Copyright (c) 1986, 1989, 1990 The Regents of the University of California.\n\
  64.  portions Copyright (c) 1993 Digital Equipment Corporation\n\
  65.  portions Copyright (c) 1993 Berkeley Network Software Consortium\n\
  66.  All rights reserved.\n";
  67. #endif /* not lint */
  68.  
  69. /*
  70.  * Internet Name server (see rfc883 & others).
  71.  */
  72.  
  73. #include <sys/param.h>
  74. #include <sys/file.h>
  75. #include <sys/stat.h>
  76. #if !defined(SYSV) && defined(XXX)
  77. #include <sys/wait.h>
  78. #endif /* !SYSV */
  79. #include <sys/time.h>
  80. #define TIME_H_INCLUDED
  81. #include <sys/resource.h>
  82. #if defined(__osf__)
  83. #define _SOCKADDR_LEN        /* XXX - should be in portability.h but that
  84.                  * would need to be included before socket.h
  85.                  */
  86. #endif
  87. #include <sys/ioctl.h>
  88. #include <sys/socket.h>
  89. #include <netinet/in.h>
  90. #include <net/if.h>
  91. #include <arpa/nameser.h>
  92. #include <arpa/inet.h>
  93. #include <fcntl.h>
  94. #include <stdio.h>
  95. #include <syslog.h>
  96. #include <errno.h>
  97. #include <signal.h>
  98. #include <netdb.h>
  99. #include <resolv.h>
  100. #if defined(SVR4)
  101. # include <sys/sockio.h>
  102. #endif
  103.  
  104. #define MAIN_PROGRAM
  105. #include "named.h"
  106. #undef MAIN_PROGRAM
  107.  
  108. #undef nsaddr
  109.  
  110.                 /* UDP receive, TCP send buffer size */
  111. static    const int        rbufsize = 8 * 1024;
  112.  
  113. static    struct sockaddr_in    nsaddr;
  114. static    u_int16_t        local_ns_port;        /* our service port */
  115. static    fd_set            mask;            /* open descriptors */
  116. static    char            **Argv = NULL;
  117. static    char            *LastArg = NULL;    /* end of argv */
  118.  
  119. static    struct qstream        *sqadd __P((void));
  120. static    void            sq_query __P((struct qstream *)),
  121.                 opensocket __P((struct qdatagram *)),
  122. #ifdef DEBUG
  123.                 printnetinfo __P((struct netinfo *)),
  124. #endif
  125.                 setdebug __P((int));
  126. static    int            sq_here __P((struct qstream *));
  127.  
  128. static    SIG_FN            onintr __P(()),
  129.                 maint_alarm __P(()),
  130.                 setdumpflg __P(()),
  131.                 onhup __P(()),
  132. #if defined(QRYLOG) && defined(SIGWINCH)
  133.                 setQrylogFlg __P(()),
  134. #endif
  135.                 setIncrDbgFlg __P(()),
  136.                 setNoDbgFlg __P(()),
  137. #ifdef SIGSYS
  138.                 sigprof __P(()),
  139. #endif /* SIGSYS */
  140.                 setchkptflg __P(()),
  141.                 setstatsflg __P(());
  142.  
  143. static void
  144. usage()
  145. {
  146.     fprintf(stderr,
  147. "Usage: named [-d #] [-q] [-r] [-p port[/localport]] [[-b] bootfile]\n");
  148.     exit(1);
  149. }
  150.  
  151. /*ARGSUSED*/
  152. void
  153. main(argc, argv, envp)
  154.     int argc;
  155.     char *argv[], *envp[];
  156. {
  157.     register int n, udpcnt;
  158.     register char *arg;
  159.     register struct qstream *sp;
  160.     register struct qdatagram *dqp;
  161.     struct qstream *nextsp;
  162.     int nfds;
  163.     const int on = 1;
  164.     int len;
  165.     int rfd, size;
  166.     time_t lasttime, maxctime;
  167.     u_char buf[BUFSIZ];
  168. #ifndef SYSV
  169.     struct sigvec vec;
  170. #endif
  171.     fd_set tmpmask;
  172.     struct timeval t, *tp;
  173.     struct qstream *candidate = QSTREAM_NULL;
  174.     char **argp;
  175. #ifdef PID_FIX
  176.     char oldpid[10];
  177. #endif
  178. #ifdef WANT_PIDFILE
  179.     FILE    *fp;            /* file descriptor for pid file */
  180. #endif
  181. #ifdef IP_OPTIONS
  182.     u_char ip_opts[50];        /* arbitrary size */
  183. #endif
  184.  
  185.     local_ns_port = ns_port = htons(NAMESERVER_PORT);
  186.  
  187.     /*
  188.     **  Save start and extent of argv for ns_setproctitle().
  189.     */
  190.  
  191.     Argv = argp = argv;
  192.     while (*argp)
  193.         argp++;
  194.     LastArg = argp[-1] + strlen(argp[-1]);
  195.  
  196.     (void) umask(022);
  197.     /* XXX - should use getopt here */
  198.     while (--argc > 0) {
  199.         arg = *++argv;
  200.         if (*arg == '-') {
  201.             while (*++arg)
  202.                 switch (*arg) {
  203.                 case 'b':
  204.                     if (--argc <= 0)
  205.                         usage();
  206.                     bootfile = savestr(*++argv);
  207.                     break;
  208.  
  209.                   case 'd':
  210.                      ++argv;
  211.  
  212.                      if (*argv != 0) {
  213.                          if (**argv == '-') {
  214.                          argv--;
  215.                          break;
  216.                          }
  217. #ifdef DEBUG
  218.                          debug = atoi(*argv);
  219. #endif
  220.                          --argc;
  221.                      }
  222. #ifdef DEBUG
  223.                     if (debug <= 0)
  224.                         debug = 1;
  225.                     setdebug(1);
  226. #endif
  227.                     break;
  228.  
  229.                 case 'p':
  230.                     /* use nonstandard port number.
  231.                      * usage: -p remote/local
  232.                      * remote is the port number to which
  233.                      * we send queries.  local is the port
  234.                      * on which we listen for queries.
  235.                      * local defaults to same as remote.
  236.                      */
  237.                     if (--argc <= 0)
  238.                         usage();
  239.                     ns_port = htons((u_int16_t)
  240.                             atoi(*++argv));
  241.                     {
  242.                         char *p = strchr(*argv, '/');
  243.                         if (p) {
  244.                         local_ns_port =
  245.                             htons((u_int16_t)
  246.                               atoi(p+1));
  247.                         } else {
  248.                         local_ns_port = ns_port;
  249.                         }
  250.                     }
  251.                     break;
  252.  
  253. #ifdef QRYLOG
  254.                 case 'q':
  255.                     qrylog = 1;
  256.                     break;
  257. #endif
  258.  
  259.                 case 'r':
  260.                     NoRecurse = 1;
  261.                     break;
  262.  
  263.                 default:
  264.                     usage();
  265.                 }
  266.         } else
  267.             bootfile = savestr(*argv);
  268.     }
  269.  
  270. #ifdef DEBUG
  271.     if (!debug)
  272. #endif
  273.         for (n = getdtablesize() - 1; n > 2; n--)
  274.             (void) close(n);    /* don't use my_close() here */
  275. #ifdef DEBUG
  276.     else {
  277.         fprintf(ddt, "Debug turned ON, Level %d\n",debug);
  278.         fprintf(ddt, "Version = %s\n", Version);
  279.         fprintf(ddt, "bootfile = %s\n", bootfile);
  280.     }        
  281. #endif
  282.  
  283.     n = 0;
  284. #if defined(DEBUG) && defined(LOG_PERROR)
  285.     if (debug)
  286.         n = LOG_PERROR;
  287. #endif
  288. #ifdef LOG_DAEMON
  289.     openlog("named", LOG_PID|LOG_CONS|LOG_NDELAY|n, LOGFAC);
  290. #else
  291.     openlog("named", LOG_PID);
  292. #endif
  293.  
  294. #ifdef WANT_PIDFILE
  295.     /* tuck my process id away */
  296. #ifdef PID_FIX
  297.     fp = fopen(PidFile, "r+");
  298.     if (fp != NULL) {
  299.         (void) fgets(oldpid, sizeof(oldpid), fp);
  300.         (void) rewind(fp);
  301.         fprintf(fp, "%d\n", getpid());
  302.         (void) my_fclose(fp);
  303.     }
  304. #else /*PID_FIX*/
  305.     fp = fopen(PidFile, "w");
  306.     if (fp != NULL) {
  307.         fprintf(fp, "%d\n", getpid());
  308.         (void) my_fclose(fp);
  309.     }
  310. #endif /*PID_FIX*/
  311. #endif /*WANT_PIDFILE*/
  312.  
  313.     syslog(LOG_NOTICE, "starting.  %s", Version);
  314.  
  315.     _res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE);
  316.  
  317.     nsaddr.sin_family = AF_INET;
  318.     nsaddr.sin_addr.s_addr = INADDR_ANY;
  319.     nsaddr.sin_port = local_ns_port;
  320.  
  321.     /*
  322.     ** Open stream port.
  323.     */
  324.     for (n = 0; ; n++) {
  325.         if ((vs = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  326.             syslog(LOG_ERR, "socket(SOCK_STREAM): %m");
  327.             exit(1);
  328.         }    
  329.         if (setsockopt(vs, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
  330.             sizeof(on)) != 0)
  331.         {
  332.             syslog(LOG_ERR, "setsockopt(vs, reuseaddr): %m");
  333.             (void) my_close(vs);
  334.             continue;
  335.         }
  336.         if (bind(vs, (struct sockaddr *)&nsaddr, sizeof(nsaddr)) == 0)
  337.             break;
  338.  
  339.         if (errno != EADDRINUSE || n > 4) {
  340.             if (errno == EADDRINUSE) {
  341.                 syslog(LOG_ERR,
  342.                  "There may be a name server already running");
  343.                 syslog(LOG_ERR, "exiting");
  344.             } else {
  345.                 syslog(LOG_ERR, "bind(vs, [%s].%d): %m",
  346.                     inet_ntoa(nsaddr.sin_addr),
  347.                     ntohs(nsaddr.sin_port));
  348.             }
  349. #if defined(WANT_PIDFILE) && defined(PID_FIX)
  350.             /* put old pid back */
  351.             if (atoi(oldpid) && (fp = fopen(PidFile, "w"))) {
  352.                 fprintf(fp, "%s", oldpid);
  353.                 (void) my_fclose(fp);
  354.                 _exit(1);
  355.             }
  356. #endif /*WANT_PIDFILE && PID_FIX*/
  357.             exit(1);
  358.         } else {    /* Retry opening the socket a few times */
  359.             my_close(vs);
  360.             sleep(1);
  361.         }
  362.     }
  363.     if (listen(vs, 5) != 0) {
  364.         syslog(LOG_ERR, "listen(vs, 5): %m");
  365.         exit(1);
  366.     }
  367.  
  368.       /*
  369.      * named would be terminated if one of these is sent and no handler
  370.      */
  371.     (void) signal(SIGINT, setdumpflg);
  372.     (void) signal(SIGQUIT, setchkptflg);
  373.     (void) signal(SIGIOT, setstatsflg);
  374. #if defined(SIGUSR1) && defined(SIGUSR2)
  375.     (void) signal(SIGUSR1, setIncrDbgFlg);
  376.     (void) signal(SIGUSR2, setNoDbgFlg);
  377. #else /* SIGUSR1&&SIGUSR2 */
  378.     (void) signal(SIGEMT, setIncrDbgFlg);
  379.     (void) signal(SIGFPE, setNoDbgFlg);
  380. #endif /* SIGUSR1&&SIGUSR2 */
  381.  
  382. #if defined(SIGWINCH) && defined(QRYLOG)
  383.     (void) signal(SIGWINCH, setQrylogFlg);
  384. #endif
  385.  
  386.     /*
  387.      * Get list of local addresses and set up datagram sockets.
  388.      */
  389.     getnetconf();
  390.  
  391.     /*
  392.     ** Initialize and load database.
  393.     */
  394.     gettime(&tt);
  395.     buildservicelist();
  396.     buildprotolist();
  397.     ns_init(bootfile);
  398. #ifdef DEBUG
  399.     if (debug) {
  400.         fprintf(ddt, "Network and sort list:\n");
  401.         printnetinfo(nettab);
  402.     }
  403. #endif
  404.  
  405.     time(&boottime);
  406.     resettime = boottime;
  407.  
  408.     (void) signal(SIGHUP, onhup);
  409. #if defined(SIGXFSZ)
  410.     (void) signal(SIGXFSZ, onhup);    /* wierd DEC Hesiodism, harmless */
  411. #endif
  412. #if defined(SYSV)
  413.     (void) signal(SIGCLD, endxfer);
  414.     (void) signal(SIGALRM, maint_alarm);
  415. #else
  416.     bzero((char *)&vec, sizeof(vec));
  417.     vec.sv_handler = maint_alarm;
  418.     vec.sv_mask = sigmask(SIGCHLD);
  419.     (void) sigvec(SIGALRM, &vec, (struct sigvec *)NULL);
  420.  
  421.     vec.sv_handler = endxfer;
  422.     vec.sv_mask = sigmask(SIGALRM);
  423.     (void) sigvec(SIGCHLD, &vec, (struct sigvec *)NULL);
  424. #endif /* SYSV */
  425.     (void) signal(SIGPIPE, SIG_IGN);
  426. #ifdef SIGSYS
  427.     (void) signal(SIGSYS, sigprof);
  428. #endif /* SIGSYS */
  429.  
  430. #ifdef ALLOW_UPDATES
  431.         /* Catch SIGTERM so we can dump the database upon shutdown if it
  432.            has changed since it was last dumped/booted */
  433.         (void) signal(SIGTERM, onintr);
  434. #endif
  435.  
  436.     dprintf(1, (ddt, "database initialized\n"));
  437.     t.tv_usec = 0;
  438.  
  439.     /*
  440.      * Fork and go into background now that
  441.      * we've done any slow initialization
  442.      * and are ready to answer queries.
  443.      */
  444. #ifdef USE_SETSID
  445.     if (
  446. #ifdef DEBUG
  447.         !debug ||
  448. #endif
  449.         !isatty(0)) {
  450.         if (fork() > 0)
  451.             exit(0);
  452.         setsid();
  453. #ifdef DEBUG
  454.         if (!debug)
  455. #endif
  456.         {
  457.             n = open(_PATH_DEVNULL, O_RDONLY);
  458.             (void) dup2(n, 0);
  459.             (void) dup2(n, 1);
  460.             (void) dup2(n, 2);
  461.             if (n > 2)
  462.                 (void) my_close(n);
  463.         }
  464.     }
  465. #else
  466. #ifdef DEBUG
  467.     if (!debug)
  468. #endif
  469.     {
  470. #ifdef HAVE_DAEMON
  471.         daemon(1, 0);
  472. #else
  473.         switch (fork()) {
  474.         case -1:
  475.             syslog(LOG_ERR, "fork: %m");
  476.             exit(1);
  477.             /*FALLTHROUGH*/
  478.         case 0:
  479.             /* child */
  480.             break;
  481.         default:
  482.             /* parent */
  483.             exit(0);
  484.         }
  485.         n = open(_PATH_DEVNULL, O_RDONLY);
  486.         (void) dup2(n, 0);
  487.         (void) dup2(n, 1);
  488.         (void) dup2(n, 2);
  489.         if (n > 2)
  490.             (void) my_close(n);
  491. #ifdef SYSV
  492.         setpgrp();
  493. #else
  494.         {
  495.             struct itimerval ival;
  496.  
  497.             /*
  498.              * The open below may hang on pseudo ttys if the person
  499.              * who starts named logs out before this point.
  500.              *
  501.              * needmaint may get set inapropriately if the open
  502.              * hangs, but all that will happen is we will see that
  503.              * no maintenance is required.
  504.              */
  505.             bzero((char *)&ival, sizeof(ival));
  506.             ival.it_value.tv_sec = 120;
  507.             (void) setitimer(ITIMER_REAL, &ival,
  508.                     (struct itimerval *)NULL);
  509.             n = open(_PATH_TTY, O_RDWR);
  510.             ival.it_value.tv_sec = 0;
  511.             (void) setitimer(ITIMER_REAL, &ival,
  512.                     (struct itimerval *)NULL);
  513.             if (n > 0) {
  514.                 (void) ioctl(n, TIOCNOTTY, (char *)NULL);
  515.                 (void) my_close(n);
  516.             }
  517.         }
  518. #endif /* SYSV */
  519. #endif /* HAVE_DAEMON */
  520.     }
  521. #endif /* USE_SETSID */
  522. #ifdef WANT_PIDFILE
  523.     /* tuck my process id away again */
  524.     fp = fopen(PidFile, "w");
  525.     if (fp != NULL) {
  526.         fprintf(fp, "%d\n", getpid());
  527.         (void) my_fclose(fp);
  528.     }
  529. #endif
  530.  
  531.     syslog(LOG_NOTICE, "Ready to answer queries.\n");
  532.     prime_cache();
  533.     nfds = getdtablesize();       /* get the number of file descriptors */
  534.     if (nfds > FD_SETSIZE) {
  535.         nfds = FD_SETSIZE;    /* Bulletproofing */
  536.         syslog(LOG_ERR, "Return from getdtablesize() > FD_SETSIZE");
  537.     }
  538.     FD_ZERO(&mask);
  539.     FD_SET(vs, &mask);
  540.     for (dqp = datagramq; dqp != QDATAGRAM_NULL; dqp = dqp->dq_next)
  541.         FD_SET(dqp->dq_dfd, &mask);
  542.     for (;;) {
  543. #ifdef DEBUG
  544.         if (ddt && debug == 0) {
  545.             fprintf(ddt,"Debug turned OFF\n");
  546.             (void) my_fclose(ddt);
  547.             ddt = 0;
  548.         }
  549. #endif
  550. #ifdef ALLOW_UPDATES
  551.                 if (needToExit) {
  552.             struct zoneinfo *zp;
  553.             sigblock(~0);   /*
  554.                      * Block all blockable signals
  555.                      * to ensure a consistant
  556.                      * state during final dump
  557.                      */
  558.             dprintf(1, (ddt, "Received shutdown signal\n"));
  559.             for (zp = zones; zp < &zones[nzones]; zp++) {
  560.                 if (zp->z_flags & Z_CHANGED)
  561.                     zonedump(zp);
  562.                         }
  563.                         exit(0);
  564.                 }
  565. #endif /* ALLOW_UPDATES */
  566.         if (needreload) {
  567.             needreload = 0;
  568.             db_reload();
  569.         }
  570.         if (needStatsDump) {
  571.             needStatsDump = 0;
  572.             ns_stats();
  573.         }
  574.         if (needzoneload) {
  575.             needzoneload = 0;
  576.             loadxfer();
  577.         }
  578.         if (needmaint) {
  579.                         needmaint = 0;
  580.                         ns_maint();
  581.                 }
  582.             if(needToChkpt) {
  583.                         needToChkpt = 0;
  584.                         doachkpt();
  585.             }
  586.                 if(needToDoadump) {
  587.                         needToDoadump = 0;
  588.                         doadump();
  589.                 }
  590.         /*
  591.         ** Wait until a query arrives
  592.         */
  593.         if (retryqp != NULL) {
  594.             gettime(&tt);
  595.             /*
  596.             ** The tv_sec field might be unsigned 
  597.             ** and thus cannot be negative.
  598.             */
  599.             if ((int32_t) retryqp->q_time <= tt.tv_sec) {
  600.                 retry(retryqp);
  601.                 continue;
  602.             }
  603.             t.tv_sec = (int32_t) retryqp->q_time - tt.tv_sec;
  604.             tp = &t;
  605.         } else
  606.             tp = NULL;
  607.         tmpmask = mask;
  608.         n = select(nfds, &tmpmask, (fd_set *)NULL, (fd_set *)NULL, tp);
  609.         if (n < 0) {
  610.             if (errno != EINTR) {
  611.                 syslog(LOG_ERR, "select: %m");
  612.                 sleep(60);
  613.             }
  614.         }
  615.         if (n <= 0)
  616.             continue;
  617.  
  618.         for (dqp = datagramq;
  619.              dqp != QDATAGRAM_NULL;
  620.              dqp = dqp->dq_next) {
  621.             if (FD_ISSET(dqp->dq_dfd, &tmpmask))
  622.                 for (udpcnt = 0; udpcnt < 25; udpcnt++) {  /*XXX*/
  623.                 from_len = sizeof(from_addr);
  624.                 if ((n = recvfrom(dqp->dq_dfd, buf, sizeof(buf), 0,
  625.                 (struct sockaddr *)&from_addr, &from_len)) < 0)
  626.                 {
  627.                 if ((n < 0) && (errno == PORT_WOULDBLK))
  628.                     break;
  629.                 syslog(LOG_WARNING, "recvfrom: %m");
  630.                 break;
  631.                 }
  632.                 if (n == 0)
  633.                 break;
  634.                 gettime(&tt);
  635.                 dprintf(1, (ddt,
  636.                  "\ndatagram from [%s].%d, fd %d, len %d; now %s",
  637.                     inet_ntoa(from_addr.sin_addr),
  638.                     ntohs(from_addr.sin_port),
  639.                     dqp->dq_dfd, n,
  640.                         ctime(&tt.tv_sec)));
  641. #ifdef DEBUG
  642.                 if (debug >= 10)
  643.                 fp_query(buf, ddt);
  644. #endif
  645.                 /*
  646.                  * Consult database to get the answer.
  647.                  */
  648.                 gettime(&tt);
  649.                 ns_req(buf, n, PACKETSZ, QSTREAM_NULL, &from_addr,
  650.                     dqp->dq_dfd);
  651.                 }
  652.         }
  653.         /*
  654.         ** Process stream connection.
  655.         **
  656.         ** Note that a "continue" in here takes us back to the select()
  657.         ** which, if our accept() failed, will bring us back here.
  658.         */
  659.         if (FD_ISSET(vs, &tmpmask)) {
  660.             from_len = sizeof(from_addr);
  661.             rfd = accept(vs,
  662.                      (struct sockaddr *)&from_addr,
  663.                      &from_len);
  664.             if (rfd < 0 && errno == EINTR)
  665.                 continue;
  666.             if (rfd < 0 && errno == EMFILE && streamq) {
  667.                 maxctime = 0;
  668.                 candidate = NULL;
  669.                 for (sp = streamq; sp; sp = nextsp) {
  670.                     nextsp = sp->s_next;
  671.                     if (sp->s_refcnt)
  672.                         continue;
  673.                     gettime(&tt);
  674.                     lasttime = tt.tv_sec - sp->s_time;
  675.                     if (lasttime >= VQEXPIRY)
  676.                         sqrm(sp);
  677.                     else if (lasttime > maxctime) {
  678.                         candidate = sp;
  679.                         maxctime = lasttime;
  680.                     }
  681.                 }
  682.                 if (candidate)
  683.                     sqrm(candidate);
  684.                 continue;
  685.             }
  686.             if (rfd < 0) {
  687.                 syslog(LOG_WARNING, "accept: %m");
  688.                 continue;
  689.             }
  690.             if ((n = fcntl(rfd, F_GETFL, 0)) < 0) {
  691.                 syslog(LOG_ERR, "fcntl(rfd, F_GETFL): %m");
  692.                 (void) my_close(rfd);
  693.                 continue;
  694.             }
  695.             if (fcntl(rfd, F_SETFL, n|PORT_NONBLOCK) != 0) {
  696.                 syslog(LOG_ERR, "fcntl(rfd, NONBLOCK): %m");
  697.                 (void) my_close(rfd);
  698.                 continue;
  699.             }
  700. #if defined(IP_OPTIONS)
  701.             len = sizeof ip_opts;
  702.             if (getsockopt(rfd, IPPROTO_IP, IP_OPTIONS,
  703.                        (char *)ip_opts, &len) < 0) {
  704.                 syslog(LOG_ERR,
  705.                        "getsockopt(rfd, IP_OPTIONS): %m");
  706.                 (void) my_close(rfd);
  707.                 continue;
  708.             }
  709.             if (len != 0) {
  710.                 nameserIncr(from_addr.sin_addr, nssRcvdOpts);
  711.                 if (!haveComplained((char*)
  712.                             from_addr.sin_addr.s_addr,
  713.                             "rcvd ip options")) {
  714.                     syslog(LOG_NOTICE,
  715.                       "rcvd IP_OPTIONS from [%s].%d (ignored)",
  716.                            inet_ntoa(from_addr.sin_addr),
  717.                            ntohs(from_addr.sin_port));
  718.                 }
  719.                 if (setsockopt(rfd, IPPROTO_IP, IP_OPTIONS,
  720.                            NULL, 0) < 0) {
  721.                     syslog(LOG_ERR,
  722.                            "setsockopt(!IP_OPTIONS): %m");
  723.                     (void) my_close(rfd);
  724.                     continue;
  725.                 }
  726.             }
  727. #endif
  728.             if (setsockopt(rfd, SOL_SOCKET, SO_KEEPALIVE,
  729.                        (char *)&on, sizeof(on)) < 0) {
  730.                 syslog(LOG_ERR,
  731.                        "setsockopt(rfd, KEEPALIVE): %m");
  732.                 (void) my_close(rfd);
  733.                 continue;
  734.             }
  735.             if ((sp = sqadd()) == QSTREAM_NULL) {
  736.                 (void) my_close(rfd);
  737.                 continue;
  738.             }
  739.             sp->s_rfd = rfd;    /* stream file descriptor */
  740.             sp->s_size = -1;    /* amount of data to receive */
  741.             gettime(&tt);
  742.             sp->s_time = tt.tv_sec;    /* last transaction time */
  743.             sp->s_from = from_addr;    /* address to respond to */
  744.             sp->s_bufp = (u_char *)&sp->s_tempsize;
  745.             FD_SET(rfd, &mask);
  746.             FD_SET(rfd, &tmpmask);
  747.             dprintf(1, (ddt,
  748.                   "\nTCP connection from [%s].%d (fd %d)\n",
  749.                     inet_ntoa(sp->s_from.sin_addr),
  750.                     ntohs(sp->s_from.sin_port), rfd));
  751.         }
  752.         if (streamq) {
  753.             dprintf(3, (ddt, "streamq = 0x%x\n",streamq));
  754.         }
  755.         for (sp = streamq;  sp != QSTREAM_NULL;  sp = nextsp) {
  756.             nextsp = sp->s_next;
  757.             if (!FD_ISSET(sp->s_rfd, &tmpmask))
  758.                 continue;
  759.             dprintf(5, (ddt,
  760.                     "sp x%x rfd %d size %d time %d next x%x\n",
  761.                     sp, sp->s_rfd, sp->s_size,
  762.                     sp->s_time, sp->s_next));
  763.             dprintf(5, (ddt,
  764.                     "\tbufsize %d buf x%x bufp x%x\n",
  765.                     sp->s_bufsize, sp->s_buf, sp->s_bufp));
  766.             if (sp->s_size < 0) {
  767.                 size = INT16SZ
  768.                     - (sp->s_bufp - (u_char *)&sp->s_tempsize);
  769.                     while (size > 0 &&
  770.                        (n = read(sp->s_rfd, sp->s_bufp, size)) > 0
  771.                        ) {
  772.                     sp->s_bufp += n;
  773.                     size -= n;
  774.                     }
  775.                 if ((n < 0) && (errno == PORT_WOULDBLK))
  776.                     continue;
  777.                 if (n <= 0) {
  778.                     sqrm(sp);
  779.                     continue;
  780.                     }
  781.                     if ((sp->s_bufp - (u_char *)&sp->s_tempsize) ==
  782.                     INT16SZ) {
  783.                     sp->s_size = htons(sp->s_tempsize);
  784.                     if (sp->s_bufsize == 0) {
  785.                         if ( (sp->s_buf = (u_char *)
  786.                           malloc(rbufsize))
  787.                         == NULL) {
  788.                             sp->s_buf = buf;
  789.                             sp->s_size  = sizeof(buf);
  790.                         } else {
  791.                             sp->s_bufsize = rbufsize;
  792.                         }
  793.                     }
  794.                     if (sp->s_size > sp->s_bufsize &&
  795.                         sp->s_bufsize != 0
  796.                     ) {
  797.                         sp->s_buf = (u_char *)
  798.                         realloc((char *)sp->s_buf,
  799.                             (unsigned)sp->s_size);
  800.                         if (sp->s_buf == NULL) {
  801.                         sp->s_buf = buf;
  802.                         sp->s_bufsize = 0;
  803.                         sp->s_size = sizeof(buf);
  804.                         } else {
  805.                         sp->s_bufsize = sp->s_size;
  806.                         }
  807.                     }
  808.                     sp->s_bufp = sp->s_buf;    
  809.                 }
  810.             }
  811.             gettime(&tt);
  812.             sp->s_time = tt.tv_sec;
  813.             while (sp->s_size > 0 &&
  814.                   (n = read(sp->s_rfd,
  815.                     sp->s_bufp,
  816.                     sp->s_size)
  817.                    ) > 0
  818.             ) {
  819.                 sp->s_bufp += n;
  820.                 sp->s_size -= n;
  821.             }
  822.             /*
  823.              * we don't have enough memory for the query.
  824.              * if we have a query id, then we will send an
  825.              * error back to the user.
  826.              */
  827.             if (sp->s_bufsize == 0 &&
  828.                 (sp->s_bufp - sp->s_buf > INT16SZ)) {
  829.                 HEADER *hp;
  830.  
  831.                 hp = (HEADER *)sp->s_buf;
  832.                 hp->qr = 1;
  833.                 hp->ra = 1;
  834.                 hp->ancount = 0;
  835.                 hp->qdcount = 0;
  836.                 hp->nscount = 0;
  837.                 hp->arcount = 0;
  838.                 hp->rcode = SERVFAIL;
  839.                 (void) writemsg(sp->s_rfd, sp->s_buf,
  840.                         HFIXEDSZ);
  841.                 continue;
  842.             }
  843.             if ((n == -1) && (errno == PORT_WOULDBLK))
  844.                 continue;
  845.             if (n <= 0) {
  846.                 sqrm(sp);
  847.                 continue;
  848.             }
  849.             /*
  850.              * Consult database to get the answer.
  851.              */
  852.             if (sp->s_size == 0) {
  853.                 nameserIncr(sp->s_from.sin_addr, nssRcvdTCP);
  854.                 sq_query(sp);
  855.                 ns_req(sp->s_buf,
  856.                        sp->s_bufp - sp->s_buf,
  857.                        sp->s_bufsize, sp,
  858.                        &sp->s_from, -1);
  859.                 /* ns_req() can call sqrm() - check for it */
  860.                 if (sq_here(sp)) {
  861.                     sp->s_bufp = (u_char *)&sp->s_tempsize;
  862.                     sp->s_size = -1;
  863.                 }
  864.                 continue;
  865.             }
  866.         }
  867.     }
  868.     /* NOTREACHED */
  869. }
  870.  
  871. void
  872. getnetconf()
  873. {
  874.     register struct netinfo *ntp;
  875.     struct netinfo *ontp;
  876.     struct ifconf ifc;
  877.     struct ifreq ifreq, *ifr;
  878.     struct qdatagram *dqp;
  879.     static int first = 1;
  880.     char buf[BUFSIZ], *cp, *cplim;
  881.     u_int32_t nm;
  882.     time_t my_generation = time(NULL);
  883.  
  884.     ifc.ifc_len = sizeof(buf);
  885.     ifc.ifc_buf = buf;
  886.     if (ioctl(vs, SIOCGIFCONF, (char *)&ifc) < 0) {
  887.         syslog(LOG_ERR, "get interface configuration: %m - exiting");
  888.         exit(1);
  889.     }
  890.     ntp = NULL;
  891. #if defined(AF_LINK) && !defined(RISCOS_BSD)
  892. #define my_max(a, b) (a > b ? a : b)
  893. #define my_size(p)    my_max((p).sa_len, sizeof(p))
  894. #else
  895. #define my_size(p) (sizeof (p))
  896. #endif
  897.     cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
  898.     for (cp = buf;
  899.          cp < cplim;
  900.          cp += sizeof (ifr->ifr_name) + my_size(ifr->ifr_addr)) {
  901. #undef my_size
  902.         ifr = (struct ifreq *)cp;
  903.         if (ifr->ifr_addr.sa_family != AF_INET ||
  904.            ((struct sockaddr_in *)
  905.             &ifr->ifr_addr)->sin_addr.s_addr == 0) {
  906.             continue;
  907.         }
  908.         ifreq = *ifr;
  909.         /*
  910.          * Don't test IFF_UP, packets may still be received at this
  911.          * address if any other interface is up.
  912.          */
  913. #if !defined(BSD) || (BSD < 199103)
  914.         if (ioctl(vs, SIOCGIFADDR, (char *)&ifreq) < 0) {
  915.             syslog(LOG_ERR, "get interface addr: %m");
  916.             continue;
  917.         }
  918. #endif
  919.         dprintf(1, (ddt, "considering [%s]\n",
  920.                 inet_ntoa(((struct sockaddr_in *)
  921.                        &ifreq.ifr_addr)->sin_addr)));
  922.         /* build datagram queue */
  923.         /* 
  924.          * look for an already existing source interface address.
  925.          * This happens mostly when reinitializing.  Also, if
  926.          * the machine has multiple point to point interfaces, then 
  927.          * the local address may appear more than once.
  928.          */
  929.         if (dqp = aIsUs(((struct sockaddr_in *)&ifreq.ifr_addr)
  930.                 ->sin_addr)) {
  931.             dprintf(1, (ddt,
  932.                     "dup interface address %s on %s\n",
  933.                     inet_ntoa(((struct sockaddr_in *)
  934.                            &ifreq.ifr_addr)->sin_addr),
  935.                     ifreq.ifr_name));
  936.             dqp->dq_gen = my_generation;
  937.             continue;
  938.         }
  939.  
  940.         /*
  941.          * Skip over address 0.0.0.0 since this will conflict
  942.          * with binding to wildcard address later.  Interfaces
  943.          * which are not completely configured can have this addr.
  944.          */
  945.         if (((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr
  946.             == 0x00000000) {    /* XXX */
  947.             dprintf(1, (ddt, "skipping address 0.0.0.0 on %s\n",
  948.                     ifreq.ifr_name));
  949.             continue;
  950.         }
  951.         if ((dqp = (struct qdatagram *)
  952.                calloc(1, sizeof(struct qdatagram))
  953.              ) == NULL) {
  954.             syslog(LOG_ERR, "getnetconf: malloc: %m");
  955.             exit(12);
  956.         }
  957.         dqp->dq_next = datagramq;
  958.         datagramq = dqp;
  959.         dqp->dq_addr = ((struct sockaddr_in *)
  960.                 &ifreq.ifr_addr)->sin_addr;
  961.         dqp->dq_gen = my_generation;
  962.         opensocket(dqp);
  963.         dprintf(1, (ddt, "listening [%s]\n",
  964.                 inet_ntoa(((struct sockaddr_in *)
  965.                        &ifreq.ifr_addr)->sin_addr)));
  966.  
  967.         /*
  968.          * Add interface to list of directly-attached (sub)nets
  969.          * for use in sorting addresses.
  970.          */
  971.         if (ntp == NULL) {
  972.             ntp = (struct netinfo *)malloc(sizeof(struct netinfo));
  973.         }
  974.         ntp->my_addr = ((struct sockaddr_in *)
  975.                 &ifreq.ifr_addr)->sin_addr;
  976. #ifdef SIOCGIFNETMASK
  977.         if (ioctl(vs, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
  978.             syslog(LOG_ERR, "get netmask: %m");
  979.             ntp->mask = net_mask(ntp->my_addr);
  980.         } else
  981.             ntp->mask = ((struct sockaddr_in *)
  982.                 &ifreq.ifr_addr)->sin_addr.s_addr;
  983. #else
  984.         /* 4.2 does not support subnets */
  985.         ntp->mask = net_mask(ntp->my_addr);
  986. #endif
  987.         if (ioctl(vs, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
  988.             syslog(LOG_ERR, "get interface flags: %m");
  989.             continue;
  990.         }
  991. #ifdef IFF_LOOPBACK
  992.         if (ifreq.ifr_flags & IFF_LOOPBACK)
  993. #else
  994.         /* test against 127.0.0.1 (yuck!!) */
  995.         if (ntp->my_addr.s_addr == inet_addr("127.0.0.1"))  /* XXX */
  996. #endif
  997.         {
  998.             if (netloop.my_addr.s_addr == 0) {
  999.                 netloop.my_addr = ntp->my_addr;
  1000.                 netloop.mask = 0xffffffff;
  1001.                 netloop.addr = ntp->my_addr.s_addr;
  1002.                 dprintf(1, (ddt, "loopback address: x%lx\n",
  1003.                         netloop.my_addr.s_addr));
  1004.             }
  1005.             continue;
  1006.         } else if ((ifreq.ifr_flags & IFF_POINTOPOINT)) {
  1007.             if (ioctl(vs, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
  1008.                 syslog(LOG_ERR, "get dst addr: %m");
  1009.                 continue;
  1010.             }
  1011.             ntp->mask = 0xffffffff;
  1012.             ntp->addr = ((struct sockaddr_in *)
  1013.                      &ifreq.ifr_addr)->sin_addr.s_addr;
  1014.         } else {
  1015.             ntp->addr = ntp->mask & ntp->my_addr.s_addr;
  1016.         }
  1017.         /*
  1018.          * Place on end of list of locally-attached (sub)nets,
  1019.          * but before logical nets for subnetted nets.
  1020.          */
  1021.         ntp->next = *elocal;
  1022.         *elocal = ntp;
  1023.         if (elocal == enettab)
  1024.             enettab = &ntp->next;
  1025.         elocal = &ntp->next;
  1026.         ntp = NULL;
  1027.     }
  1028.     if (ntp)
  1029.         free((char *)ntp);
  1030.  
  1031.     /*
  1032.      * now go through the datagramq and delete anything that
  1033.      * does not have the current generation number.  this is
  1034.      * how we catch interfaces that go away or change their
  1035.      * addresses.  note that 0.0.0.0 is the wildcard element
  1036.      * and should never be deleted by this code.
  1037.      *
  1038.      * XXX - need to update enettab/elocal as well.
  1039.      */
  1040.     dqflush(my_generation);
  1041.  
  1042.     /*
  1043.      * Create separate qdatagram structure for socket
  1044.      * wildcard address.
  1045.      */
  1046.     if (first) {
  1047.         if (!(dqp = (struct qdatagram *)calloc(1, sizeof(*dqp)))) {
  1048.             syslog(LOG_ERR, "getnetconf: malloc: %m");
  1049.             exit(12);
  1050.         }
  1051.         dqp->dq_next = datagramq;
  1052.         datagramq = dqp;
  1053.         dqp->dq_addr.s_addr = INADDR_ANY;
  1054.         opensocket(dqp);
  1055.         ds = dqp->dq_dfd;
  1056.     }
  1057.  
  1058.     /*
  1059.      * Compute logical networks to which we're connected
  1060.      * based on attached subnets;
  1061.      * used for sorting based on network configuration.
  1062.      */
  1063.     for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
  1064.         nm = net_mask(ntp->my_addr);
  1065.         if (nm != ntp->mask) {
  1066.             if (findnetinfo(ntp->my_addr))
  1067.                 continue;
  1068.             ontp = (struct netinfo *)
  1069.                    malloc(sizeof(struct netinfo));
  1070.             if (ontp == NULL) {
  1071.                 syslog(LOG_ERR, "getnetconf: malloc: %m");
  1072.                 exit(12);
  1073.             }
  1074.             ontp->my_addr = ntp->my_addr;
  1075.             ontp->mask = nm;
  1076.             ontp->addr = ontp->my_addr.s_addr & nm;
  1077.             ontp->next = *enettab;
  1078.             *enettab = ontp;
  1079.             enettab = &ontp->next;
  1080.         }
  1081.     }
  1082.     first = 0;
  1083. }
  1084.  
  1085. /*
  1086.  * Find netinfo structure for logical network implied by address "addr",
  1087.  * if it's on list of local/favored networks.
  1088.  */
  1089. struct netinfo *
  1090. findnetinfo(addr)
  1091.     struct in_addr addr;
  1092. {
  1093.     register struct netinfo *ntp;
  1094.     u_int32_t net, mask;
  1095.  
  1096.     mask = net_mask(addr);
  1097.     net = addr.s_addr & mask;
  1098.     for (ntp = nettab; ntp != NULL; ntp = ntp->next)
  1099.         if (ntp->addr == net && ntp->mask == mask)
  1100.             return (ntp);
  1101.     return ((struct netinfo *) NULL);
  1102. }
  1103.  
  1104. #ifdef DEBUG
  1105. static void
  1106. printnetinfo(ntp)
  1107.     register struct netinfo *ntp;
  1108. {
  1109.     for ( ; ntp != NULL; ntp = ntp->next) {
  1110.         fprintf(ddt,"addr x%lx mask x%lx", ntp->addr, ntp->mask);
  1111.         fprintf(ddt," my_addr x%lx", ntp->my_addr.s_addr);
  1112.         fprintf(ddt," %s\n", inet_ntoa(ntp->my_addr));
  1113.     }
  1114. }
  1115. #endif
  1116.  
  1117. static void
  1118. opensocket(dqp)
  1119.     register struct qdatagram *dqp;
  1120. {
  1121.     int n, m;
  1122.     int on = 1;
  1123.  
  1124.     /*
  1125.      * Open datagram sockets bound to interface address.
  1126.      */
  1127.     if ((dqp->dq_dfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  1128.         syslog(LOG_ERR, "socket(SOCK_DGRAM): %m - exiting");
  1129.         exit(1);
  1130.     }    
  1131.     dprintf(1, (ddt, "dqp->dq_addr %s d_dfd %d\n",
  1132.             inet_ntoa(dqp->dq_addr), dqp->dq_dfd));
  1133.     if (setsockopt(dqp->dq_dfd, SOL_SOCKET, SO_REUSEADDR,
  1134.         (char *)&on, sizeof(on)) != 0)
  1135.     {
  1136.         syslog(LOG_ERR, "setsockopt(dqp->dq_dfd, reuseaddr): %m");
  1137.         /* XXX press on regardless, this is not too serious. */
  1138.     }
  1139. #ifdef SO_RCVBUF
  1140.     m = sizeof(n);
  1141.     if ((getsockopt(dqp->dq_dfd, SOL_SOCKET, SO_RCVBUF, &n, &m) >= 0)
  1142.         && (m == sizeof(n))
  1143.         && (n < rbufsize)) {
  1144.         (void) setsockopt(dqp->dq_dfd, SOL_SOCKET, SO_RCVBUF,
  1145.                   (char *)&rbufsize, sizeof(rbufsize));
  1146.     }
  1147. #endif /* SO_RCVBUF */
  1148.     if ((n = fcntl(dqp->dq_dfd, F_GETFL, 0)) < 0) {
  1149.         syslog(LOG_ERR, "fcntl(dfd, F_GETFL): %m");
  1150.         /* XXX press on regardless, but this really is a problem. */
  1151.     } else if (fcntl(dqp->dq_dfd, F_SETFL, n|PORT_NONBLOCK) != 0) {
  1152.         syslog(LOG_ERR, "fcntl(dqp->dq_dfd, non-blocking): %m");
  1153.         /* XXX press on regardless, but this really is a problem. */
  1154.     }
  1155.     /*
  1156.      *   NOTE: Some versions of SunOS have problems with the following
  1157.      *   call to bind.  Bind still seems to function on these systems
  1158.      *   if you comment out the exit inside the if.  This may cause
  1159.      *   Suns with multiple interfaces to reply strangely.
  1160.      */
  1161.     nsaddr.sin_addr = dqp->dq_addr;
  1162.     if (bind(dqp->dq_dfd, (struct sockaddr *)&nsaddr, sizeof(nsaddr))) {
  1163.         syslog(LOG_ERR, "bind(dfd=%d, [%s].%d): %m - exiting",
  1164.             dqp->dq_dfd, inet_ntoa(nsaddr.sin_addr),
  1165.             ntohs(nsaddr.sin_port));
  1166. #if !defined(sun)
  1167.         exit(1);
  1168. #endif
  1169.     }
  1170. }
  1171.  
  1172. /*
  1173. ** Set flag saying to reload database upon receiving SIGHUP.
  1174. ** Must make sure that someone isn't walking through a data
  1175. ** structure at the time.
  1176. */
  1177.  
  1178. static SIG_FN
  1179. onhup()
  1180. {
  1181.     int save_errno = errno;
  1182. #if defined(SYSV)
  1183.     (void)signal(SIGHUP, onhup);
  1184. #endif /* SYSV */
  1185.     needreload = 1;
  1186.     errno = save_errno;
  1187. }
  1188.  
  1189. /*
  1190. ** Set flag saying to call ns_maint()
  1191. ** Must make sure that someone isn't walking through a data
  1192. ** structure at the time.
  1193. */
  1194.  
  1195. static SIG_FN
  1196. maint_alarm()
  1197. {
  1198.     int save_errno = errno;
  1199. #if defined(SYSV)
  1200.     (void)signal(SIGALRM, maint_alarm);
  1201. #endif /* SYSV */
  1202.     needmaint = 1;
  1203.     errno = save_errno;
  1204. }
  1205.  
  1206.  
  1207. #ifdef ALLOW_UPDATES
  1208. /*
  1209.  * Signal handler to schedule shutdown.  Just set flag, to ensure a consistent
  1210.  * state during dump.
  1211.  */
  1212. static SIG_FN
  1213. onintr()
  1214. {
  1215.         needToExit = 1;
  1216. }
  1217. #endif /* ALLOW_UPDATES */
  1218.  
  1219. /*
  1220.  * Signal handler to schedule a data base dump.  Do this instead of dumping the
  1221.  * data base immediately, to avoid seeing it in a possibly inconsistent state
  1222.  * (due to updates), and to avoid long disk I/O delays at signal-handler
  1223.  * level
  1224.  */
  1225. static SIG_FN
  1226. setdumpflg()
  1227. {
  1228.     int save_errno = errno;
  1229. #if defined(SYSV)
  1230.     (void)signal(SIGINT, setdumpflg);
  1231. #endif /* SYSV */
  1232.         needToDoadump = 1;
  1233.     errno = save_errno;
  1234. }
  1235.  
  1236. /*
  1237. ** Turn on or off debuging by open or closeing the debug file
  1238. */
  1239.  
  1240. static void
  1241. setdebug(code)
  1242.     int code;
  1243. {
  1244. #if defined(lint) && !defined(DEBUG)
  1245.     code = code;
  1246. #endif
  1247. #ifdef DEBUG
  1248.  
  1249.     if (code) {
  1250.         int n;
  1251.  
  1252.         ddt = freopen(debugfile, "w+", stderr);
  1253.         if ( ddt == NULL) {
  1254.             syslog(LOG_WARNING, "can't open debug file %s: %m",
  1255.                 debugfile);
  1256.             debug = 0;
  1257.         } else {
  1258. #if defined(SYSV)
  1259.             setvbuf(ddt, NULL, _IOLBF, BUFSIZ);
  1260. #else
  1261.             setlinebuf(ddt);
  1262. #endif
  1263.             if ((n = fcntl(fileno(ddt), F_GETFL, 0)) < 0) {
  1264.                 syslog(LOG_WARNING,
  1265.                        "fcntl(ddt, F_GETFL): %m");
  1266.             } else {
  1267.                 (void) fcntl(fileno(ddt), F_SETFL, n|O_APPEND);
  1268.             }
  1269.         }
  1270.     } else
  1271.         debug = 0;
  1272.         /* delay closing ddt, we might interrupt someone */
  1273. #endif
  1274. }
  1275.  
  1276. /*
  1277. ** Catch a special signal and set debug level.
  1278. **
  1279. **  If debuging is off then turn on debuging else increment the level.
  1280. **
  1281. ** Handy for looking in on long running name servers.
  1282. */
  1283.  
  1284. static SIG_FN
  1285. setIncrDbgFlg()
  1286. {
  1287.     int save_errno = errno;
  1288. #if defined(SYSV)
  1289.     (void)signal(SIGUSR1, setIncrDbgFlg);
  1290. #endif /* SYSV */
  1291. #ifdef DEBUG
  1292.     if (debug == 0) {
  1293.         debug++;
  1294.         setdebug(1);
  1295.     } else {
  1296.         debug++;
  1297.     }
  1298.     if (debug)
  1299.         fprintf(ddt, "Debug turned ON, Level %d\n", debug);
  1300. #endif
  1301.     errno = save_errno;
  1302. }
  1303.  
  1304. /*
  1305. ** Catch a special signal to turn off debugging
  1306. */
  1307.  
  1308. static SIG_FN
  1309. setNoDbgFlg()
  1310. {
  1311.     int save_errno = errno;
  1312. #if defined(SYSV)
  1313.     (void)signal(SIGUSR2, setNoDbgFlg);
  1314. #endif /* SYSV */
  1315.     setdebug(0);
  1316.     errno = save_errno;
  1317. }
  1318.  
  1319. #if defined(QRYLOG) && defined(SIGWINCH)
  1320. /*
  1321. ** Set flag for query logging
  1322. */
  1323. static SIG_FN
  1324. setQrylogFlg()
  1325. {
  1326.     int save_errno = errno;
  1327. #if defined(SYSV)
  1328.     (void)signal(SIGWINCH, setQrylogFlg);
  1329. #endif /* SYSV */
  1330.     qrylog = !qrylog;
  1331.     syslog(LOG_NOTICE, "query log %s\n", qrylog ?"on" :"off");
  1332.     errno = save_errno;
  1333. }
  1334. #endif /*QRYLOG && SIGWINCH*/
  1335.  
  1336. /*
  1337. ** Set flag for statistics dump
  1338. */
  1339. static SIG_FN
  1340. setstatsflg()
  1341. {
  1342.     int save_errno = errno;
  1343. #if defined(SYSV)
  1344.     (void)signal(SIGIOT, setstatsflg);
  1345. #endif /* SYSV */
  1346.     needStatsDump = 1;
  1347.     errno = save_errno;
  1348. }
  1349.  
  1350. static SIG_FN
  1351. setchkptflg()
  1352. {
  1353.     int save_errno = errno;
  1354. #if defined(SYSV)
  1355.     (void)signal(SIGQUIT, setchkptflg);
  1356. #endif /* SYSV */
  1357.     needToChkpt = 1;
  1358.     errno = save_errno;
  1359. }
  1360.  
  1361. /*
  1362. ** Catch a special signal SIGSYS
  1363. **
  1364. **  this is setup to fork and exit to drop to /usr/tmp/gmon.out
  1365. **   and keep the server running
  1366. */
  1367.  
  1368. #ifdef SIGSYS
  1369. static SIG_FN
  1370. sigprof()
  1371. {
  1372.     int save_errno = errno;
  1373. #if defined(SYSV)
  1374.     (void)signal(SIGSYS, sigprof);
  1375. #endif /* SYSV */
  1376.     dprintf(1, (ddt, "sigprof()\n"));
  1377.     if (fork() == 0)
  1378.     {
  1379.         (void) chdir(_PATH_TMPDIR);
  1380.         exit(1);
  1381.     }
  1382.     errno = save_errno;
  1383. }
  1384. #endif /* SIGSYS */
  1385.  
  1386. /*
  1387. ** Routines for managing stream queue
  1388. */
  1389.  
  1390. static struct qstream *
  1391. sqadd()
  1392. {
  1393.     register struct qstream *sqp;
  1394.  
  1395.     if (!(sqp = (struct qstream *)calloc(1, sizeof(struct qstream)))) {
  1396.         syslog(LOG_ERR, "sqadd: calloc: %m");
  1397.         return (QSTREAM_NULL);
  1398.     }
  1399.     dprintf(3, (ddt, "sqadd(x%x)\n", sqp));
  1400.  
  1401.     sqp->s_next = streamq;
  1402.     streamq = sqp;
  1403.     return (sqp);
  1404. }
  1405.  
  1406. /* sqrm(qp)
  1407.  *    remove stream queue structure `qp'.
  1408.  *    no current queries may refer to this stream when it is removed.
  1409.  * side effects:
  1410.  *    memory is deallocated.  sockets are closed.  lists are relinked.
  1411.  */
  1412. void
  1413. sqrm(qp)
  1414.     register struct qstream *qp;
  1415. {
  1416.     register struct qstream *qsp;
  1417.  
  1418.     dprintf(2, (ddt, "sqrm(%#x, %d ) rfcnt=%d\n",
  1419.             qp, qp->s_rfd, qp->s_refcnt));
  1420.  
  1421.     if (qp->s_bufsize != 0)
  1422.         free(qp->s_buf);
  1423.     FD_CLR(qp->s_rfd, &mask);
  1424.     (void) my_close(qp->s_rfd);
  1425.     if (qp == streamq) {
  1426.         streamq = qp->s_next;
  1427.     } else {
  1428.         for (qsp = streamq;
  1429.              qsp && (qsp->s_next != qp);
  1430.              qsp = qsp->s_next)
  1431.             ;
  1432.         if (qsp) {
  1433.             qsp->s_next = qp->s_next;
  1434.         }
  1435.     }
  1436.     free((char *)qp);
  1437. }
  1438.  
  1439. /* void
  1440.  * sqflush(allbut)
  1441.  *    call sqrm() on all open streams except `allbut'
  1442.  * side effects:
  1443.  *    global list `streamq' modified
  1444.  * idiocy:
  1445.  *    is N^2 due to the scan inside of sqrm()
  1446.  */
  1447. void
  1448. sqflush(allbut)
  1449.     register struct qstream *allbut;
  1450. {
  1451.     register struct qstream *sp, *spnext;
  1452.  
  1453.     for (sp = streamq; sp != NULL; sp = spnext) {
  1454.         spnext = sp->s_next;
  1455.         if (sp != allbut)
  1456.             sqrm(sp);
  1457.     }
  1458. }
  1459.  
  1460. /* void
  1461.  * dqflush(gen)
  1462.  *    close/deallocate all the udp sockets, unless `gen' != (time_t)0
  1463.  *    in which case all those not matching this generation will
  1464.  *    be deleted except the 0.0.0.0 element, and syslog() will
  1465.  *    be called whenever something is deleted.
  1466.  * side effects:
  1467.  *    global list `datagramq' is modified
  1468.  */
  1469. void
  1470. dqflush(gen)
  1471.     register time_t gen;
  1472. {
  1473.     register struct qdatagram *dqp, *pqp, *nqp;
  1474.  
  1475.     for (pqp = NULL, dqp = datagramq;
  1476.          dqp != NULL;
  1477.          pqp = dqp, dqp = nqp) {
  1478.         nqp = dqp->dq_next;
  1479.         if (gen != (time_t)0) {
  1480.             if (dqp->dq_addr.s_addr == INADDR_ANY ||
  1481.                 dqp->dq_gen == gen)
  1482.                 continue;
  1483.             syslog(LOG_CRIT, "interface [%s] missing; deleting",
  1484.                    inet_ntoa(dqp->dq_addr));
  1485.         }
  1486.         if (pqp != NULL)
  1487.             pqp->dq_next = dqp->dq_next;
  1488.         else
  1489.             datagramq = dqp->dq_next;
  1490.         free(dqp);
  1491.     }
  1492. }
  1493.  
  1494. /* int
  1495.  * sq_here(sp)
  1496.  *    determine whether stream 'sp' is still on the streamq
  1497.  * return:
  1498.  *    boolean: is it here?
  1499.  */
  1500. static int
  1501. sq_here(sp)
  1502.     register struct qstream *sp;
  1503. {
  1504.     register struct qstream *t;
  1505.  
  1506.     for (t = streamq;  t != NULL;  t = t->s_next)
  1507.         if (t == sp)
  1508.             return (1);
  1509.     return (0);
  1510. }
  1511.  
  1512. /*
  1513.  * Initiate query on stream;
  1514.  * mark as referenced and stop selecting for input.
  1515.  */
  1516. static void
  1517. sq_query(sp)
  1518.     register struct qstream *sp;
  1519. {
  1520.     sp->s_refcnt++;
  1521.     FD_CLR(sp->s_rfd, &mask);
  1522. }
  1523.  
  1524. /*
  1525.  * Note that the current request on a stream has completed,
  1526.  * and that we should continue looking for requests on the stream.
  1527.  */
  1528. void
  1529. sq_done(sp)
  1530.     register struct qstream *sp;
  1531. {
  1532.  
  1533.     sp->s_refcnt = 0;
  1534.     sp->s_time = tt.tv_sec;
  1535.     FD_SET(sp->s_rfd, &mask);
  1536. }
  1537.  
  1538. void
  1539. ns_setproctitle(a, s)
  1540.     char *a;
  1541.     int s;
  1542. {
  1543.     int size;
  1544.     register char *cp;
  1545.     struct sockaddr_in sin;
  1546.     char buf[80];
  1547.  
  1548.     cp = Argv[0];
  1549.     size = sizeof(sin);
  1550.     if (getpeername(s, (struct sockaddr *)&sin, &size) == 0)
  1551.         (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr));
  1552.     else {
  1553.         syslog(LOG_DEBUG, "getpeername: %m");
  1554.         (void) sprintf(buf, "-%s", a);
  1555.     }
  1556.     (void) strncpy(cp, buf, LastArg - cp);
  1557.     cp += strlen(cp);
  1558.     while (cp < LastArg)
  1559.         *cp++ = ' ';
  1560. }
  1561.  
  1562. u_int32_t
  1563. net_mask(in)
  1564.     struct in_addr in;
  1565. {
  1566.     register u_int32_t i = ntohl(in.s_addr);
  1567.  
  1568.     if (IN_CLASSA(i))
  1569.         return (htonl(IN_CLASSA_NET));
  1570.     else if (IN_CLASSB(i))
  1571.         return (htonl(IN_CLASSB_NET));
  1572.     else
  1573.         return (htonl(IN_CLASSC_NET));
  1574. }
  1575.  
  1576. #if defined(BSD43_BSD43_NFS)
  1577. /* junk needed for old Sun NFS licensees */
  1578. #undef dn_skipname
  1579. extern char *dn_skipname();
  1580. char *(*hack_skipname)() = dn_skipname;
  1581. #endif
  1582.