summaryrefslogtreecommitdiffstats
path: root/contrib/bind/bin/named/ns_maint.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind/bin/named/ns_maint.c')
-rw-r--r--contrib/bind/bin/named/ns_maint.c210
1 files changed, 148 insertions, 62 deletions
diff --git a/contrib/bind/bin/named/ns_maint.c b/contrib/bind/bin/named/ns_maint.c
index 952774f..b5ed644 100644
--- a/contrib/bind/bin/named/ns_maint.c
+++ b/contrib/bind/bin/named/ns_maint.c
@@ -1,6 +1,6 @@
#if !defined(lint) && !defined(SABER)
static const char sccsid[] = "@(#)ns_maint.c 4.39 (Berkeley) 3/2/91";
-static const char rcsid[] = "$Id: ns_maint.c,v 8.105 2000/07/17 07:25:00 vixie Exp $";
+static const char rcsid[] = "$Id: ns_maint.c,v 8.117 2001/01/25 05:50:55 marka Exp $";
#endif /* not lint */
/*
@@ -120,14 +120,14 @@ static const char rcsid[] = "$Id: ns_maint.c,v 8.105 2000/07/17 07:25:00 vixie E
#include <isc/eventlib.h>
#include <isc/logging.h>
#include <isc/memcluster.h>
-
#include <isc/dst.h>
+#include <isc/misc.h>
#include "port_after.h"
#include "named.h"
-static int nxfers(struct zoneinfo *, int),
+static int nxfers(struct zoneinfo *),
bottom_of_zone(struct databuf *, int);
static void startxfer(struct zoneinfo *),
@@ -135,19 +135,18 @@ static void startxfer(struct zoneinfo *),
tryxfer(void),
purge_z_2(struct hashbuf *, int);
static int purge_nonglue_2(const char *, struct hashbuf *,
- int, int);
+ int, int, int);
#ifndef HAVE_SPAWNXFER
static pid_t spawnxfer(char **, struct zoneinfo *);
#endif
-static time_t stats_time; /* Redundant ??? XXX ogud */
-
/* State of all running zone transfers */
static struct {
- pid_t xfer_pid;
- int xfer_state; /* see below */
- WAIT_T xfer_status;
+ pid_t xfer_pid;
+ int xfer_state; /* see below */
+ WAIT_T xfer_status;
+ struct in_addr xfer_addr;
} xferstatus[MAX_XFERS_RUNNING];
#define XFER_IDLE 0
@@ -642,41 +641,115 @@ qserial_answer(struct qinfo *qp) {
/*
* Writes TSIG key info for an address to a file, optionally opening it first.
+ * Returns:
+ * -1: Error.
+ * 0: No action taken.
+ * 1: Tsig info successfully written.
*/
static int
-write_tsig_info(struct in_addr addr, char *name, int *fd, int creat_failed) {
+write_tsig_info(struct in_addr addr, char *name, int *fd) {
server_info si;
DST_KEY *dst_key;
int tsig_fd = *fd;
char tsig_str[1024], secret_buf64[172];
u_char secret_buf[128];
- int secret_len;
+ int secret_len, len;
si = find_server(addr);
if (si == NULL || si->key_list == NULL || si->key_list->first == NULL)
return(0);
dst_key = si->key_list->first->key;
- if (tsig_fd < 0 && creat_failed == 0) {
- *fd = tsig_fd = creat(name, S_IRUSR);
+ if (tsig_fd == -1) {
+ *fd = tsig_fd = mkstemp(name);
if (tsig_fd < 0) {
ns_warning(ns_log_default,
- "write_tsig_info: creat(%s) for TSIG info failed",
+ "write_tsig_info: mkstemp(%s) for TSIG info failed",
name);
return(-1);
}
(void) fchown(tsig_fd, user_id, group_id);
}
- if (creat_failed != 0)
- return(-1);
+
memset(secret_buf, 0, sizeof(secret_buf));
secret_len = dst_key_to_buffer(dst_key, secret_buf, sizeof(secret_buf));
- b64_ntop(secret_buf, secret_len, secret_buf64, sizeof(secret_buf64));
+ if (secret_len == 0)
+ return (-1);
+ len = b64_ntop(secret_buf, secret_len, secret_buf64,
+ sizeof(secret_buf64));
+ if (len == -1)
+ return (-1);
+ /* We need snprintf! */
+ if (strlen(dst_key->dk_key_name) + len + sizeof("XXX.XXX.XXX.XXX"),
+ sizeof("123") + 5 > sizeof(tsig_str))
+ return (-1);
sprintf(tsig_str, "%s\n%s\n%d\n%s\n",
inet_ntoa(addr), dst_key->dk_key_name, dst_key->dk_alg,
secret_buf64);
- write(tsig_fd, tsig_str, strlen(tsig_str));
- return (0);
+ len = strlen(tsig_str);
+ if (write(tsig_fd, tsig_str, strlen(tsig_str)) != len)
+ return (-1);
+ return (1);
+}
+
+/*
+ * Returns number of tsigs written or -1.
+ */
+static int
+write_tsigs(struct zoneinfo *zp, char *tsig_name) {
+ struct in_addr a;
+ int tsig_ret;
+ int tsig_fd = -1;
+ int cnt;
+ int records = 0;
+
+ for (cnt = 0; cnt < zp->z_xaddrcnt; cnt++) {
+ a = zp->z_xaddr[cnt];
+ if (aIsUs(a) && ns_port == zp->z_port)
+ continue;
+
+ tsig_ret = write_tsig_info(a, tsig_name, &tsig_fd);
+ switch (tsig_ret) {
+ case -1:
+ goto error;
+ case 0:
+ break;
+ case 1:
+ records++;
+ break;
+ }
+ }
+
+ if (tsig_fd != -1)
+ close(tsig_fd);
+ return (records);
+
+ error:
+ if (tsig_fd != -1) {
+ unlink(tsig_name);
+ close(tsig_fd);
+ }
+ return (-1);
+}
+
+#ifdef BIND_IXFR
+static int
+supports_ixfr(struct zoneinfo *zp) {
+ int cnt = 0;
+ for (cnt = 0; cnt < zp->z_xaddrcnt; cnt++) {
+ struct in_addr a;
+ server_info si;
+
+ a = zp->z_xaddr[cnt];
+ if (aIsUs(a) && ns_port == zp->z_port)
+ continue;
+ si = find_server(a);
+
+ if (si != NULL && (si->flags & SERVER_INFO_SUPPORT_IXFR) != 0)
+ return(1);
+ }
+ return(0);
}
+#endif
/*
* Start an asynchronous zone transfer for a zone. Depends on current time
@@ -693,8 +766,7 @@ startxfer(struct zoneinfo *zp) {
char port_str[10];
char class_str[10];
char src_str[20];
- int tsig_fd = -1;
- char tsig_name[MAXPATHLEN+1], *s;
+ char tsig_name[MAXPATHLEN+1];
int tsig_ret = 0;
ns_debug(ns_log_default, 1, "startxfer() %s",
@@ -706,9 +778,9 @@ startxfer(struct zoneinfo *zp) {
argv[argc++] = "-f";
argv[argc++] = zp->z_source;
#ifdef BIND_IXFR
- if (zp->z_ixfr_tmp) {
- argv[argc++] = "-i";
- argv[argc++] = zp->z_ixfr_tmp;
+ if (supports_ixfr(zp) && zp->z_ixfr_tmp != NULL) {
+ argv[argc++] = "-i";
+ argv[argc++] = zp->z_ixfr_tmp;
}
#endif
if (zp->z_serial != 0) {
@@ -731,12 +803,6 @@ startxfer(struct zoneinfo *zp) {
argv[argc++] = "-P";
sprintf(port_str, "%d", ntohs(zp->z_port) != 0 ? zp->z_port : ns_port);
argv[argc++] = port_str;
- argv[argc++] = "-T";
- sprintf(tsig_name, "%s.%d", zp->z_origin, getpid());
- s = tsig_name;
- while ((s = strchr(s, '/')) != NULL)
- *s = '_';
- argv[argc++] = tsig_name;
#ifdef STUBS
if (zp->z_type == Z_STUB)
argv[argc++] = "-S";
@@ -762,6 +828,22 @@ startxfer(struct zoneinfo *zp) {
zp->z_xaddr[zp->z_xaddrcnt] =
zp->z_addr[zp->z_xaddrcnt];
}
+
+ /*
+ * Store TSIG keys if we have them.
+ */
+ strcpy(tsig_name, "tsigs.XXXXXX");
+ tsig_ret = write_tsigs(zp, tsig_name);
+ if (tsig_ret == -1) {
+ ns_error(ns_log_xfer_in, "unable to write tsig info: '%s'",
+ zp->z_origin);
+ return;
+ }
+ if (tsig_ret != 0) {
+ argv[argc++] = "-T";
+ argv[argc++] = tsig_name;
+ }
+
/*
* Copy the server ip addresses into argv, after converting
* to ascii and saving the static inet_ntoa result.
@@ -790,10 +872,7 @@ startxfer(struct zoneinfo *zp) {
argv[argc++] = "axfr";
}
#endif
- tsig_ret = write_tsig_info(a, tsig_name, &tsig_fd, tsig_ret);
}
- if (tsig_fd > 0)
- close(tsig_fd);
argv[argc] = NULL;
@@ -830,7 +909,6 @@ startxfer(struct zoneinfo *zp) {
ns_warning(ns_log_default,
"startxfer: too many xfers running");
zp->z_time = tt.tv_sec + 10;
- (void)nxfers(zp, -1);
return;
}
@@ -842,6 +920,7 @@ startxfer(struct zoneinfo *zp) {
xferstatus[i].xfer_state = XFER_RUNNING;
xferstatus[i].xfer_pid = pid; /* XXX - small race condition here if we
* can't hold signals */
+ xferstatus[i].xfer_addr = zp->z_xaddr[0];
ns_debug(ns_log_default, 1, "started xfer child %d", pid);
zp->z_flags &= ~Z_NEED_XFER;
zp->z_flags |= Z_XFER_RUNNING;
@@ -1102,11 +1181,12 @@ remove_zone(struct zoneinfo *zp, const char *verb) {
memset(zp, 0, sizeof(*zp));
zp->z_type = z_nil; /* Pedantic; memset() did it. */
INIT_LINK(zp, z_reloadlink);
+ INIT_LINK(zp, z_freelink);
free_zone(zp);
}
int
-purge_nonglue(const char *dname, struct hashbuf *htp, int class) {
+purge_nonglue(const char *dname, struct hashbuf *htp, int class, int log) {
const char *fname;
struct namebuf *np;
struct hashbuf *phtp = htp;
@@ -1127,7 +1207,7 @@ purge_nonglue(const char *dname, struct hashbuf *htp, int class) {
h = htp;
else
h = np->n_hash;
- errs += purge_nonglue_2(dname, h, class, 0);
+ errs += purge_nonglue_2(dname, h, class, 0, log);
if (h->h_cnt == 0 && !root_zone) {
rm_hash(np->n_hash);
np->n_hash = NULL;
@@ -1157,7 +1237,7 @@ valid_glue(struct databuf *dp, char *name, int belowcut) {
/* NOKEY is in parent zone otherwise child zone */
if (dp->d_type == T_KEY && dp->d_size == 4 &&
- (dp->d_data[0] & 0xc6) == 0xc2)
+ (dp->d_data[0] & 0xc3) == 0xc1)
return (1);
/* NXT & KEY records may be signed */
@@ -1169,7 +1249,7 @@ valid_glue(struct databuf *dp, char *name, int belowcut) {
static int
purge_nonglue_2(const char *dname, struct hashbuf *htp, int class,
- int belowcut)
+ int belowcut, int log)
{
struct databuf *dp, *pdp;
struct namebuf *np, *pnp, *npn;
@@ -1197,7 +1277,8 @@ purge_nonglue_2(const char *dname, struct hashbuf *htp, int class,
if (dp->d_class == class &&
zonecut &&
!valid_glue(dp, name, belowcut)) {
- ns_error(ns_log_db,
+ if (log)
+ ns_error(ns_log_db,
"zone: %s/%s: non-glue record %s bottom of zone: %s/%s",
*dname ? dname : ".",
p_class(dp->d_class),
@@ -1207,7 +1288,8 @@ purge_nonglue_2(const char *dname, struct hashbuf *htp, int class,
p_type(dp->d_type));
dp = rm_datum(dp, np, pdp,
NULL);
- errs++;
+ if (log)
+ errs++;
} else {
pdp = dp;
dp = dp->d_next;
@@ -1222,7 +1304,8 @@ purge_nonglue_2(const char *dname, struct hashbuf *htp, int class,
np->n_hash,
class,
zonecut ||
- belowcut);
+ belowcut,
+ log);
/* if now empty, free it */
if (np->n_hash->h_cnt == 0) {
@@ -1356,11 +1439,13 @@ bottom_of_zone(struct databuf *dp, int class) {
/*
* Handle XFER limit for a nameserver.
*/
+
+
static int
-nxfers(struct zoneinfo *zp, int delta) {
+nxfers(struct zoneinfo *zp) {
struct in_addr nsa;
- struct nameser *nsp;
int ret;
+ int i;
if (zp->z_xaddrcnt != 0)
nsa = zp->z_xaddr[0]; /* first ns holds zone's xfer limit */
@@ -1368,15 +1453,12 @@ nxfers(struct zoneinfo *zp, int delta) {
nsa = zp->z_addr[0]; /* first ns holds zone's xfer limit */
else
return (-1);
-
- 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;
+
+ ret = 0;
+ for (i = 0; i < MAX_XFERS_RUNNING; i++)
+ if (xferstatus[i].xfer_status == XFER_RUNNING &&
+ xferstatus[i].xfer_addr.s_addr == nsa.s_addr)
+ ret++;
return (ret);
}
@@ -1413,7 +1495,6 @@ pid %lu - forgetting, processes may accumulate",
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, SIGTERM) == -1) {
if (errno == ESRCH)
@@ -1479,7 +1560,6 @@ endxfer() {
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);
@@ -1509,7 +1589,9 @@ endxfer() {
if (exitstatus == XFER_SUCCESSAXFRIXFRFILE) {
zp->z_xferpid = XFER_ISAXFRIXFR;
}
- movefile(zp->z_ixfr_tmp, zp->z_source);
+ if (zp->z_ixfr_tmp != NULL)
+ isc_movefile(zp->z_ixfr_tmp,
+ zp->z_source);
/* XXX should incorporate loadxfer() */
zp->z_flags |= Z_NEED_RELOAD;
zp->z_flags &= ~Z_SYSLOGGED;
@@ -1529,19 +1611,24 @@ endxfer() {
(void)unlink(zp->z_updatelog);
(void)unlink(zp->z_ixfr_base);
- movefile(zp->z_ixfr_tmp,
- zp->z_ixfr_base);
+ isc_movefile(zp->z_ixfr_tmp,
+ zp->z_ixfr_base);
(void)unlink(zp->z_ixfr_tmp);
if (zonedump(zp, ISIXFR) < 0)
ns_warning(ns_log_db,
"error in write ixfr updates to zone file %s",
zp ->z_source);
- } else
+ ns_refreshtime(zp, tt.tv_sec);
+ sched_zone_maint(zp);
+ } else {
ns_notice(ns_log_default,
"IXFR Merge failed %s",
zp->z_ixfr_tmp);
zp->z_flags &=
~(Z_XFER_RUNNING|Z_XFER_ABORTED|Z_XFER_GONE);
+ ns_retrytime(zp, tt.tv_sec);
+ sched_zone_maint(zp);
+ }
break;
case XFER_TIMEOUT:
@@ -1622,10 +1709,9 @@ tryxfer() {
xfers_running >= server_options->transfers_in)
break;
- if ((xfers = nxfers(zp, 0)) != -1 &&
+ if ((xfers = nxfers(zp)) != -1 &&
xfers < server_options->transfers_per_ns &&
(zp->z_flags & Z_NEED_XFER)) {
- nxfers(zp, 1);
xfers_deferred--;
startxfer(zp);
sched_zone_maint(zp);
@@ -1827,7 +1913,7 @@ ns_reload(void) {
qflush();
sq_flush(NULL);
reloading++; /* To force transfer if secondary and backing up. */
- ns_init(conffile);
+ confmtime = ns_init(conffile);
time(&resettime);
reloading--;
ns_notice(ns_log_default, "Ready to answer queries.");
@@ -1875,6 +1961,7 @@ make_new_zones(void) {
block_signals();
for (n = 0; n < NEWZONES; n++) {
INIT_LINK(&zones[nzones], z_reloadlink);
+ INIT_LINK(&zones[nzones], z_freelink);
if (nzones != 0)
free_zone(&zones[nzones]);
nzones++;
@@ -1906,7 +1993,6 @@ spawnxfer(char **argv, struct zoneinfo *zp) {
execv(server_options->named_xfer, argv);
ns_error(ns_log_default, "can't exec %s: %s",
server_options->named_xfer, strerror(errno));
- (void)nxfers(zp, -1);
_exit(XFER_FAIL); /* Avoid duplicate buffer flushes. */
}
return (pid);
OpenPOWER on IntegriCloud