1: /*
   2:  * Copyright (c) 1986 Regents of the University of California.
   3:  * All rights reserved.
   4:  *
   5:  * Redistribution and use in source and binary forms are permitted
   6:  * provided that this notice is preserved and that due credit is given
   7:  * to the University of California at Berkeley. The name of the University
   8:  * may not be used to endorse or promote products derived from this
   9:  * software without specific prior written permission. This software
  10:  * is provided ``as is'' without express or implied warranty.
  11:  */
  12: 
  13: #if !defined(lint) && defined(DOSCCS)
  14: char copyright[] =
  15: "@(#) Copyright (c) 1986 Regents of the University of California.\n\
  16:  All rights reserved.\n";
  17: 
  18: static char sccsid[] = "@(#)ns_main.c	4.30.1 (2.11BSD) 1996/11/16";
  19: #endif /* not lint */
  20: 
  21: /*
  22: * Internet Name server (see rfc883 & others).
  23: */
  24: 
  25: #include <sys/param.h>
  26: #if defined(SYSV)
  27: #include <fcntl.h>
  28: #endif SYSV
  29: #include <sys/file.h>
  30: #include <sys/time.h>
  31: #if !defined(SYSV)
  32: #include <sys/wait.h>
  33: #endif !SYSV
  34: #include <sys/resource.h>
  35: #include <sys/ioctl.h>
  36: #include <sys/socket.h>
  37: #include <netinet/in.h>
  38: #include <net/if.h>
  39: #include <stdio.h>
  40: #include <syslog.h>
  41: #include <errno.h>
  42: #include <signal.h>
  43: #include <netdb.h>
  44: #include <arpa/nameser.h>
  45: #include <arpa/inet.h>
  46: #include <resolv.h>
  47: #undef nsaddr               /* XXX */
  48: #include "ns.h"
  49: #include "db.h"
  50: 
  51: #ifdef BOOTFILE             /* default boot file */
  52: char    *bootfile = BOOTFILE;
  53: #else
  54: char    *bootfile = "/etc/named.boot";
  55: #endif
  56: 
  57: #ifdef DEBUGFILE            /* default debug output file */
  58: char    *debugfile = DEBUGFILE;
  59: #else
  60: char    *debugfile = "/usr/tmp/named.run";
  61: #endif
  62: 
  63: #ifdef PIDFILE              /* file to store current named PID */
  64: char    *PidFile = PIDFILE;
  65: #else
  66: char    *PidFile = "/var/run/named.pid";
  67: #endif
  68: 
  69: #ifndef FD_SET
  70: #define NFDBITS     32
  71: #define FD_SETSIZE  32
  72: #define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
  73: #define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
  74: #define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
  75: #define FD_ZERO(p)  bzero((char *)(p), sizeof(*(p)))
  76: #endif
  77: 
  78: FILE    *fp;                /* file descriptor for pid file */
  79: 
  80: #ifdef DEBUG
  81: FILE    *ddt;
  82: #endif
  83: 
  84: int debug = 0;          /* debugging flag */
  85: int ds;             /* datagram socket */
  86: int read_interrupted = 0;       /* flag for read timer */
  87: int needreload = 0;         /* received SIGHUP, need to reload db */
  88: int needmaint = 0;          /* need to call ns_maint()*/
  89: int     needToDoadump = 0;              /* need to dump database */
  90: int     needToChkpt = 0;            /* need to checkpoint cache */
  91: int needStatsDump = 0;      /* need to dump statistics */
  92: #ifdef ALLOW_UPDATES
  93: int     needToExit = 0;                 /* need to exit (may need to doadump
  94: 					 * first, if database has changed since
  95: 					 * it was last dumped/booted). Gets
  96: 					 * set by shutdown signal handler
  97: 					 *  (onintr)
  98: 					 */
  99: #endif ALLOW_UPDATES
 100: int priming = 0;            /* is cache being primed */
 101: 
 102: #ifdef SO_RCVBUF
 103: int rbufsize = 8 * 1024;        /* UDP recive buffer size */
 104: #endif
 105: 
 106: struct  qstream *streamq = QSTREAM_NULL; /* list of open streams */
 107: struct  qdatagram *datagramq = QDATAGRAM_NULL; /* list of datagram interfaces */
 108: struct  qdatagram *dqp, *sqp;
 109: struct  sockaddr_in nsaddr;
 110: struct  timeval tt;
 111: struct  netinfo *nettab = NULL;
 112: struct  netinfo *fnettab = NULL;
 113: struct  netinfo *onettab = NULL;
 114: struct  netinfo netloop;
 115: short   ns_port;
 116: struct  sockaddr_in from_addr;      /* Source addr of last packet */
 117: int from_len;           /* Source addr size of last packet */
 118: time_t  boottime, resettime;        /* Used by ns_stats */
 119: fd_set  mask;               /* select mask of open descriptors */
 120: u_long  net_mask();
 121: 
 122: char        **Argv = NULL;      /* pointer to argument vector */
 123: char        *LastArg = NULL;    /* end of argv */
 124: 
 125: extern int errno;
 126: 
 127: #if defined(SYSV)
 128: getdtablesize()
 129: {
 130:     return(FD_SETSIZE);
 131: }
 132: #endif SYSV
 133: 
 134: main(argc, argv, envp)
 135:     int argc;
 136:     char *argv[], *envp[];
 137: {
 138:     register int n, udpcnt;
 139:     register char *arg;
 140:     register struct qstream *sp;
 141:     int vs;
 142:     int nfds;
 143:     int on = 1;
 144:     int rfd, size;
 145:     u_long lasttime, maxctime;
 146:     u_long nnn, nm;
 147:     char buf[BUFSIZ];
 148: 
 149:     fd_set tmpmask;
 150: 
 151:     struct timeval t, *tp;
 152:     struct qstream *candidate = QSTREAM_NULL;
 153:     struct ifconf ifc;
 154:     struct ifreq ifreq, *ifr;
 155:     struct netinfo *ntp;
 156:     struct netinfo *ntip;
 157:     struct netinfo *ontp;
 158:     struct netinfo *ontip;
 159:     extern int onintr(), maint_alarm(), reapchild(), setdumpflg(), onhup();
 160:     extern int setIncrDbgFlg(), setNoDbgFlg(), sigprof();
 161:     extern int setchkptflg(), setstatsflg();
 162:     extern struct qstream *sqadd();
 163:     extern struct qinfo *qhead;
 164:     extern char Version[];
 165: 
 166:     ns_port = htons(NAMESERVER_PORT);
 167:     _res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE);
 168: 
 169:     /*
 170: 	**  Save start and extent of argv for setproctitle.
 171: 	*/
 172: 
 173:     Argv = argv;
 174:     if (envp == 0 || *envp == 0)
 175:         envp = argv;
 176:     while (*envp)
 177:         envp++;
 178:     LastArg = envp[-1] + strlen(envp[-1]);
 179: 
 180:     (void) umask(022);
 181:     while (--argc > 0) {
 182:         arg = *++argv;
 183:         if (*arg == '-') {
 184:             while (*++arg)
 185:                 switch (*arg) {
 186:                 case 'b':
 187:                     if (--argc <= 0)
 188:                         usage();
 189:                     bootfile = *++argv;
 190:                     break;
 191: 
 192:                 case 'd':
 193:                     ++argv;
 194: 
 195:                     if (*argv != 0) {
 196:                         if (**argv == '-') {
 197:                         argv--;
 198:                         break;
 199:                         }
 200:                         debug = atoi(*argv);
 201:                         --argc;
 202:                     }
 203:                     if (debug <= 0)
 204:                         debug = 1;
 205:                     setdebug(1);
 206:                     break;
 207: 
 208:                 case 'p':
 209:                     if (--argc <= 0)
 210:                         usage();
 211:                     ns_port = htons((u_short)atoi(*++argv));
 212:                     break;
 213: 
 214:                 default:
 215:                     usage();
 216:                 }
 217:         } else
 218:             bootfile = *argv;
 219:     }
 220: 
 221:     if (!debug) {
 222:         if (fork())
 223:             exit(0);
 224:         for (n = getdtablesize() - 1; n >= 0; n--)
 225:             (void) close(n);
 226:         (void) open("/dev/null", O_RDONLY);
 227:         (void) dup2(0, 1);
 228:         (void) dup2(0, 2);
 229:         n = open("/dev/tty", O_RDWR);
 230:         if (n > 0) {
 231: #ifndef SYSV
 232:             (void) ioctl(n, TIOCNOTTY, (char *)NULL);
 233: #else
 234:             setpgrp();
 235: #endif
 236:             (void) close(n);
 237:         }
 238:     }
 239: #ifdef DEBUG
 240:     else {
 241:         fprintf(ddt,"Debug turned ON, Level %d\n",debug);
 242:         fprintf(ddt,"Version = %s\t",Version);
 243:         fprintf(ddt,"bootfile = %s\n",bootfile);
 244:     }
 245: #endif
 246: 
 247: #ifdef LOG_DAEMON
 248:     openlog("named", LOG_PID|LOG_CONS|LOG_NDELAY, LOG_DAEMON);
 249: #else
 250:     openlog("named", LOG_PID);
 251: #endif
 252: 
 253:     /* tuck my process id away */
 254:     fp = fopen(PidFile, "w");
 255:     if (fp != NULL) {
 256:         fprintf(fp, "%d\n", getpid());
 257:         (void) fclose(fp);
 258:     }
 259:     syslog(LOG_NOTICE, "restarted\n");
 260: 
 261:     nsaddr.sin_family = AF_INET;
 262:     nsaddr.sin_addr.s_addr = INADDR_ANY;
 263:     nsaddr.sin_port = ns_port;
 264:     /*
 265: 	** Initialize and load database.
 266: 	*/
 267:     gettime(&tt);
 268:     buildservicelist();
 269:     buildprotolist();
 270:     ns_init(bootfile);
 271:     time(&boottime);
 272:     resettime = boottime;
 273: 
 274:     (void) signal(SIGALRM, maint_alarm);
 275:     (void) signal(SIGHUP, onhup);
 276: #if defined(SYSV)
 277:     (void) signal(SIGCLD, reapchild);
 278: #else
 279:     (void) signal(SIGCHLD, reapchild);
 280: #endif SYSV
 281:     (void) signal(SIGPIPE, SIG_IGN);
 282:     (void) signal(SIGSYS, sigprof);
 283:     (void) signal(SIGINT, setdumpflg);
 284:     (void) signal(SIGQUIT, setchkptflg);
 285:     (void) signal(SIGIOT, setstatsflg);
 286: 
 287: #ifdef ALLOW_UPDATES
 288:         /* Catch SIGTERM so we can dump the database upon shutdown if it
 289:            has changed since it was last dumped/booted */
 290:         (void) signal(SIGTERM, onintr);
 291: #endif ALLOW_UPDATES
 292: 
 293: #if defined(SIGUSR1) && defined(SIGUSR2)
 294:     (void) signal(SIGUSR1, setIncrDbgFlg);
 295:     (void) signal(SIGUSR2, setNoDbgFlg);
 296: #else   SIGUSR1&&SIGUSR2
 297:     (void) signal(SIGEMT, setIncrDbgFlg);
 298:     (void) signal(SIGFPE, setNoDbgFlg);
 299: #endif SIGUSR1&&SIGUSR2
 300: 
 301: #ifdef DEBUG
 302:     if (debug) {
 303:         fprintf(ddt,"database initialized\n");
 304:     }
 305: #endif
 306:     /*
 307: 	** Open stream port.
 308: 	*/
 309:     if ((vs = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
 310:         syslog(LOG_ERR, "socket(SOCK_STREAM): %m");
 311:         exit(1);
 312:     }
 313:     (void)setsockopt(vs, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
 314:     if (bind(vs, (struct sockaddr *)&nsaddr, sizeof(nsaddr))) {
 315:         syslog(LOG_ERR, "bind(vs, %s[%d]): %m",
 316:             inet_ntoa(nsaddr.sin_addr), ntohs(nsaddr.sin_port));
 317:         exit(1);
 318:     }
 319:     ifc.ifc_len = sizeof(buf);
 320:     ifc.ifc_buf = buf;
 321:     if (ioctl(vs, SIOCGIFCONF, (char *)&ifc) < 0) {
 322:         syslog(LOG_ERR, "get interface configuration: %m");
 323:         exit(1);
 324:     }
 325:     n = ifc.ifc_len/sizeof(struct ifreq);
 326:     ntp = NULL;
 327:     for (ifr = ifc.ifc_req; n > 0; n--, ifr++) {
 328:         int dup_addr;
 329: 
 330:         if (ifr->ifr_addr.sa_family != AF_INET)
 331:             continue;
 332:         ifreq = *ifr;
 333:         if (ioctl(vs, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
 334:             syslog(LOG_ERR, "get interface flags: %m");
 335:             continue;
 336:         }
 337:         if ((ifreq.ifr_flags & IFF_UP) == 0)
 338:             continue;
 339:         if (ioctl(vs, SIOCGIFADDR, (char *)&ifreq) < 0) {
 340:             syslog(LOG_ERR, "get interface addr: %m");
 341:             continue;
 342:         }
 343:         /* build datagram queue */
 344:         if ((dqp = (struct qdatagram *)calloc(1,
 345:             sizeof(struct qdatagram))) == NULL) {
 346: #ifdef DEBUG
 347:             if (debug >= 5)
 348:                 fprintf(ddt,"main: malloc error\n");
 349: #endif
 350:             syslog(LOG_ERR, "main: Out Of Memory");
 351:             exit(12);
 352:         }
 353:         dqp->dq_next = datagramq;
 354:         dqp->dq_addr = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
 355:         /*
 356: 		 * look for an already existing source interface address.  If
 357: 		 * the machine has multiple point to point interfaces, then
 358: 		 * the local address may appear more than once.
 359: 		 */
 360:         dup_addr = 0;
 361:         for (sqp=datagramq; sqp != NULL; sqp = sqp->dq_next)
 362:           if (dqp->dq_addr.s_addr == sqp->dq_addr.s_addr) {
 363:             dup_addr = 1;
 364:             break;
 365:           }
 366:         if (!dup_addr)
 367:               datagramq = dqp;
 368:         else {
 369: #ifdef DEBUG
 370:           if (debug)
 371:             fprintf(ddt, "main: dup interface address %s on %s\n",
 372:                 inet_ntoa(dqp->dq_addr), ifreq.ifr_name);
 373: #endif
 374:           free((char *) dqp);
 375:         }
 376: 
 377:         if (ntp == NULL)
 378:             ntp = (struct netinfo *)malloc(sizeof(struct netinfo));
 379:         ntp->my_addr =
 380:             ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
 381: #ifdef SIOCGIFNETMASK
 382:         if (ioctl(vs, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
 383:             syslog(LOG_ERR, "get netmask: %m");
 384:             continue;
 385:         }
 386:         ntp->mask = ((struct sockaddr_in *)
 387:             &ifreq.ifr_addr)->sin_addr.s_addr;
 388: #else
 389:         /* 4.2 does not support subnets */
 390:         ntp->mask = net_mask(ntp->my_addr);
 391: #endif
 392:         if (ioctl(vs, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
 393:             syslog(LOG_ERR, "get interface flags: %m");
 394:             continue;
 395:         }
 396: #ifdef IFF_LOOPBACK
 397:         if ((ifreq.ifr_flags & IFF_LOOPBACK))
 398: #else
 399:         /* test against 127.0.0.1 (yuck!!) */
 400:         if (ntp->my_addr.s_addr == htonl(0x7F000001))
 401: #endif
 402:         {
 403:             netloop.my_addr = ntp->my_addr;
 404:             netloop.mask = 0xffffffff;
 405:             netloop.net = ntp->my_addr.s_addr;
 406:             netloop.next = NULL;
 407: #ifdef DEBUG
 408:             if (debug)
 409:             fprintf(ddt,"loopback address: x%lx\n",
 410:                 netloop.my_addr.s_addr);
 411: #endif DEBUG
 412:             continue;
 413:         } else if ((ifreq.ifr_flags & IFF_POINTOPOINT)) {
 414:             if (ioctl(vs, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
 415:                     syslog(LOG_ERR, "get dst addr: %m");
 416:                     continue;
 417:             }
 418:             ntp->mask = 0xffffffff;
 419:             ntp->net = ((struct sockaddr_in *)
 420:                     &ifreq.ifr_addr)->sin_addr.s_addr;
 421:         } else {
 422:             ntp->net = ntp->mask & ntp->my_addr.s_addr;
 423:         }
 424:         ntp->next = NULL;
 425:         if (nettab == NULL)
 426:             nettab = ntip = ntp;
 427:         else {
 428:             ntip->next = ntp;
 429:             ntip = ntp;
 430:         }
 431:         ntp = NULL;
 432:     }
 433:     if (ntp)
 434:         (void) free((char *)ntp);
 435: 
 436:     /*
 437: 	 * Create separate qdatagram structure for socket
 438: 	 * wildcard address.
 439: 	 */
 440:     if ((dqp = (struct qdatagram *)calloc(1, sizeof(struct qdatagram)))
 441:          == NULL) {
 442: #ifdef DEBUG
 443:         if (debug >= 5)
 444:             fprintf(ddt,"main: malloc error\n");
 445: #endif
 446:         syslog(LOG_ERR, "main: Out Of Memory");
 447:         exit(12);
 448:     }
 449:     dqp->dq_next = datagramq;
 450:     datagramq = dqp;
 451:     dqp->dq_addr.s_addr = INADDR_ANY;
 452: 
 453:     /*
 454: 	 * Compute other networks for sorting based on network configuration
 455: 	 */
 456:     ontp = NULL;
 457:     for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
 458:         nm = net_mask(ntp->my_addr);
 459:         if (nm != ntp->mask) {
 460:             nnn = ntp->my_addr.s_addr & nm;
 461:             for (ontp=onettab; ontp != NULL; ontp=ontp->next) {
 462:                 if ((ontp->net == nnn) &&
 463:                     (ontp->mask == nm))
 464:                     goto outerloop;
 465:                 ontip = ontp;
 466:             }
 467:             ontp = (struct netinfo *)
 468:                 malloc(sizeof(struct netinfo));
 469:             ontp->net = nnn;
 470:             ontp->mask = nm;
 471:             ontp->my_addr = ntp->my_addr;
 472:             ontp->next = NULL;
 473:             if (onettab == NULL )
 474:                 onettab = ontp;
 475:             else
 476:                 ontip->next = ontp;
 477:         }
 478: outerloop:
 479:         ;
 480:     }
 481:     /*
 482: 	 * Merge sort list from network configuration
 483: 	 * with list we computed from network configuration
 484: 	 */
 485:     for (ntp = nettab; ntp != NULL; ntp = ntp->next){
 486:         if (ntp->next == NULL) {
 487:             ntp->next = onettab;
 488:             break;
 489:         }
 490:     }
 491:     /*
 492: 	 * Merge sort list from boot file with list from
 493: 	 * network configuration
 494: 	 */
 495:     for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
 496:         for (ontp = fnettab; ontp != NULL; ontp = ontp->next) {
 497:         if ((ontp->mask == ntp->mask) && (ontp->net == ntp->net)) {
 498:             if( fnettab == ontp )  {
 499:                 ontip = ontp;
 500:             fnettab = ontp->next;
 501:             free((char *)ontip);
 502:             break;
 503:             } else {
 504:             for (ontip = fnettab; ontip != NULL;ontip = ontip->next)
 505:                if (ontip->next == ontp) break;
 506:             ontip->next = ontp->next;
 507:             free((char *)ontp);
 508:             ontp = ontip;
 509:             break;
 510:             }
 511:         }
 512:         }
 513:         if (ntp->next == NULL)
 514:         break;
 515:     }
 516:     ntp->next = fnettab;
 517: #ifdef DEBUG
 518:     if (debug)
 519:         for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
 520:             fprintf(ddt,"net x%lx mask x%lx",
 521:                 ntohl(ntp->net), ntohl(ntp->mask));
 522:             fprintf(ddt," my_addr x%lx", ntohl(ntp->my_addr.s_addr));
 523:             fprintf(ddt," %s\n", inet_ntoa(ntp->my_addr));
 524:         }
 525: #endif DEBUG
 526:     (void) listen(vs, 5);
 527: 
 528:     /*
 529: 	 * Open datagram ports for each interface
 530: 	 * (the first is un-addressed datagram port).
 531: 	 */
 532:     for (dqp = datagramq; dqp != QDATAGRAM_NULL; dqp = dqp->dq_next) {
 533:         nsaddr.sin_addr = dqp->dq_addr;
 534:         if ((dqp->dq_dfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
 535:             syslog(LOG_ERR, "socket(SOCK_DGRAM): %m");
 536:             exit(1);
 537:         }
 538: #ifdef DEBUG
 539:         if (debug)
 540:             fprintf(ddt,"dqp->dq_addr %s d_dfd %d\n",
 541:                 inet_ntoa(dqp->dq_addr), dqp->dq_dfd);
 542: #endif DEBUG
 543:         (void)setsockopt(dqp->dq_dfd, SOL_SOCKET, SO_REUSEADDR,
 544:             (char *)&on, sizeof(on));
 545: #ifdef SO_RCVBUF
 546:         (void)setsockopt(dqp->dq_dfd, SOL_SOCKET, SO_RCVBUF,
 547:             (char *)&rbufsize, sizeof(rbufsize));
 548: #endif SO_RCVBUF
 549:         (void) fcntl(dqp->dq_dfd, F_SETFL, FNDELAY);
 550: /*
 551:  *   NOTE: Some versions of SunOS have problems with the following
 552:  *   call to bind.  Bind still seems to function on these systems
 553:  *   if you comment out the exit inside the if.  This may cause
 554:  *   Suns with multiple interfaces to reply strangely.
 555:  */
 556:         if (bind(dqp->dq_dfd, (struct sockaddr *)&nsaddr, sizeof(nsaddr))) {
 557:             syslog(LOG_ERR, "bind(dfd %d, %s[%d]): %m",
 558:                 dqp->dq_dfd, inet_ntoa(nsaddr.sin_addr),
 559:                 ntohs(nsaddr.sin_port));
 560: #if !defined(sun)
 561:             exit(1);
 562: #endif
 563:         }
 564:     }
 565:     ds = datagramq->dq_dfd;
 566: 
 567:     t.tv_usec = 0;
 568: 
 569: #ifdef DEBUG
 570:     if (debug)
 571:         fprintf(ddt,"Ready to answer queries.\n");
 572: #endif
 573:     prime_cache();
 574:     nfds = getdtablesize();       /* get the number of file descriptors */
 575:     if (nfds > FD_SETSIZE) {
 576:         nfds = FD_SETSIZE;  /* Bulletproofing */
 577:         syslog(LOG_ERR, "Return from getdtablesize() > FD_SETSIZE");
 578: #ifdef DEBUG
 579:         if (debug)
 580:               fprintf(ddt,"Return from getdtablesize() > FD_SETSIZE\n");
 581: #endif
 582:     }
 583:     FD_ZERO(&mask);
 584:     FD_SET(vs, &mask);
 585:     FD_SET(ds, &mask);
 586:     for (dqp = datagramq; dqp != QDATAGRAM_NULL; dqp = dqp->dq_next)
 587:         FD_SET(dqp->dq_dfd, &mask);
 588:     for (;;) {
 589: #ifdef ALLOW_UPDATES
 590:                 if (needToExit) {
 591:             struct zoneinfo *zp;
 592:             sigblock(~0L);   /*
 593: 					 * Block all blockable signals
 594: 					 * to ensure a consistant
 595: 					 * state during final dump
 596: 					 */
 597: #ifdef DEBUG
 598:             if (debug)
 599:                 fprintf(ddt, "Received shutdown signal\n");
 600: #endif DEBUG
 601:             for (zp = zones; zp < &zones[nzones]; zp++) {
 602:                 if (zp->hasChanged)
 603:                     zonedump(zp);
 604:                         }
 605:                         exit(0);
 606:                 }
 607: #endif ALLOW_UPDATES
 608:         if(needreload) {
 609:             needreload = 0;
 610:             db_reload();
 611:         }
 612: #ifdef STATS
 613:         if(needStatsDump) {
 614:             needStatsDump = 0;
 615:             ns_stats();
 616:         }
 617: #endif STATS
 618:         if(needmaint) {
 619:                         needmaint = 0;
 620:                         ns_maint();
 621:                 }
 622:             if(needToChkpt) {
 623:                         needToChkpt = 0;
 624:                         doachkpt();
 625:             }
 626:                 if(needToDoadump) {
 627:                         needToDoadump = 0;
 628:                         doadump();
 629:                 }
 630:         /*
 631: 		** Wait until a query arrives
 632: 		*/
 633:         if (retryqp != NULL) {
 634:             gettime(&tt);
 635:             t.tv_sec = (long) retryqp->q_time - tt.tv_sec;
 636:             if (t.tv_sec <= 0) {
 637:                 retry(retryqp);
 638:                 continue;
 639:             }
 640:             tp = &t;
 641:         } else
 642:             tp = NULL;
 643:         tmpmask = mask;
 644:         n = select(nfds, &tmpmask, (fd_set *)NULL, (fd_set *)NULL, tp);
 645:         if (n < 0) {
 646:             if (errno == EINTR)
 647:                 continue;
 648:             syslog(LOG_ERR, "select: %m");
 649: #ifdef DEBUG
 650:             if (debug)
 651:                 fprintf(ddt,"select error\n");
 652: #endif
 653:             ;
 654:         }
 655:         if (n == 0)
 656:             continue;
 657: 
 658:         for (dqp = datagramq; dqp != QDATAGRAM_NULL;
 659:             dqp = dqp->dq_next) {
 660:             if (FD_ISSET(dqp->dq_dfd, &tmpmask))
 661:                 for(udpcnt = 0; udpcnt < 25; udpcnt++) {
 662:                 from_len = sizeof(from_addr);
 663:                 if ((n = recvfrom(dqp->dq_dfd, buf, sizeof(buf), 0,
 664:                 (struct sockaddr *)&from_addr, &from_len)) < 0)
 665:                 {
 666:                 if ((n == -1) && (errno == EWOULDBLOCK))
 667:                     break;
 668:                 syslog(LOG_WARNING, "recvfrom: %m");
 669:                 break;
 670:                 }
 671: #ifdef STATS
 672:                 stats[S_INPKTS].cnt++;
 673: #endif
 674: #ifdef DEBUG
 675:                 if (debug)
 676:                 fprintf(ddt,
 677:                   "\ndatagram from %s port %d, fd %d, len %d\n",
 678:                     inet_ntoa(from_addr.sin_addr),
 679:                     ntohs(from_addr.sin_port), ds, n);
 680:                 if (debug >= 10)
 681:                 fp_query(buf, ddt);
 682: #endif
 683:                 /*
 684: 			     * Consult database to get the answer.
 685: 			     */
 686:                 gettime(&tt);
 687:                 ns_req(buf, n, PACKETSZ, QSTREAM_NULL, &from_addr,
 688:                     dqp->dq_dfd);
 689:                 }
 690:         }
 691:         /*
 692: 		** Process stream connection
 693: 		*/
 694:         if (FD_ISSET(vs, &tmpmask)) {
 695:             from_len = sizeof(from_addr);
 696:             rfd = accept(vs, (struct sockaddr *)&from_addr, &from_len);
 697:             gettime(&tt);
 698:             if (rfd < 0 && errno == EMFILE && streamq != NULL) {
 699:                 maxctime = 0;
 700:                 candidate = QSTREAM_NULL;
 701:                 for (sp = streamq; sp != QSTREAM_NULL;
 702:                    sp = sp->s_next) {
 703:                     if (sp->s_refcnt != 0)
 704:                         continue;
 705:                     lasttime = tt.tv_sec - sp->s_time;
 706:                     if (lasttime >= 900)
 707:                         sqrm(sp, &mask);
 708:                     else if (lasttime > maxctime) {
 709:                         candidate = sp;
 710:                         maxctime = lasttime;
 711:                     }
 712:                 }
 713:                 rfd = accept(vs, (struct sockaddr *)&from_addr, &from_len);
 714:                 if ((rfd < 0) && (errno == EMFILE) &&
 715:                     candidate != QSTREAM_NULL) {
 716:                     sqrm(candidate, &mask);
 717:                     rfd = accept(vs, (struct sockaddr *)&from_addr, &from_len);
 718:                 }
 719:             }
 720:             if (rfd < 0) {
 721:                 syslog(LOG_WARNING, "accept: %m");
 722:                 continue;
 723:             }
 724:             (void) fcntl(rfd, F_SETFL, FNDELAY);
 725:             (void) setsockopt(rfd, SOL_SOCKET, SO_KEEPALIVE,
 726:                 (char *)&on, sizeof(on));
 727:             if ((sp = sqadd()) == QSTREAM_NULL) {
 728:                 (void) close(rfd);
 729:                 continue;
 730:             }
 731:             sp->s_rfd = rfd;    /* stream file descriptor */
 732:             sp->s_size = -1;    /* amount of data to receive */
 733:             gettime(&tt);
 734:             sp->s_time = tt.tv_sec; /* last transaction time */
 735:             sp->s_from = from_addr; /* address to respond to */
 736:             sp->s_bufsize = 0;
 737:             sp->s_bufp = (char *)&sp->s_tempsize;
 738:             sp->s_refcnt = 0;
 739:             FD_SET(rfd, &mask);
 740:             FD_SET(rfd, &tmpmask);
 741: #ifdef DEBUG
 742:             if (debug) {
 743:                 fprintf(ddt,
 744:                    "\nTCP connection from %s port %d (fd %d)\n",
 745:                     inet_ntoa(sp->s_from.sin_addr),
 746:                     ntohs(sp->s_from.sin_port), rfd);
 747:             }
 748: #endif
 749:         }
 750: #ifdef DEBUG
 751:         if (debug > 2 && streamq)
 752:             fprintf(ddt,"streamq  = x%x\n",streamq);
 753: #endif
 754:         if (streamq != NULL) {
 755:             for (sp = streamq; sp != QSTREAM_NULL; sp = sp->s_next)
 756:                 if (FD_ISSET(sp->s_rfd, &tmpmask)) {
 757: #ifdef DEBUG
 758:                 if (debug > 5) {
 759:                     fprintf(ddt,
 760:                     "sp x%x rfd %d size %d time %ld ",
 761:                     sp, sp->s_rfd, sp->s_size,
 762:                     sp->s_time );
 763:                     fprintf(ddt," next x%x \n", sp->s_next );
 764:                     fprintf(ddt,"\tbufsize %d",sp->s_bufsize);
 765:                     fprintf(ddt," buf x%x ",sp->s_buf);
 766:                     fprintf(ddt," bufp x%x\n",sp->s_bufp);
 767:                 }
 768: #endif DEBUG
 769:                 if (sp->s_size < 0) {
 770:                     size = sizeof(u_short) -
 771:                    (sp->s_bufp - (char *)&sp->s_tempsize);
 772:                     while (size > 0 &&
 773:                        (n = read(sp->s_rfd, sp->s_bufp, size)) > 0){
 774:                         sp->s_bufp += n;
 775:                         size -= n;
 776:                     }
 777:                     if ((n == -1) && (errno == EWOULDBLOCK))
 778:                         continue;
 779:                     if (n <= 0) {
 780:                         sp->s_refcnt = 0;
 781:                         sqrm(sp, &mask);
 782:                         continue;
 783:                     }
 784:                     if ((sp->s_bufp - (char *)&sp->s_tempsize) ==
 785:                     sizeof(u_short)) {
 786:                     sp->s_size = htons(sp->s_tempsize);
 787:                     if (sp->s_bufsize == 0) {
 788:                         if ( (sp->s_buf = malloc(BUFSIZ))
 789:                         == NULL) {
 790:                             sp->s_buf = buf;
 791:                             sp->s_size  = sizeof(buf);
 792:                         } else {
 793:                             sp->s_bufsize = BUFSIZ;
 794:                         }
 795:                     }
 796:                     if (sp->s_size > sp->s_bufsize &&
 797:                       sp->s_bufsize != 0) {
 798:                         if ((sp->s_buf = realloc(
 799:                         (char *)sp->s_buf,
 800:                         (unsigned)sp->s_size)) == 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, sp->s_bufp, sp->s_size)) > 0)
 815:                 {
 816:                     sp->s_bufp += n;
 817:                     sp->s_size -= n;
 818:                 }
 819:                 /*
 820: 			     * we don't have enough memory for the query.
 821: 			     * if we have a query id, then we will send an
 822: 			     * error back to the user.
 823: 			     */
 824:                 if (sp->s_bufsize == 0 &&
 825:                 (sp->s_bufp - sp->s_buf > sizeof(u_short))) {
 826:                     HEADER *hp;
 827: 
 828:                     hp = (HEADER *)sp->s_buf;
 829:                     hp->qr = 1;
 830:                     hp->ra = 1;
 831:                     hp->ancount = 0;
 832:                     hp->qdcount = 0;
 833:                     hp->nscount = 0;
 834:                     hp->arcount = 0;
 835:                     hp->rcode = SERVFAIL;
 836:                     (void) writemsg(sp->s_rfd, sp->s_buf,
 837:                     sizeof(HEADER));
 838:                     continue;
 839:                 }
 840:                 if ((n == -1) && (errno == EWOULDBLOCK))
 841:                     continue;
 842:                 if (n <= 0) {
 843:                     sp->s_refcnt = 0;
 844:                     sqrm(sp, &mask);
 845:                     continue;
 846:                 }
 847:                 /*
 848: 			     * Consult database to get the answer.
 849: 			     */
 850:                 if (sp->s_size == 0) {
 851:                     sp->s_refcnt++;
 852:                     ns_req(sp->s_buf,
 853:                     sp->s_bufp - sp->s_buf,
 854:                     sp->s_bufsize, sp,
 855:                     &sp->s_from, -1);
 856:                     sp->s_bufp = (char *)&sp->s_tempsize;
 857:                     sp->s_size = -1;
 858:                     continue;
 859:                 }
 860:             }
 861:         }
 862:     }
 863:     /* NOTREACHED */
 864: }
 865: 
 866: usage()
 867: {
 868:     fprintf(stderr, "Usage: named [-d #] [-p port] [{-b} bootfile]\n");
 869:     exit(1);
 870: }
 871: 
 872: /*
 873: ** Set flag saying to reload database upon receiving SIGHUP.
 874: ** Must make sure that someone isn't walking through a data
 875: ** structure at the time.
 876: */
 877: 
 878: onhup()
 879: {
 880: #if defined(SYSV)
 881:     (void)signal(SIGHUP, onhup);
 882: #endif SYSV
 883:     needreload = 1;
 884: }
 885: 
 886: /*
 887: ** Set flag saying to call ns_maint()
 888: ** Must make sure that someone isn't walking through a data
 889: ** structure at the time.
 890: */
 891: 
 892: maint_alarm()
 893: {
 894: #if defined(SYSV)
 895:     (void)signal(SIGALRM, maint_alarm);
 896: #endif SYSV
 897:     needmaint = 1;
 898: }
 899: 
 900: #ifdef ALLOW_UPDATES
 901: /*
 902:  * Signal handler to schedule shutdown.  Just set flag, to ensure a consistent
 903:  * state during dump.
 904:  */
 905: onintr()
 906: {
 907:         needToExit = 1;
 908: }
 909: #endif ALLOW_UPDATES
 910: 
 911: /*
 912:  * Signal handler to schedule a data base dump.  Do this instead of dumping the
 913:  * data base immediately, to avoid seeing it in a possibly inconsistent state
 914:  * (due to updates), and to avoid long disk I/O delays at signal-handler
 915:  * level
 916:  */
 917: int setdumpflg()
 918: {
 919: #if defined(SYSV)
 920:     (void)signal(SIGINT, setdumpflg);
 921: #endif SYSV
 922:         needToDoadump = 1;
 923: }
 924: 
 925: /*
 926: ** Set flag saying to read was interrupted
 927: ** used for a read timer
 928: */
 929: 
 930: read_alarm()
 931: {
 932:     extern int read_interrupted;
 933:     read_interrupted = 1;
 934: }
 935: 
 936: reapchild()
 937: {
 938: #if defined(SYSV)
 939:     (void)wait(0);
 940:     (void)signal(SIGCLD, reapchild);
 941: #else
 942:     union wait status;
 943: 
 944:     while ((wait3(&status, WNOHANG, (struct rusage *)NULL)) > 0)
 945:         ;
 946: #endif SYSV
 947: }
 948: 
 949: /*
 950: ** Turn on or off debuging by open or closeing the debug file
 951: */
 952: 
 953: setdebug(code)
 954: int code;
 955: {
 956: #if defined(lint) && !defined(DEBUG)
 957:     code = code;
 958: #endif
 959: #ifdef DEBUG
 960: 
 961:     if (code) {
 962:         ddt = freopen(debugfile, "w+", stderr);
 963:         if ( ddt == NULL)
 964:             syslog(LOG_WARNING, "can't open debug file: %m");
 965:         else {
 966: #if defined(SYSV)
 967:             setvbuf(ddt, NULL, _IOLBF, BUFSIZ);
 968: #else
 969:             setlinebuf(ddt);
 970: #endif
 971:             (void) fcntl(fileno(ddt), F_SETFL, FAPPEND);
 972:         }
 973:     }
 974:     else {
 975:         if (ddt) {
 976:             fprintf(ddt,"Debug turned OFF, Level %d\n",debug);
 977:             (void) fclose(ddt);
 978:         }
 979:         debug = 0;
 980:     }
 981: #endif
 982: }
 983: 
 984: /*
 985: ** Catch a special signal and set debug level.
 986: **
 987: **  If debuging is off then turn on debuging else increment the level.
 988: **
 989: ** Handy for looking in on long running name servers.
 990: */
 991: 
 992: setIncrDbgFlg()
 993: {
 994: #if defined(SYSV)
 995:     (void)signal(SIGUSR1, setIncrDbgFlg);
 996: #endif SYSV
 997: #ifdef DEBUG
 998:     if (debug == 0) {
 999:         debug++;
1000:         setdebug(1);
1001:     }
1002:     else {
1003:         debug++;
1004:     }
1005:     fprintf(ddt,"Debug turned ON, Level %d\n",debug);
1006: #endif
1007: }
1008: 
1009: /*
1010: ** Catch a special signal to turn off debugging
1011: */
1012: 
1013: setNoDbgFlg()
1014: {
1015: #if defined(SYSV)
1016:     (void)signal(SIGUSR2, setNoDbgFlg);
1017: #endif SYSV
1018:     setdebug(0);
1019: }
1020: 
1021: /*
1022: ** Set flag for statistics dump
1023: */
1024: setstatsflg()
1025: {
1026: #if defined(SYSV)
1027:     (void)signal(SIGIOT, setstatsflg);
1028: #endif SYSV
1029:     needStatsDump = 1;
1030: }
1031: 
1032: int setchkptflg()
1033: {
1034: #if defined(SYSV)
1035:     (void)signal(SIGQUIT, setchkptflg);
1036: #endif SYSV
1037:     needToChkpt = 1;
1038: }
1039: 
1040: /*
1041: ** Catch a special signal SIGSYS
1042: **
1043: **  this is setup to fork and exit to drop to /usr/tmp/gmon.out
1044: **   and keep the server running
1045: */
1046: 
1047: sigprof()
1048: {
1049: #if defined(SYSV)
1050:     (void)signal(SIGSYS, sigprof);
1051: #endif SYSV
1052: #ifdef DEBUG
1053:     if (debug)
1054:         fprintf(ddt,"sigprof()\n");
1055: #endif
1056:     if ( fork() == 0)
1057:     {
1058:         (void) chdir("/usr/tmp");
1059:         exit(1);
1060:     }
1061: }
1062: 
1063: /*
1064: ** Routines for managing stream queue
1065: */
1066: 
1067: struct qstream *
1068: sqadd()
1069: {
1070:     register struct qstream *sqp;
1071: 
1072:     if ((sqp = (struct qstream *)calloc(1, sizeof(struct qstream)))
1073:         == NULL ) {
1074: #ifdef DEBUG
1075:         if (debug >= 5)
1076:             fprintf(ddt,"sqadd: malloc error\n");
1077: #endif
1078:         syslog(LOG_ERR, "sqadd: Out Of Memory");
1079:         return(QSTREAM_NULL);
1080:     }
1081: #ifdef DEBUG
1082:     if (debug > 3)
1083:         fprintf(ddt,"sqadd(x%x)\n", sqp);
1084: #endif
1085: 
1086:     sqp->s_next = streamq;
1087:     streamq = sqp;
1088:     return(sqp);
1089: }
1090: 
1091: sqrm(qp, mask)
1092:     register struct qstream *qp;
1093:     fd_set *mask;
1094: {
1095:     register struct qstream *qsp;
1096: 
1097: #ifdef DEBUG
1098:     if (debug > 1) {
1099:         fprintf(ddt,"sqrm(%x, %d ) rfcnt=%d\n",
1100:             qp, qp->s_rfd, qp->s_refcnt);
1101:     }
1102: #endif
1103:     if (qp->s_refcnt != 0)
1104:         return;
1105: 
1106:     if (qp->s_bufsize != 0)
1107:         (void) free(qp->s_buf);
1108:     FD_CLR(qp->s_rfd, mask);
1109:     (void) close(qp->s_rfd);
1110:     if (qp == streamq) {
1111:         streamq = qp->s_next;
1112:     } else {
1113:         for (qsp = streamq; qsp->s_next != qp; qsp = qsp->s_next)
1114:             ;
1115:         qsp->s_next = qp->s_next;
1116:     }
1117:     (void)free((char *)qp);
1118: }
1119: 
1120: sqflush()
1121: {
1122:     register struct qstream *sp, *spnext;
1123: 
1124:     for (sp = streamq; sp != QSTREAM_NULL; sp = spnext) {
1125:         sp->s_refcnt = 0;
1126:         spnext = sp->s_next;
1127:         sqrm(sp, &mask);
1128:     }
1129: }
1130: 
1131: setproctitle(a, s)
1132:     char *a;
1133:     int s;
1134: {
1135:     int size;
1136:     register char *cp;
1137:     struct sockaddr_in sin;
1138:     char buf[80];
1139: 
1140:     cp = Argv[0];
1141:     size = sizeof(sin);
1142:     if (getpeername(s, (struct sockaddr *)&sin, &size) == 0)
1143:         (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr));
1144:     else {
1145:         syslog(LOG_DEBUG, "getpeername: %m");
1146:         (void) sprintf(buf, "-%s", a);
1147:     }
1148:     (void) strncpy(cp, buf, LastArg - cp);
1149:     cp += strlen(cp);
1150:     while (cp < LastArg)
1151:         *cp++ = ' ';
1152: }
1153: 
1154: u_long
1155: net_mask(in)
1156: struct in_addr in;
1157: {
1158:     register u_long i = ntohl(in.s_addr);
1159: 
1160:     if (IN_CLASSA(i))
1161:         return (htonl(IN_CLASSA_NET));
1162:     else if (IN_CLASSB(i))
1163:         return (htonl(IN_CLASSB_NET));
1164:     else
1165:         return (htonl(IN_CLASSC_NET));
1166: }
1167: 
1168: gettime(ttp)
1169: struct timeval *ttp;
1170: {
1171:     if (gettimeofday(ttp, (struct timezone *)0) < 0)
1172:         syslog(LOG_ERR, "gettimeofday failed: %m");
1173:     return;
1174: }

Defined functions

getdtablesize defined in line 128; used 2 times
main defined in line 134; never used
maint_alarm defined in line 892; used 3 times
net_mask defined in line 1154; used 5 times
onhup defined in line 878; used 3 times
onintr defined in line 905; used 2 times
read_alarm defined in line 930; used 2 times
reapchild defined in line 936; used 4 times
setIncrDbgFlg defined in line 992; used 4 times
setNoDbgFlg defined in line 1013; used 4 times
setchkptflg defined in line 1032; used 3 times
setdebug defined in line 953; used 3 times
setdumpflg defined in line 917; used 3 times
setproctitle defined in line 1131; used 1 times
setstatsflg defined in line 1024; used 3 times
sigprof defined in line 1047; used 3 times
sqadd defined in line 1067; used 2 times
sqflush defined in line 1120; used 1 times
sqrm defined in line 1091; used 5 times
usage defined in line 866; used 3 times

Defined variables

Argv defined in line 122; used 2 times
LastArg defined in line 123; used 3 times
PidFile defined in line 66; used 1 times
bootfile defined in line 54; used 4 times
boottime defined in line 118; used 3 times
copyright defined in line 14; never used
datagramq defined in line 107; used 18 times
debug defined in line 84; used 266 times
debugfile defined in line 60; used 1 times
dqp defined in line 108; used 72 times
fnettab defined in line 112; used 5 times
from_addr defined in line 116; used 16 times
from_len defined in line 117; used 6 times
mask defined in line 119; used 25 times
needStatsDump defined in line 91; used 3 times
needToChkpt defined in line 90; used 3 times
needToDoadump defined in line 89; used 3 times
needToExit defined in line 93; used 2 times
needmaint defined in line 88; used 3 times
needreload defined in line 87; used 3 times
netloop defined in line 114; used 5 times
nettab defined in line 111; used 6 times
ns_port defined in line 115; used 4 times
nsaddr defined in line 109; never used
onettab defined in line 113; used 4 times
priming defined in line 100; used 7 times
rbufsize defined in line 103; used 2 times
  • in line 547(2)
read_interrupted defined in line 86; used 2 times
sccsid defined in line 18; never used
sqp defined in line 108; used 11 times
streamq defined in line 106; used 24 times

Defined macros

FD_CLR defined in line 73; used 1 times
FD_ISSET defined in line 74; used 3 times
FD_SET defined in line 72; used 6 times
FD_SETSIZE defined in line 71; used 3 times
FD_ZERO defined in line 75; used 1 times
NFDBITS defined in line 70; used 6 times
Last modified: 1996-11-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 11140
Valid CSS Valid XHTML 1.0 Strict