summaryrefslogtreecommitdiffstats
path: root/contrib/bind/named/ns_maint.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind/named/ns_maint.c')
-rw-r--r--contrib/bind/named/ns_maint.c1087
1 files changed, 0 insertions, 1087 deletions
diff --git a/contrib/bind/named/ns_maint.c b/contrib/bind/named/ns_maint.c
deleted file mode 100644
index 944d2b2..0000000
--- a/contrib/bind/named/ns_maint.c
+++ /dev/null
@@ -1,1087 +0,0 @@
-#if !defined(lint) && !defined(SABER)
-static char sccsid[] = "@(#)ns_maint.c 4.39 (Berkeley) 3/2/91";
-static char rcsid[] = "$Id: ns_maint.c,v 8.18 1996/09/22 00:13:10 vixie Exp $";
-#endif /* not lint */
-
-/*
- * ++Copyright++ 1986, 1988
- * -
- * Copyright (c) 1986, 1988
- * 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--
- */
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <arpa/nameser.h>
-#include <sys/wait.h>
-#include <stdio.h>
-#include <syslog.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/stat.h>
-
-#include "named.h"
-
-#ifdef USE_UTIME
-# include <utime.h>
-#endif
-
-static int xfers_running, /* # of xfers running */
- xfers_deferred, /* # of needed xfers not run yet */
- qserials_running,
- alarm_pending, /* flag */
- nxfers __P((struct zoneinfo *, int));
-
-static void startxfer __P((struct zoneinfo *)),
- abortxfer __P((struct zoneinfo *)),
- addxfer __P((struct zoneinfo *)),
- tryxfer __P((void));
-
-#define qserial_qfull() (qserials_running == MAXQSERIAL)
-
-#ifdef CLEANCACHE
-static time_t cache_time;
-#endif
-#ifdef XSTATS
-static time_t stats_time;
-#endif
-/*
- * Invoked at regular intervals by signal interrupt; refresh all secondary
- * zones from primary name server and remove old cache entries.
- */
-void
-ns_maint()
-{
- register struct zoneinfo *zp;
- int zonenum;
-
- gettime(&tt);
-
- dprintf(1, (ddt, "\nns_maint(); now %s", ctimel(tt.tv_sec)));
-
- alarm_pending = 0;
- for (zp = zones, zonenum = 0; zp < &zones[nzones]; zp++, zonenum++) {
-#ifdef DEBUG
- if (debug >= 2)
- printzoneinfo(zonenum);
-#endif
- if (tt.tv_sec >= zp->z_time && zp->z_refresh > 0) {
- switch (zp->z_type) {
-
- case Z_CACHE:
- doachkpt();
- ns_refreshtime(zp, tt.tv_sec);
- break;
-
- case Z_SECONDARY:
-#ifdef STUBS
- case Z_STUB:
-#endif
- if (zp->z_serial != 0 &&
- ((zp->z_lastupdate + zp->z_expire) <
- tt.tv_sec)
- ) {
- zp->z_serial = 0;
- }
- if (zp->z_flags &
- (Z_NEED_RELOAD|Z_NEED_XFER|Z_QSERIAL)) {
- ns_refreshtime(zp, tt.tv_sec);
- break;
- }
- if (zp->z_flags & Z_XFER_RUNNING) {
- abortxfer(zp);
- break;
- }
- qserial_query(zp);
- break;
- }
- gettime(&tt);
- }
- }
-#ifdef CLEANCACHE
- if ((cache_time + cache_interval) <= tt.tv_sec) {
- if (cache_time && (!NoRecurse || !NoFetchGlue))
- remove_zone(hashtab, 0, 0);
- cache_time = tt.tv_sec;
- }
-#endif
-#ifdef XSTATS
- if (stats_time + stats_interval <= tt.tv_sec) {
- if (stats_time)
- ns_logstats();
- stats_time = tt.tv_sec;
- }
-#endif
- if (!needmaint)
- sched_maint();
- dprintf(1, (ddt, "exit ns_maint()\n"));
-}
-
-/*
- * Find when the next refresh needs to be and set
- * interrupt time accordingly.
- */
-void
-sched_maint()
-{
- register struct zoneinfo *zp;
- struct itimerval ival;
-#ifdef CLEANCACHE
- time_t next_refresh = cache_time + cache_interval;
-#else
- time_t next_refresh = 0;
-#endif
- static time_t next_alarm;
-
- for (zp = zones; zp < &zones[nzones]; zp++)
- if (zp->z_time != 0 &&
- (next_refresh == 0 || next_refresh > zp->z_time))
- next_refresh = zp->z_time;
- /*
- * Schedule the next call to ns_maint.
- * Don't visit any sooner than maint_interval.
- */
- bzero((char *)&ival, sizeof ival);
- if (next_refresh != 0) {
- if (next_refresh == next_alarm && alarm_pending) {
- dprintf(1, (ddt, "sched_maint: no schedule change\n"));
- return;
- }
- /*
- * tv_sec can be an unsigned long, so we can't let
- * it go negative.
- */
- if (next_refresh < tt.tv_sec)
- next_refresh = tt.tv_sec;
- ival.it_value.tv_sec = next_refresh - tt.tv_sec;
- if ((long) ival.it_value.tv_sec < maint_interval)
- ival.it_value.tv_sec = maint_interval;
- next_alarm = next_refresh;
- alarm_pending = 1;
- }
- (void) setitimer(ITIMER_REAL, &ival, (struct itimerval *)NULL);
- dprintf(1, (ddt, "sched_maint: Next interrupt in %lu sec\n",
- (u_long)ival.it_value.tv_sec));
-}
-
-/*
- * Mark a zone "up to date" after named-xfer tells us this or we
- * discover it through the qserial_*() logic.
- */
-static void
-markUpToDate(zp)
- struct zoneinfo *zp;
-{
- struct stat f_time;
-
- zp->z_flags &= ~Z_SYSLOGGED;
- zp->z_lastupdate = tt.tv_sec;
- ns_refreshtime(zp, tt.tv_sec);
- /*
- * Restore Z_AUTH in case expired,
- * but only if there were no errors
- * in the zone file.
- */
- if ((zp->z_flags & Z_DB_BAD) == 0)
- zp->z_flags |= Z_AUTH;
- if (zp->z_source) {
-#if defined(USE_UTIME)
- struct utimbuf t;
-
- t.actime = tt.tv_sec;
- t.modtime = tt.tv_sec;
- (void) utime(zp->z_source, &t);
-#else
- struct timeval t[2];
-
- t[0] = tt;
- t[1] = tt;
- (void) utimes(zp->z_source, t);
-#endif /* USE_UTIME */
- }
- /* we use "stat" to set zp->z_ftime instead of just
- setting it to tt.tv_sec in order to avoid any
- possible rounding problems in utimes(). */
- if (stat(zp->z_source, &f_time) != -1)
- zp->z_ftime = f_time.st_mtime;
- /* XXX log if stat fails? */
-}
-
-/*
- * Query for the serial number of a zone, so that
- * we can check to see if we need to transfer it.
- */
-void
-qserial_query(zp)
- struct zoneinfo *zp;
-{
- struct qinfo *qp;
-
- dprintf(1, (ddt, "qserial_query(%s)\n", zp->z_origin));
-
- if (qserial_qfull())
- return;
-
- qp = sysquery(zp->z_origin, zp->z_class, T_SOA,
- zp->z_addr, zp->z_addrcnt, QUERY);
- if (!qp) {
- syslog(LOG_INFO, "qserial_query(%s): sysquery FAILED",
- zp->z_origin);
- return; /* XXX - this is bad, we should do something */
- }
- qp->q_flags |= Q_ZSERIAL;
- qp->q_zquery = zp;
- zp->z_flags |= Z_QSERIAL;
- ns_refreshtime(zp, tt.tv_sec);
- qserials_running++;
- dprintf(1, (ddt, "qserial_query(%s) QUEUED\n", zp->z_origin));
-}
-
-void
-qserial_answer(qp, serial)
- struct qinfo *qp;
- u_int32_t serial;
-{
- struct zoneinfo *zp = qp->q_zquery;
- int was_qfull = qserial_qfull();
-
- dprintf(1, (ddt, "qserial_answer(%s, %lu)\n",
- zp->z_origin, (u_long)serial));
- zp->z_flags &= ~Z_QSERIAL;
- qp->q_flags &= ~Q_ZSERIAL; /* keeps us from being called twice */
- qserials_running--;
- if (serial == 0) {
- /* an error occurred, or the query timed out.
- */
-#ifdef GETSER_LOGGING
- syslog(GETSER_LOGGING, "Err/TO getting serial# for \"%s\"",
- zp->z_origin);
-#endif /* GETSER_LOGGING */
- addxfer(zp);
- } else if (SEQ_GT(serial, zp->z_serial) || !zp->z_serial) {
- dprintf(1, (ddt, "qserial_answer: zone is out of date\n"));
- zp->z_xaddr = from_addr.sin_addr; /* don't use qp->q_from */
- addxfer(zp);
- } else if (SEQ_GT(zp->z_serial, serial)) {
- if (!haveComplained((char*)zp, "went backward")) {
- syslog(LOG_NOTICE,
- "Zone \"%s\" (class %d) SOA serial# (%lu) rcvd from [%s] is < ours (%lu)\n",
- zp->z_origin, zp->z_class, (u_long)serial,
- inet_ntoa(from_addr.sin_addr),
- (u_long)zp->z_serial);
- }
- } else {
- dprintf(1, (ddt, "qserial_answer: zone serial is still OK\n"));
- markUpToDate(zp);
- }
- if (was_qfull)
- needmaint = 1;
-}
-
-/*
- * Hold and release SIGCHLD
- */
-#ifdef POSIX_SIGNALS
-static sigset_t sset;
-#else
-#ifndef SYSV
-static int omask;
-#endif
-#endif /* POSIX_SIGNALS */
-
-void holdsigchld()
-{
-#ifdef POSIX_SIGNALS
- sigemptyset(&sset);
- sigaddset(&sset,SIGCHLD);
- sigprocmask(SIG_BLOCK,&sset,NULL);
-#else /* POSIX_SIGNALS */
-#ifndef SYSV
- omask = sigblock(sigmask(SIGCHLD));
-#else /* SYSV */
- /* XXX - out of luck? */
-#endif /* SYSV */
-#endif /* POSIX_SIGNALS */
-}
-
-void releasesigchld()
-{
-#ifdef POSIX_SIGNALS
- sigprocmask(SIG_UNBLOCK,&sset,NULL);
-#else
-#ifndef SYSV
- (void) sigsetmask(omask);
-#endif
-#endif /* POSIX_SIGNALS */
-}
-
- /* State of all running zone transfers */
-static struct {
- pid_t xfer_pid;
- int xfer_state; /* see below */
-#ifdef sequent
- union wait xfer_status;
-#else
- int xfer_status;
-#endif
-} xferstatus[MAX_XFERS_RUNNING];
-#define XFER_IDLE 0
-#define XFER_RUNNING 1
-#define XFER_DONE 2
-
-/*
- * Start an asynchronous zone transfer for a zone.
- * Depends on current time being in tt.
- * The caller must call sched_maint after startxfer.
- */
-static void
-startxfer(zp)
- struct zoneinfo *zp;
-{
- char *argv[NSMAX + 20], argv_ns[NSMAX][MAXDNAME];
- int argc = 0, argc_ns = 0, pid, i;
- unsigned int cnt;
- char debug_str[10];
- char serial_str[10];
- char port_str[10];
-#ifdef GEN_AXFR
- char class_str[10];
-#endif
-
- dprintf(1, (ddt, "startxfer() %s\n", zp->z_origin));
-
- argv[argc++] = _PATH_XFER;
- argv[argc++] = "-z";
- argv[argc++] = zp->z_origin;
- argv[argc++] = "-f";
- argv[argc++] = zp->z_source;
- argv[argc++] = "-s";
- sprintf(serial_str, "%lu", (u_long)zp->z_serial);
- argv[argc++] = serial_str;
-#ifdef GEN_AXFR
- argv[argc++] = "-C";
- sprintf(class_str, "%d", zp->z_class);
- argv[argc++] = class_str;
-#endif
- if (zp->z_flags & Z_SYSLOGGED)
- argv[argc++] = "-q";
- argv[argc++] = "-P";
- sprintf(port_str, "%d", ns_port);
- argv[argc++] = port_str;
-#ifdef STUBS
- if (zp->z_type == Z_STUB)
- argv[argc++] = "-S";
-#endif
-#ifdef DEBUG
- if (debug) {
- argv[argc++] = "-d";
- sprintf(debug_str, "%d", debug);
- argv[argc++] = debug_str;
- argv[argc++] = "-l";
- argv[argc++] = _PATH_XFERDDT;
- if (debug > 5) {
- argv[argc++] = "-t";
- argv[argc++] = _PATH_XFERTRACE;
- }
- }
-#endif
-
- if (zp->z_xaddr.s_addr != 0) {
- /* Address was specified by the qserial logic, use it. */
- argv[argc++] = strcpy(argv_ns[argc_ns++],
- inet_ntoa(zp->z_xaddr));
- } else {
- /*
- * Copy the server ip addresses into argv, after converting
- * to ascii and saving the static inet_ntoa result.
- */
- for (cnt = 0; cnt < zp->z_addrcnt; cnt++) {
- struct in_addr a;
-
- a = zp->z_addr[cnt];
- if (aIsUs(a) &&
- !haveComplained(zp->z_origin, (char*)startxfer)) {
- syslog(LOG_NOTICE,
- "attempted to fetch zone %s from self (%s)",
- zp->z_origin, inet_ntoa(a));
- continue;
- }
- argv[argc++] = strcpy(argv_ns[argc_ns++],
- inet_ntoa(a));
- }
- }
-
- argv[argc] = 0;
-
-#ifdef DEBUG
- if (debug) {
- for (i = 0; i < argc; i++)
- fprintf(ddt, " %s", argv[i]);
- fprintf(ddt, "\n");
- }
-#endif /* DEBUG */
-
- gettime(&tt);
- holdsigchld();
- for (i = 0; i < MAX_XFERS_RUNNING; i++) {
- if (xferstatus[i].xfer_pid == 0) {
- xferstatus[i].xfer_state = XFER_RUNNING;
- break;
- }
- }
- if ((pid = vfork()) == -1) {
- syslog(LOG_ERR, "xfer vfork: %m");
- releasesigchld();
- zp->z_time = tt.tv_sec + 10;
- return;
- }
-
- if (pid == 0) {
- /* Child. */
- execv(_PATH_XFER, argv);
- syslog(LOG_ERR, "can't exec %s: %m", _PATH_XFER);
- _exit(XFER_FAIL); /* Avoid duplicate buffer flushes. */
- }
- /* Parent. */
- xferstatus[i].xfer_pid = pid; /* XXX - small race condition here if we
- * can't hold signals */
- dprintf(1, (ddt, "started xfer child %d\n", pid));
- zp->z_flags &= ~Z_NEED_XFER;
- zp->z_flags |= Z_XFER_RUNNING;
- zp->z_xferpid = pid;
- xfers_running++;
- zp->z_time = tt.tv_sec + MAX_XFER_TIME;
- releasesigchld();
-}
-
-const char *
-zoneTypeString(zp)
- const struct zoneinfo *zp;
-{
- static char ret[sizeof "(4294967296?)"]; /* 2^32 */
-
- switch (zp->z_type) {
- case Z_PRIMARY: return ("primary");
- case Z_SECONDARY: return ("secondary");
-#ifdef STUBS
- case Z_STUB: return ("stub");
-#endif
- case Z_CACHE: return ("cache");
- default:
- sprintf(ret, "(%lu?)", (u_long)zp->z_type);
- return (ret);
- }
-}
-
-#ifdef DEBUG
-void
-printzoneinfo(zonenum)
- int zonenum;
-{
- struct timeval tt;
- struct zoneinfo *zp = &zones[zonenum];
-
- if (!debug)
- return;
-
- if (!zp->z_origin)
- return;
-
- fprintf(ddt, "printzoneinfo(%d):\n", zonenum);
-
- gettime(&tt);
- fprintf(ddt, "origin ='%s'", zp->z_origin[0] ? zp->z_origin : ".");
-#ifdef GEN_AXFR
- fprintf(ddt, ", class = %d", zp->z_class);
-#endif
- fprintf(ddt, ", type = %s", zoneTypeString(zp));
- if (zp->z_source)
- fprintf(ddt,", source = %s\n", zp->z_source);
- fprintf(ddt, "z_refresh = %lu", (u_long)zp->z_refresh);
- fprintf(ddt, ", retry = %lu", (u_long)zp->z_retry);
- fprintf(ddt, ", expire = %lu", (u_long)zp->z_expire);
- fprintf(ddt, ", minimum = %lu", (u_long)zp->z_minimum);
- fprintf(ddt, ", serial = %lu\n", (u_long)zp->z_serial);
- fprintf(ddt, "z_time = %lu", (u_long)zp->z_time);
- if (zp->z_time) {
- fprintf(ddt, ", now time : %lu sec", (u_long)tt.tv_sec);
- fprintf(ddt, ", time left: %lu sec",
- (u_long)(zp->z_time - tt.tv_sec));
- }
- fprintf(ddt, "; flags %lx\n", (u_long)zp->z_flags);
-}
-#endif /* DEBUG */
-
-/*
- * remove_zone (htp, zone) --
- * Delete all RR's in the zone "zone" under specified hash table.
- */
-void
-#ifdef CLEANCACHE
-remove_zone(htp, zone, all)
-#else
-remove_zone(htp, zone)
-#endif
- register struct hashbuf *htp;
- register int zone;
-#ifdef CLEANCACHE
- register int all;
-#endif
-{
- register struct databuf *dp, *pdp;
- register struct namebuf *np, *pnp, *npn;
- struct namebuf **npp, **nppend;
-
- nppend = htp->h_tab + htp->h_size;
- for (npp = htp->h_tab; npp < nppend; npp++) {
- for (pnp = NULL, np = *npp; np != NULL; np = npn) {
- for (pdp = NULL, dp = np->n_data; dp != NULL; NULL) {
- if (dp->d_zone == zone
-#ifdef CLEANCACHE
- && (all || stale(dp))
-#endif
- ) {
- dp = rm_datum(dp, np, pdp);
- } else {
- pdp = dp;
- dp = dp->d_next;
- }
- } /*for(pdp)*/
-
- if (np->n_hash) {
- /* call recursively to remove subdomains. */
- remove_zone(np->n_hash, zone
-#ifdef CLEANCACHE
- , all
-#endif
- );
-
- /* if now empty, free it */
- if (np->n_hash->h_cnt == 0) {
- free((char*)np->n_hash);
- np->n_hash = NULL;
- }
- }
-
- if ((np->n_hash == NULL) && (np->n_data == NULL)) {
- npn = rm_name(np, npp, pnp);
- htp->h_cnt--;
- } else {
- npn = np->n_next;
- pnp = np;
- }
- } /*for(pnp)*/
- } /*for(npp)*/
-}
-
-#ifdef PURGE_ZONE
-static void purge_z_2 __P((struct hashbuf *, int));
-static bottom_of_zone __P((struct databuf *, int));
-
-void
-purge_zone(dname, htp, class)
- const char *dname;
- register struct hashbuf *htp;
- int class;
-{
- const char *fname;
- struct databuf *dp, *pdp;
- struct namebuf *np;
- struct hashbuf *phtp = htp;
-
- dprintf(1, (ddt, "purge_zone(%s,%d)\n", dname, class));
- if ((np = nlookup(dname, &phtp, &fname, 0)) && dname == fname &&
- !ns_wildcard(NAME(*np))) {
- for (pdp = NULL, dp = np->n_data; dp != NULL; ) {
- if (dp->d_class == class)
- dp = rm_datum(dp, np, pdp);
- else {
- pdp = dp;
- dp = dp->d_next;
- }
- }
-
- if (np->n_hash) {
- purge_z_2(np->n_hash, class);
- if (np->n_hash->h_cnt == 0) {
- free((char*)np->n_hash);
- np->n_hash = NULL;
- }
- }
-
- /* remove entry from cache, if required */
- if ((np->n_hash == NULL) && (np->n_data == NULL)) {
- struct namebuf **npp, **nppend;
- struct namebuf *npn, *pnp, *nnp;
-
- dprintf(3,(ddt, "purge_zone: cleaning cache\n"));
-
- /* walk parent hashtable looking for ourself */
- if (np->n_parent)
- phtp = np->n_parent->n_hash;
- else
- phtp = htp; /* top / root zone */
-
- if (phtp) {
- nppend = phtp->h_tab + phtp->h_size;
- for (npp = phtp->h_tab; npp < nppend; npp++) {
- for (pnp = NULL, nnp = *npp;
- nnp != NULL;
- nnp = npn) {
- if (nnp == np) {
- dprintf(3, (ddt,
- "purge_zone: found our selves\n"
- ));
- npn = rm_name(nnp,npp,pnp);
- phtp->h_cnt--;
- } else {
- npn = nnp->n_next;
- pnp = nnp;
- }
- }
- }
- }
- }
- }
-}
-
-static void
-purge_z_2(htp, class)
- register struct hashbuf *htp;
- register int class;
-{
- register struct databuf *dp, *pdp;
- register struct namebuf *np, *pnp, *npn;
- struct namebuf **npp, **nppend;
-
- nppend = htp->h_tab + htp->h_size;
- for (npp = htp->h_tab; npp < nppend; npp++) {
- for (pnp = NULL, np = *npp; np != NULL; np = npn) {
- if (!bottom_of_zone(np->n_data, class)) {
- for (pdp = NULL, dp = np->n_data; dp != NULL; ) {
- if (dp->d_class == class)
- dp = rm_datum(dp, np, pdp);
- else {
- pdp = dp;
- dp = dp->d_next;
- }
- }
- if (np->n_hash) {
- /* call recursively to rm subdomains */
- purge_z_2(np->n_hash, class);
-
- /* if now empty, free it */
- if (np->n_hash->h_cnt == 0) {
- free((char*)np->n_hash);
- np->n_hash = NULL;
- }
- }
- }
-
- if ((np->n_hash == NULL) && (np->n_data == NULL)) {
- npn = rm_name(np, npp, pnp);
- htp->h_cnt--;
- } else {
- npn = np->n_next;
- pnp = np;
- }
- }
- }
-}
-
-static int
-bottom_of_zone(dp, class)
- struct databuf *dp;
- int class;
-{
- for ( ; dp ; dp = dp->d_next) {
- if (dp->d_class != class)
- continue;
- if (dp->d_zone == 0)
- continue;
-#ifdef NCACHE
- if (dp->d_rcode) /* this should not occur */
- continue;
-#endif
- if (dp->d_type == T_SOA)
- return (1);
- }
- dprintf(3, (ddt, "bottom_of_zone() == 0\n"));
- return (0);
-}
-#endif
-
-/*
- * Handle XFER limit for a nameserver.
- */
-static int
-nxfers(zp, delta)
- struct zoneinfo *zp;
- int delta;
-{
- struct in_addr nsa;
- struct nameser *nsp;
- int ret;
-
- if (zp->z_xaddr.s_addr)
- nsa = zp->z_xaddr; /* qserial overrode address */
- else if (!zp->z_addrcnt)
- return (-1);
- else
- nsa = zp->z_addr[0]; /* first ns holds zone's xfer limit */
-
- if (!(nsp = nameserFind(nsa, NS_F_INSERT)))
- return (-1); /* probably ENOMEM */
-
- ret = nsp->xfers;
- if (delta < 0 && -delta > ret)
- return (-1); /* taking more than we have */
-
- nsp->xfers += delta;
- return (ret);
-}
-
-/*
- * Abort an xfer that has taken too long.
- */
-static void
-abortxfer(zp)
- struct zoneinfo *zp;
-{
- if (zp->z_flags & (Z_XFER_GONE|Z_XFER_ABORTED)) {
- int i;
-
- for (i = 0; i < MAX_XFERS_RUNNING; i++) {
- if (xferstatus[i].xfer_pid == zp->z_xferpid) {
- xferstatus[i].xfer_pid = 0;
- xferstatus[i].xfer_state = XFER_IDLE;
- break;
- }
- }
-
- if (zp->z_flags & Z_XFER_GONE)
- syslog(LOG_WARNING,
- "zone transfer timeout for \"%s\"; pid %lu missing",
- zp->z_origin, (u_long)zp->z_xferpid);
- else if (kill(zp->z_xferpid, SIGKILL) == -1)
- syslog(LOG_WARNING,
- "zone transfer timeout for \"%s\"; kill pid %lu: %m",
- zp->z_origin, (u_long)zp->z_xferpid);
- else
- syslog(LOG_WARNING,
-"zone transfer timeout for \"%s\"; second kill\
-pid %lu - forgetting, processes may accumulate",
- zp->z_origin, (u_long)zp->z_xferpid);
-
- zp->z_xferpid = 0;
- xfers_running--;
- (void)nxfers(zp, -1);
- zp->z_flags &= ~(Z_XFER_RUNNING|Z_XFER_ABORTED|Z_XFER_GONE);
- } else if (kill(zp->z_xferpid, SIGKILL) == -1) {
- if (errno == ESRCH)
- /* No warning on first time, it may have just exited */
- zp->z_flags |= Z_XFER_GONE;
- else {
- syslog(LOG_WARNING,
- "zone transfer timeout for \"%s\"; pid %lu kill failed %m",
- zp->z_origin, (u_long)zp->z_xferpid);
- zp->z_flags |= Z_XFER_ABORTED;
- }
- } else {
- syslog(LOG_NOTICE,
- "zone transfer timeout for \"%s\"; pid %lu killed",
- zp->z_origin, (u_long)zp->z_xferpid);
- zp->z_flags |= Z_XFER_ABORTED;
- }
-}
-
-/*
- * SIGCHLD signal handler: process exit of xfer's.
- * (Note: also called when outgoing transfer completes.)
- */
-SIG_FN
-reapchild()
-{
- int pid, i, save_errno;
-#if defined(sequent)
- union wait status;
-#else
- int status;
-#endif /* sequent */
-
-#if defined(MUST_REARM_SIGS)
- (void)signal(SIGCLD, (SIG_FN (*)()) reapchild);
-#endif
- save_errno = errno;
- gettime(&tt);
-#if defined(USE_WAITPID)
- while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
-#else /* USE_WAITPID */
- {
- pid = wait(&status);
-#endif /* USE_WAITPID */
- for (i = 0; i < MAX_XFERS_RUNNING; i++) {
- if (xferstatus[i].xfer_pid == pid) {
- xferstatus[i].xfer_status = status;
- xferstatus[i].xfer_state = XFER_DONE;
- needendxfer++;
- break;
- }
- }
- }
- errno = save_errno;
-}
-
-/*
- * Finish processing of of finished xfers
- */
-void
-endxfer()
-{
- register struct zoneinfo *zp;
- int exitstatus, pid, i;
-#if defined(sequent)
- union wait status;
-#else
- int status;
-#endif /* sequent */
-
- gettime(&tt);
-
- for (i = 0; i < MAX_XFERS_RUNNING; i++) {
- if (xferstatus[i].xfer_state != XFER_DONE)
- continue;
- pid = xferstatus[i].xfer_pid;
- status = xferstatus[i].xfer_status;
- exitstatus = WIFEXITED(status) ?WEXITSTATUS(status) :0;
-
- for (zp = zones; zp < &zones[nzones]; zp++) {
- if (zp->z_xferpid != pid)
- continue;
- xfers_running--;
- (void) nxfers(zp, -1);
- zp->z_xferpid = 0;
- zp->z_flags &=
- ~(Z_XFER_RUNNING|Z_XFER_ABORTED|Z_XFER_GONE);
- dprintf(1, (ddt,
- "\nendxfer: child %d zone %s returned status=%d termsig=%d\n",
- pid, zp->z_origin, exitstatus,
- WIFSIGNALED(status) ?WTERMSIG(status) :-1
- )
- );
- if (WIFSIGNALED(status)) {
- if (WTERMSIG(status) != SIGKILL) {
- syslog(LOG_NOTICE,
- "named-xfer \"%s\" exited with signal %d\n",
- zp->z_origin[0]?zp->z_origin:".",
- WTERMSIG(status));
- }
- ns_retrytime(zp, tt.tv_sec);
- } else {
- switch (exitstatus) {
- case XFER_UPTODATE:
- markUpToDate(zp);
- break;
-
- case XFER_SUCCESS:
- /* XXX should incorporate loadxfer() */
- zp->z_flags |= Z_NEED_RELOAD;
- zp->z_flags &= ~Z_SYSLOGGED;
- needzoneload++;
- break;
-
- case XFER_TIMEOUT:
- if (!(zp->z_flags & Z_SYSLOGGED)) {
- zp->z_flags |= Z_SYSLOGGED;
- syslog(LOG_NOTICE,
- "zoneref: Masters for secondary zone \"%s\" unreachable",
- zp->z_origin);
- }
- ns_retrytime(zp, tt.tv_sec);
- break;
-
- default:
- if (!(zp->z_flags & Z_SYSLOGGED)) {
- zp->z_flags |= Z_SYSLOGGED;
- syslog(LOG_NOTICE,
- "named-xfer for \"%s\" exited %d",
- zp->z_origin,
- exitstatus);
- }
- /* FALLTHROUGH */
- case XFER_FAIL:
- zp->z_flags |= Z_SYSLOGGED;
- ns_retrytime(zp, tt.tv_sec);
- break;
- }
- break;
- }
- }
- xferstatus[i].xfer_state = XFER_IDLE;
- xferstatus[i].xfer_pid = 0;
- }
- releasesigchld();
- tryxfer();
-}
-
-/*
- * Try to start some xfers - new "fair scheduler" by Bob Heiney @DEC (1995)
- */
-static void
-tryxfer() {
- static struct zoneinfo *zp = NULL;
- static struct zoneinfo *lastzones = NULL;
- static int lastnzones = 0;
- struct zoneinfo *startzp, *stopzp;
-
- /* initialize, and watch out for changes in zones! */
- if (lastzones != zones) {
- if (lastzones != NULL)
- syslog(LOG_INFO, "zones changed: %p != %p",
- lastzones, zones);
- lastzones = zones;
- zp = zones;
- }
-
- /* did zones shrink? */
- if (lastnzones > nzones) {
- syslog(LOG_INFO, "zones shrunk");
- zp = zones;
- }
- lastnzones = nzones;
-
- if (zp == zones)
- stopzp = &zones[nzones-1];
- else
- stopzp = zp - 1;
-
- dprintf(3, (ddt, "tryxfer start zp=%p stopzp=%p def=%d running=%d\n",
- zp, stopzp, xfers_deferred, xfers_running));
-
- startzp = zp;
- for (;;) {
- int xfers;
-
- if (!xfers_deferred || xfers_running >= max_xfers_running)
- break;
-
- if ((xfers = nxfers(zp, 0)) != -1 &&
- xfers < max_xfers_per_ns &&
- (zp->z_flags & Z_NEED_XFER)) {
- nxfers(zp, 1);
- xfers_deferred--;
- startxfer(zp);
- }
-
- if (zp == stopzp) {
- dprintf(3, (ddt, "tryxfer stop mark\n"));
- zp = startzp;
- break;
- }
-
- zp++;
- /* wrap around? */
- if (zp == &zones[nzones])
- zp = zones;
- }
- dprintf(3, (ddt, "tryxfer stop zp=%p\n", zp));
-
- if (!needmaint)
- sched_maint();
-}
-
-/*
- * Reload zones whose transfers have completed.
- */
-void
-loadxfer() {
- register struct zoneinfo *zp;
-
- gettime(&tt);
- for (zp = zones; zp < &zones[nzones]; zp++) {
- if (zp->z_flags & Z_NEED_RELOAD) {
- dprintf(1, (ddt, "loadxfer() \"%s\"\n",
- zp->z_origin[0] ? zp->z_origin : "."));
- zp->z_flags &= ~(Z_NEED_RELOAD|Z_AUTH);
- remove_zone(hashtab, zp - zones
-#ifdef CLEANCACHE
- , 1
-#endif
- );
-#ifdef PURGE_ZONE
- purge_zone(zp->z_origin, hashtab, zp->z_class);
-#endif
- if (!db_load(zp->z_source, zp->z_origin, zp, NULL))
- zp->z_flags |= Z_AUTH;
- if (zp->z_flags & Z_TMP_FILE)
- (void) unlink(zp->z_source);
- }
- }
- if (!needmaint)
- sched_maint();
-}
-
-/*
- * Add this zone to the set of those needing transfers.
- */
-static void
-addxfer(zp)
- struct zoneinfo *zp;
-{
- if (!(zp->z_flags & Z_NEED_XFER)) {
- zp->z_flags |= Z_NEED_XFER;
- xfers_deferred++;
- tryxfer();
- }
-}
OpenPOWER on IntegriCloud