📄 ns_main.c
字号:
dprintf(1, (ddt, "bye, bye, interface [%s]", inet_ntoa(dqp->dq_addr))); syslog(LOG_CRIT, "interface [%s] missing; deleting", inet_ntoa(dqp->dq_addr)); if (pqp != NULL) pqp->dq_next = dqp->dq_next; else datagramq = dqp->dq_next; (void) free(dqp); } } /* * Create separate qdatagram structure for socket * wildcard address. */ if (first) { if ((dqp = (struct qdatagram *)calloc(1, sizeof(*dqp))) == NULL) { dprintf(1, (ddt, "getnetconf: malloc error\n")); syslog(LOG_ERR, "getnetconf: Out Of Memory"); exit(12); } dqp->dq_next = datagramq; datagramq = dqp; dqp->dq_addr.s_addr = INADDR_ANY; opensocket(dqp); ds = dqp->dq_dfd; } /* * Compute logical networks to which we're connected * based on attached subnets; * used for sorting based on network configuration. */ for (ntp = nettab; ntp != NULL; ntp = ntp->next) { nm = net_mask(ntp->my_addr); if (nm != ntp->mask) { if (findnetinfo(ntp->my_addr)) continue; ontp = (struct netinfo *) malloc(sizeof(struct netinfo)); if (ontp == NULL) { dprintf(5, (ddt, "getnetconf: malloc error\n")); syslog(LOG_ERR, "getnetconf: Out Of Memory"); exit(12); } ontp->my_addr = ntp->my_addr; ontp->mask = nm; ontp->net = ontp->my_addr.s_addr & nm; ontp->next = *enettab; *enettab = ontp; enettab = &ontp->next; } } first = 0;}/* * Find netinfo structure for logical network implied by address "addr", * if it's on list of local/favored networks. */struct netinfo *findnetinfo(addr) struct in_addr addr;{ register struct netinfo *ntp; u_int32_t net, mask; mask = net_mask(addr); net = addr.s_addr & mask; for (ntp = nettab; ntp != NULL; ntp = ntp->next) if (ntp->net == net && ntp->mask == mask) return (ntp); return ((struct netinfo *) NULL);}#ifdef DEBUGstatic voidprintnetinfo(ntp) register struct netinfo *ntp;{ for ( ; ntp != NULL; ntp = ntp->next) { fprintf(ddt,"net x%lx mask x%lx", ntp->net, ntp->mask); fprintf(ddt," my_addr x%lx", ntp->my_addr.s_addr); fprintf(ddt," %s\n", inet_ntoa(ntp->my_addr)); }}#endifstatic voidopensocket(dqp) register struct qdatagram *dqp;{ int n, m; int on = 1; /* * Open datagram sockets bound to interface address. */ if ((dqp->dq_dfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, "socket(SOCK_DGRAM): %m - exiting"); exit(1); } #ifdef DEBUG if (debug) fprintf(ddt,"dqp->dq_addr %s d_dfd %d\n", inet_ntoa(dqp->dq_addr), dqp->dq_dfd);#endif if (setsockopt(dqp->dq_dfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) != 0) { syslog(LOG_ERR, "setsockopt(dqp->dq_dfd, reuseaddr): %m"); /* XXX press on regardless, this is not too serious. */ }#ifdef SO_RCVBUF m = sizeof(n); /* note: this depends on short-circuit evaluation, which is in the * C standards, but tricky nonetheless. (vix) */ if ((getsockopt(dqp->dq_dfd, SOL_SOCKET, SO_RCVBUF, &n, &m) >= 0) && (m == sizeof(n)) && (n < rbufsize)) { (void) setsockopt(dqp->dq_dfd, SOL_SOCKET, SO_RCVBUF, (char *)&rbufsize, sizeof(rbufsize)); }#endif /* SO_RCVBUF */ if ((n = fcntl(dqp->dq_dfd, F_GETFL, 0)) < 0) { syslog(LOG_ERR, "fcntl(dfd, F_GETFL): %m"); /* XXX press on regardless, but this really is a problem. */ } else if (fcntl(dqp->dq_dfd, F_SETFL, n|PORT_NONBLOCK) != 0) { syslog(LOG_ERR, "fcntl(dqp->dq_dfd, non-blocking): %m"); /* XXX press on regardless, but this really is a problem. */ } /* * NOTE: Some versions of SunOS have problems with the following * call to bind. Bind still seems to function on these systems * if you comment out the exit inside the if. This may cause * Suns with multiple interfaces to reply strangely. */ nsaddr.sin_addr = dqp->dq_addr; if (bind(dqp->dq_dfd, (struct sockaddr *)&nsaddr, sizeof(nsaddr))) { syslog(LOG_ERR, "bind(dfd=%d, [%s].%d): %m - exiting", dqp->dq_dfd, inet_ntoa(nsaddr.sin_addr), ntohs(nsaddr.sin_port));#if !defined(sun) exit(1);#endif }}/*** Set flag saying to reload database upon receiving SIGHUP.** Must make sure that someone isn't walking through a data** structure at the time.*/static SIG_FNonhup(){#if defined(SYSV) (void)signal(SIGHUP, onhup);#endif /* SYSV */ needreload = 1;}/*** Set flag saying to call ns_maint()** Must make sure that someone isn't walking through a data** structure at the time.*/static SIG_FNmaint_alarm(){#if defined(SYSV) (void)signal(SIGALRM, maint_alarm);#endif /* SYSV */ needmaint = 1; }#ifdef ALLOW_UPDATES/* * Signal handler to schedule shutdown. Just set flag, to ensure a consistent * state during dump. */static SIG_FNonintr(){ needToExit = 1;}#endif /* ALLOW_UPDATES *//* * Signal handler to schedule a data base dump. Do this instead of dumping the * data base immediately, to avoid seeing it in a possibly inconsistent state * (due to updates), and to avoid long disk I/O delays at signal-handler * level */static SIG_FNsetdumpflg(){#if defined(SYSV) (void)signal(SIGINT, setdumpflg);#endif /* SYSV */ needToDoadump = 1;}/*** Turn on or off debuging by open or closeing the debug file*/static voidsetdebug(code) int code;{#if defined(lint) && !defined(DEBUG) code = code;#endif#ifdef DEBUG if (code) { int n; ddt = freopen(debugfile, "w+", stderr); if ( ddt == NULL) { syslog(LOG_WARNING, "can't open debug file %s: %m", debugfile); debug = 0; } else {#if defined(SYSV) setvbuf(ddt, NULL, _IOLBF, BUFSIZ);#else setlinebuf(ddt);#endif if ((n = fcntl(fileno(ddt), F_GETFL, 0)) < 0) { syslog(LOG_WARNING, "fcntl(ddt, F_GETFL): %m"); } else { (void) fcntl(fileno(ddt), F_SETFL, n|O_APPEND); } } } else debug = 0; /* delay closing ddt, we might interrupt someone */#endif}/*** Catch a special signal and set debug level.**** If debuging is off then turn on debuging else increment the level.**** Handy for looking in on long running name servers.*/static SIG_FNsetIncrDbgFlg(){#if defined(SYSV) (void)signal(SIGUSR1, setIncrDbgFlg);#endif /* SYSV */#ifdef DEBUG if (debug == 0) { debug++; setdebug(1); } else { debug++; } fprintf(ddt,"Debug turned ON, Level %d\n",debug);#endif}/*** Catch a special signal to turn off debugging*/static SIG_FNsetNoDbgFlg(){#if defined(SYSV) (void)signal(SIGUSR2, setNoDbgFlg);#endif /* SYSV */ setdebug(0);}#if defined(QRYLOG) && defined(SIGWINCH)/*** Set flag for query logging*/static SIG_FNsetQrylogFlg(){#if defined(SYSV) (void)signal(SIGWINCH, setQrylogFlg);#endif /* SYSV */ qrylog = !qrylog; syslog(LOG_NOTICE, "query log %s\n", qrylog ?"on" :"off");}#endif /*QRYLOG && SIGWINCH*//*** Set flag for statistics dump*/static SIG_FNsetstatsflg(){#if defined(SYSV) (void)signal(SIGIOT, setstatsflg);#endif /* SYSV */ needStatsDump = 1;}static SIG_FNsetchkptflg(){#if defined(SYSV) (void)signal(SIGQUIT, setchkptflg);#endif /* SYSV */ needToChkpt = 1;}/*** Catch a special signal SIGSYS**** this is setup to fork and exit to drop to /usr/tmp/gmon.out** and keep the server running*/static SIG_FNsigprof(){#if defined(SYSV) (void)signal(SIGSYS, sigprof);#endif /* SYSV */#ifdef DEBUG if (debug) fprintf(ddt,"sigprof()\n");#endif if (fork() == 0) { (void) chdir(_PATH_TMPDIR); exit(1); }}/*** Routines for managing stream queue*/static struct qstream *sqadd(){ register struct qstream *sqp; if (!(sqp = (struct qstream *)calloc(1, sizeof(struct qstream)))) { dprintf(5, (ddt, "sqadd: calloc error\n")); syslog(LOG_ERR, "sqadd: Out Of Memory"); return(QSTREAM_NULL); } dprintf(3, (ddt, "sqadd(x%x)\n", sqp)); sqp->s_next = streamq; streamq = sqp; return(sqp);}/* sqrm(qp) * remove stream queue structure `qp'. * no current queries may refer to this stream when it is removed. * side effects: * memory is deallocated. sockets are closed. lists are relinked. */voidsqrm(qp) register struct qstream *qp;{ register struct qstream *qsp; dprintf(2, (ddt, "sqrm(%#x, %d ) rfcnt=%d\n", qp, qp->s_rfd, qp->s_refcnt)); if (qp->s_bufsize != 0) free(qp->s_buf); FD_CLR(qp->s_rfd, &mask); (void) my_close(qp->s_rfd); if (qp == streamq) { streamq = qp->s_next; } else { for (qsp = streamq; qsp && (qsp->s_next != qp); qsp = qsp->s_next) ; if (qsp) { qsp->s_next = qp->s_next; } } free((char *)qp);}/* sqflush() * call sqrm() on all open streams * side effects: * global list `streamq' becomes empty */voidsqflush(){ register struct qstream *sp, *spnext; for (sp = streamq; sp != QSTREAM_NULL; sp = spnext) { spnext = sp->s_next; sqrm(sp); }}/* int * sq_here(sp) * determine whether stream 'sp' is still on the streamq * return: * boolean: is it here? */static intsq_here(sp) register struct qstream *sp;{ register struct qstream *t; for (t = streamq; t != QSTREAM_NULL; t = t->s_next) if (t == sp) return 1; return 0;}/* * Initiate query on stream; * mark as referenced and stop selecting for input. */static voidsq_query(sp) register struct qstream *sp;{ sp->s_refcnt++; FD_CLR(sp->s_rfd, &mask);}/* * Note that the current request on a stream has completed, * and that we should continue looking for requests on the stream. */voidsq_done(sp) register struct qstream *sp;{ sp->s_refcnt = 0; sp->s_time = tt.tv_sec; FD_SET(sp->s_rfd, &mask);}voidsetproctitle(a, s) char *a; int s;{ int size; register char *cp; struct sockaddr_in sin; char buf[80]; cp = Argv[0]; size = sizeof(sin); if (getpeername(s, (struct sockaddr *)&sin, &size) == 0) (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr)); else { syslog(LOG_DEBUG, "getpeername: %m"); (void) sprintf(buf, "-%s", a); } (void) strncpy(cp, buf, LastArg - cp); cp += strlen(cp); while (cp < LastArg) *cp++ = ' ';}u_int32_tnet_mask(in) struct in_addr in;{ register u_int32_t i = ntohl(in.s_addr); if (IN_CLASSA(i)) return (htonl(IN_CLASSA_NET)); else if (IN_CLASSB(i)) return (htonl(IN_CLASSB_NET)); else return (htonl(IN_CLASSC_NET));}#if defined(BSD43_BSD43_NFS)/* junk needed for old Sun NFS licensees */#undef dn_skipnameextern char *dn_skipname();char *(*hack_skipname)() = dn_skipname;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -