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