📄 ns_main.c
字号:
#if !defined(lint) && !defined(SABER)static char sccsid[] = "@(#)ns_main.c 4.55 (Berkeley) 7/1/91";static char rcsid[] = "$Id: ns_main.c,v 4.9.1.8 1993/12/06 00:43:02 vixie Exp $";#endif /* not lint *//* * ++Copyright++ 1986, 1989, 1990 * - * Copyright (c) 1986, 1989, 1990 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * - * --Copyright-- */#if !defined(lint) && !defined(SABER)char copyright[] ="@(#) Copyright (c) 1986, 1989, 1990 The Regents of the University of California.\n\ portions Copyright (c) 1993 Digital Equipment Corporation\n\ portions Copyright (c) 1993 Berkeley Network Software Consortium\n\ All rights reserved.\n";#endif /* not lint *//* * Internet Name server (see rfc883 & others). */#include <sys/param.h>#include <sys/file.h>#include <sys/stat.h>#if !defined(SYSV) && defined(XXX)#include <sys/wait.h>#endif /* !SYSV */#include <sys/time.h>#define TIME_H_INCLUDED#include <sys/resource.h>#include <sys/ioctl.h>#if defined(__osf__)#define _SOCKADDR_LEN /* XXX - should be in portability.h but that * would need to be included before socket.h */#endif#include <sys/socket.h>#include <netinet/in.h>#include <net/if.h>#include <arpa/nameser.h>#include <arpa/inet.h>#include <fcntl.h>#include <stdio.h>#include <syslog.h>#include <errno.h>#include <signal.h>#include <netdb.h>#include <resolv.h>#if defined(sun) && defined (SYSV) /* Solaris 2 */#include <sys/sockio.h>#endif#define MAIN_PROGRAM#include "named.h"#undef MAIN_PROGRAM#undef nsaddr#ifdef SO_RCVBUFstatic int rbufsize = 8 * 1024; /* UDP recive buffer size */#endifstatic struct sockaddr_in nsaddr;static u_int16_t local_ns_port; /* our service port */static fd_set mask; /* open descriptors */static char **Argv = NULL;static char *LastArg = NULL; /* end of argv */static struct qstream *sqadd __P((void));static void sq_query __P((struct qstream *)), opensocket __P((struct qdatagram *)),#ifdef DEBUG printnetinfo __P((struct netinfo *)),#endif setdebug __P((int));static int sq_here __P((struct qstream *));static SIG_FN onintr __P(()), maint_alarm __P(()), setdumpflg __P(()), onhup __P(()),#if defined(QRYLOG) && defined(SIGWINCH) setQrylogFlg __P(()),#endif setIncrDbgFlg __P(()), setNoDbgFlg __P(()), sigprof __P(()), setchkptflg __P(()), setstatsflg __P(());static voidusage(){ fprintf(stderr,"Usage: named [-d #] [-q] [-r] [-p port[/localport]] [[-b] bootfile]\n"); exit(1);}/*ARGSUSED*/voidmain(argc, argv, envp) int argc; char *argv[], *envp[];{ register int n, udpcnt; register char *arg; register struct qstream *sp; register struct qdatagram *dqp; struct qstream *nextsp; int nfds; int on = 1; int rfd, size; time_t lasttime, maxctime; u_char buf[BUFSIZ];#ifndef SYSV struct sigvec vec;#endif fd_set tmpmask; struct timeval t, *tp; struct qstream *candidate = QSTREAM_NULL; char **argp;#ifdef PID_FIX char oldpid[10];#endif#ifdef WANT_PIDFILE FILE *fp; /* file descriptor for pid file */#endif local_ns_port = ns_port = htons(NAMESERVER_PORT); /* ** Save start and extent of argv for setproctitle. */ Argv = argp = argv; while (*argp) argp++; LastArg = argp[-1] + strlen(argp[-1]); (void) umask(022); /* XXX - should use getopt here */ while (--argc > 0) { arg = *++argv; if (*arg == '-') { while (*++arg) switch (*arg) { case 'b': if (--argc <= 0) usage(); bootfile = savestr(*++argv); break; case 'd': ++argv; if (*argv != 0) { if (**argv == '-') { argv--; break; } debug = atoi(*argv); --argc; } if (debug <= 0) debug = 1; setdebug(1); break; case 'p': /* use nonstandard port number. * usage: -p remote/local * remote is the port number to which * we send queries. local is the port * on which we listen for queries. * local defaults to same as remote. */ if (--argc <= 0) usage(); ns_port = htons((u_int16_t) atoi(*++argv)); { char *p = strchr(*argv, '/'); if (p) { local_ns_port = htons((u_int16_t) atoi(p+1)); } else { local_ns_port = ns_port; } } break;#ifdef QRYLOG case 'q': qrylog = 1; break;#endif case 'r': NoRecurse = 1; break; default: usage(); } } else bootfile = savestr(*argv); } if (!debug) for (n = getdtablesize() - 1; n > 2; n--) (void) close(n); /* don't use my_close() here */#ifdef DEBUG else { fprintf(ddt,"Debug turned ON, Level %d\n",debug); fprintf(ddt,"Version = %s\t",Version); fprintf(ddt,"bootfile = %s\n",bootfile); } #endif#ifdef LOG_DAEMON openlog("named", LOG_PID|LOG_CONS|LOG_NDELAY, LOGFAC);#else openlog("named", LOG_PID);#endif#ifdef WANT_PIDFILE /* tuck my process id away */#ifdef PID_FIX fp = fopen(PidFile, "r+"); if (fp != NULL) { (void) fgets(oldpid, sizeof(oldpid), fp); (void) rewind(fp); fprintf(fp, "%d\n", getpid()); (void) my_fclose(fp); }#else /*PID_FIX*/ fp = fopen(PidFile, "w"); if (fp != NULL) { fprintf(fp, "%d\n", getpid()); (void) my_fclose(fp); }#endif /*PID_FIX*/#endif /*WANT_PIDFILE*/ syslog(LOG_NOTICE, "starting. %s", Version); _res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE); nsaddr.sin_family = AF_INET; nsaddr.sin_addr.s_addr = INADDR_ANY; nsaddr.sin_port = local_ns_port; /* ** Open stream port. */ for (n = 0; ; n++) { if ((vs = socket(AF_INET, SOCK_STREAM, 0)) < 0) { syslog(LOG_ERR, "socket(SOCK_STREAM): %m"); exit(1); } if (setsockopt(vs, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) != 0) { syslog(LOG_ERR, "setsockopt(vs, reuseaddr): %m"); (void) my_close(vs); continue; } if (bind(vs, (struct sockaddr *)&nsaddr, sizeof(nsaddr)) == 0) break; if (errno != EADDRINUSE || n > 4) { if (errno == EADDRINUSE) { syslog(LOG_ERR, "There may be a name server already running"); syslog(LOG_ERR, "exiting"); } else { syslog(LOG_ERR, "bind(vs, [%s].%d): %m", inet_ntoa(nsaddr.sin_addr), ntohs(nsaddr.sin_port)); }#if defined(WANT_PIDFILE) && defined(PID_FIX) /* put old pid back */ if (atoi(oldpid) && (fp = fopen(PidFile, "w"))) { fprintf(fp, "%s", oldpid); (void) my_fclose(fp); _exit(1); }#endif /*WANT_PIDFILE && PID_FIX*/ exit(1); } else { /* Retry opening the socket a few times */ my_close(vs); sleep(1); } } if (listen(vs, 5) != 0) { syslog(LOG_ERR, "listen(vs, 5): %m"); exit(1); } /* * Get list of local addresses and set up datagram sockets. */ getnetconf(); /* ** Initialize and load database. */ gettime(&tt); buildservicelist(); buildprotolist(); ns_init(bootfile);#ifdef DEBUG if (debug) { fprintf(ddt, "Network and sort list:\n"); printnetinfo(nettab); }#endif time(&boottime); resettime = boottime; (void) signal(SIGHUP, onhup);#if defined(SIGXFSZ) (void) signal(SIGXFSZ, onhup); /* wierd DEC Hesiodism, harmless */#endif#if defined(SYSV) (void) signal(SIGCLD, endxfer); (void) signal(SIGALRM, maint_alarm);#else bzero((char *)&vec, sizeof(vec)); vec.sv_handler = maint_alarm; vec.sv_mask = sigmask(SIGCHLD); (void) sigvec(SIGALRM, &vec, (struct sigvec *)NULL); vec.sv_handler = endxfer; vec.sv_mask = sigmask(SIGALRM); (void) sigvec(SIGCHLD, &vec, (struct sigvec *)NULL);#endif /* SYSV */ (void) signal(SIGPIPE, SIG_IGN); (void) signal(SIGSYS, sigprof); (void) signal(SIGINT, setdumpflg); (void) signal(SIGQUIT, setchkptflg); (void) signal(SIGIOT, setstatsflg);#ifdef ALLOW_UPDATES /* Catch SIGTERM so we can dump the database upon shutdown if it has changed since it was last dumped/booted */ (void) signal(SIGTERM, onintr);#endif#if defined(SIGUSR1) && defined(SIGUSR2) (void) signal(SIGUSR1, setIncrDbgFlg); (void) signal(SIGUSR2, setNoDbgFlg);#else /* SIGUSR1&&SIGUSR2 */ (void) signal(SIGEMT, setIncrDbgFlg); (void) signal(SIGFPE, setNoDbgFlg);#endif /* SIGUSR1&&SIGUSR2 */#if defined(SIGWINCH) && defined(QRYLOG) (void) signal(SIGWINCH, setQrylogFlg);#endif#ifdef DEBUG if (debug) { fprintf(ddt,"database initialized\n"); }#endif t.tv_usec = 0; /* * Fork and go into background now that * we've done any slow initialization * and are ready to answer queries. */#ifdef USE_SETSID if (!debug || !isatty(0)) { if (fork() > 0) exit(0); setsid(); if (!debug) { n = open(_PATH_DEVNULL, O_RDONLY); (void) dup2(n, 0); (void) dup2(n, 1); (void) dup2(n, 2); if (n > 2) (void) my_close(n); } }#else if (!debug) {#ifdef HAVE_DAEMON daemon(1, 0);#else switch (fork()) { case -1: syslog(LOG_ERR, "fork: %m"); exit(1); /*FALLTHROUGH*/ case 0: /* child */ break; default: /* parent */ exit(0); } n = open(_PATH_DEVNULL, O_RDONLY); (void) dup2(n, 0); (void) dup2(n, 1); (void) dup2(n, 2); if (n > 2) (void) my_close(n);#ifdef SYSV setpgrp();#else { struct itimerval ival; /* * The open below may hang on pseudo ttys if the person * who starts named logs out before this point. * * needmaint may get set inapropriately if the open * hangs, but all that will happen is we will see that * no maintenance is required. */ bzero((char *)&ival, sizeof(ival)); ival.it_value.tv_sec = 120; (void) setitimer(ITIMER_REAL, &ival, (struct itimerval *)NULL); n = open(_PATH_TTY, O_RDWR); ival.it_value.tv_sec = 0; (void) setitimer(ITIMER_REAL, &ival, (struct itimerval *)NULL); if (n > 0) { (void) ioctl(n, TIOCNOTTY, (char *)NULL); (void) my_close(n); } }#endif /* SYSV */#endif /* HAVE_DAEMON */ }#endif /* USE_SETSID */#ifdef WANT_PIDFILE /* tuck my process id away again */ fp = fopen(PidFile, "w"); if (fp != NULL) { fprintf(fp, "%d\n", getpid()); (void) my_fclose(fp); }#endif#ifdef DEBUG if (debug) fprintf(ddt,"Ready to answer queries.\n");#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -