summaryrefslogtreecommitdiffstats
path: root/contrib/bind/bin/named/ns_config.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind/bin/named/ns_config.c')
-rw-r--r--contrib/bind/bin/named/ns_config.c1153
1 files changed, 922 insertions, 231 deletions
diff --git a/contrib/bind/bin/named/ns_config.c b/contrib/bind/bin/named/ns_config.c
index 4f95410..67bffbd 100644
--- a/contrib/bind/bin/named/ns_config.c
+++ b/contrib/bind/bin/named/ns_config.c
@@ -1,9 +1,9 @@
#if !defined(lint) && !defined(SABER)
-static char rcsid[] = "$Id: ns_config.c,v 8.35 1998/05/05 19:44:48 halley Exp $";
+static const char rcsid[] = "$Id: ns_config.c,v 8.104 1999/11/08 23:09:42 vixie Exp $";
#endif /* not lint */
/*
- * Copyright (c) 1996, 1997 by Internet Software Consortium.
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -19,12 +19,33 @@ static char rcsid[] = "$Id: ns_config.c,v 8.35 1998/05/05 19:44:48 halley Exp $"
* SOFTWARE.
*/
+/*
+ * Portions Copyright (c) 1999 by Check Point Software Technologies, Inc.
+ *
+ * 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 Check Point Software Technologies Incorporated 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 CHECK POINT SOFTWARE TECHNOLOGIES
+ * INCORPORATED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL CHECK POINT SOFTWARE TECHNOLOGIES INCORPRATED
+ * 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.
+ */
+
#include "port_before.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
@@ -46,6 +67,8 @@ static char rcsid[] = "$Id: ns_config.c,v 8.35 1998/05/05 19:44:48 halley Exp $"
#include <isc/logging.h>
#include <isc/memcluster.h>
+#include <isc/dst.h>
+
#include "port_after.h"
#ifdef HAVE_GETRUSAGE /* XXX */
@@ -55,6 +78,8 @@ static char rcsid[] = "$Id: ns_config.c,v 8.35 1998/05/05 19:44:48 halley Exp $"
#include "named.h"
#include "ns_parseutil.h"
+/* Private. */
+
static int tmpnum = 0;
static int config_initialized = 0;
@@ -90,8 +115,7 @@ free_zone_contents(struct zoneinfo *zp, int undefine_sym) {
INSIST(zp != NULL);
if (undefine_sym)
- undefine_symbol(zone_symbol_table, zp->z_origin,
- (zp->z_type << 16) | zp->z_class);
+ undefine_symbol(zone_symbol_table, zp->z_origin, zp->z_class);
if (zp->z_flags & Z_TIMER_SET) {
free_zone_timerinfo(zp);
if (evClearTimer(ev, zp->z_timer) < 0)
@@ -102,22 +126,44 @@ free_zone_contents(struct zoneinfo *zp, int undefine_sym) {
}
if (zp->z_origin != NULL)
freestr(zp->z_origin);
+ zp->z_origin = NULL;
if (zp->z_source != NULL)
freestr(zp->z_source);
+ zp->z_source = NULL;
+ if (zp->z_ixfr_base != NULL)
+ freestr(zp->z_ixfr_base);
+ zp->z_ixfr_base = NULL;
+ if (zp->z_ixfr_tmp != NULL)
+ freestr(zp->z_ixfr_tmp);
+ zp->z_ixfr_tmp = NULL;
if (zp->z_update_acl != NULL)
free_ip_match_list(zp->z_update_acl);
+ zp->z_update_acl = NULL;
if (zp->z_query_acl != NULL)
free_ip_match_list(zp->z_query_acl);
+ zp->z_query_acl = NULL;
if (zp->z_transfer_acl != NULL)
free_ip_match_list(zp->z_transfer_acl);
+ zp->z_transfer_acl = NULL;
#ifdef BIND_UPDATE
if (zp->z_updatelog != NULL)
freestr(zp->z_updatelog);
+ zp->z_updatelog = NULL;
#endif /* BIND_UPDATE */
+#ifdef BIND_NOTIFY
+ if (zp->z_also_notify != NULL)
+ memput(zp->z_also_notify,
+ zp->z_notify_count * sizeof *zp->z_also_notify);
+ zp->z_also_notify = NULL;
+#endif
+ block_signals();
+ if (LINKED(zp, z_reloadlink))
+ UNLINK(reloadingzones, zp, z_reloadlink);
+ unblock_signals();
}
static void
-free_zone(struct zoneinfo *zp) {
+release_zone(struct zoneinfo *zp) {
INSIST(zp != NULL);
free_zone_contents(zp, 0);
@@ -125,16 +171,16 @@ free_zone(struct zoneinfo *zp) {
}
struct zoneinfo *
-find_zone(const char *name, int type, int class) {
+find_zone(const char *name, int class) {
struct zoneinfo *zp;
symbol_value value;
- ns_debug(ns_log_config, 3, "find_zone(%s,%d,%d)", name, type, class);
- if (lookup_symbol(zone_symbol_table, name,
- (type<<16) | class, &value)) {
+ ns_debug(ns_log_config, 3, "find_zone(%s, %d)",
+ *name ? name : ".", class);
+ if (lookup_symbol(zone_symbol_table, name, class, &value)) {
INSIST(value.integer >= 0 && value.integer < nzones);
- ns_debug(ns_log_config, 3,
- "find_zone: existing zone %d", value.integer);
+ ns_debug(ns_log_config, 3, "find_zone: existing zone %d",
+ value.integer);
zp = &zones[value.integer];
return (zp);
}
@@ -146,33 +192,11 @@ static struct zoneinfo *
new_zone(int class, int type) {
struct zoneinfo *zp;
- if (zones != NULL) {
- if (type == z_hint) {
- zp = &zones[0];
- return (zp);
- }
-
- for (zp = &zones[1]; zp < &zones[nzones]; zp++)
- if (zp->z_type == z_nil)
- return (zp);
- }
-
- /*
- * This code assumes that nzones never decreases.
- */
- if (nzones % 64 == 0) {
- ns_debug(ns_log_config, 1, "Reallocating zones structure");
- zp = (struct zoneinfo *)
- memget((64 + nzones) * sizeof(struct zoneinfo));
- if (zp == NULL)
- panic("no memory for more zones", NULL);
- memcpy(zp, zones, nzones * sizeof(struct zoneinfo));
- memset(&zp[nzones], 0, 64 * sizeof(struct zoneinfo));
- memput(zones, nzones * sizeof(struct zoneinfo));
- zones = zp;
- }
- zp = &zones[nzones++];
+ if (EMPTY(freezones))
+ make_new_zones();
+ zp = HEAD(freezones);
+ UNLINK(freezones, zp, z_freelink);
return (zp);
}
@@ -181,7 +205,6 @@ new_zone(int class, int type) {
*/
static int
validate_zone(struct zoneinfo *zp) {
- int warnings = 0;
char filename[MAXPATHLEN+1];
/* Check name */
@@ -204,7 +227,13 @@ validate_zone(struct zoneinfo *zp) {
zp->z_origin);
return (0);
}
- if (zp->z_type == z_hint && strcasecmp(zp->z_origin, "") != 0) {
+ if (zp->z_type == z_cache && ns_samename(zp->z_origin, "") != 1) {
+ ns_error(ns_log_config,
+ "only the root zone may be a cache zone (zone '%s')",
+ zp->z_origin);
+ return (0);
+ }
+ if (zp->z_type == z_hint && ns_samename(zp->z_origin, "") != 1) {
ns_error(ns_log_config,
"only the root zone may be a hint zone (zone '%s')",
zp->z_origin);
@@ -229,12 +258,25 @@ validate_zone(struct zoneinfo *zp) {
return (0);
}
+ if (zp->z_ixfr_base != NULL && strlen(zp->z_ixfr_base) > MAXPATHLEN) {
+ ns_error(ns_log_config, "ixfr filename too long for zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ if (zp->z_ixfr_tmp != NULL && strlen(zp->z_ixfr_tmp) > MAXPATHLEN) {
+ ns_error(ns_log_config, "tmp ixfr filename too long for zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+
/* Check masters */
if (zp->z_addrcnt != 0) {
- if (zp->z_type != z_slave && zp->z_type != z_stub) {
+ if (zp->z_type == z_master || zp->z_type == z_hint ||
+ zp->z_type == z_cache) {
ns_error(ns_log_config,
"'masters' statement present for %s zone '%s'",
- (zp->z_type == z_master) ? "master" : "hint",
+ (zp->z_type == z_master) ? "master" :
+ (zp->z_type == z_hint) ? "hint" : "cache",
zp->z_origin);
return (0);
}
@@ -247,6 +289,39 @@ validate_zone(struct zoneinfo *zp) {
}
}
+ /* Check allow-update and allow-transfer. */
+ if (zp->z_update_acl || zp->z_transfer_acl) {
+ if (zp->z_type != z_master && zp->z_type != z_slave) {
+ ns_error(ns_log_config,
+ "'allow-{update,transfer}' option for non-{master,slave} zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ }
+
+ /* Check allow-query. */
+ if (zp->z_query_acl) {
+ if (zp->z_type != z_master &&
+ zp->z_type != z_slave &&
+ zp->z_type != z_stub) {
+ ns_error(ns_log_config,
+ "'allow-query' option for non-{master,slave,stub} zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ }
+
+#ifdef BIND_NOTIFY
+ /* Check notify */
+ if (zp->z_notify != znotify_use_default) {
+ if (zp->z_type != z_master && zp->z_type != z_slave) {
+ ns_error(ns_log_config,
+ "'notify' given for non-master, non-slave zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ }
+
/* Check also-notify */
if (zp->z_notify_count != 0) {
if (zp->z_type != z_master && zp->z_type != z_slave) {
@@ -256,9 +331,43 @@ validate_zone(struct zoneinfo *zp) {
return (0);
}
}
+#endif
#ifdef BIND_UPDATE
/* XXX need more checking here */
+ if (!zp->z_updatelog && zp->z_source) {
+ /* XXX OS-specific filename validation here */
+ if ((strlen(zp->z_source) + (sizeof ".log" - 1)) >
+ MAXPATHLEN) {
+ ns_error(ns_log_config,
+ "filename too long for dynamic zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ /* this sprintf() is now safe */
+ sprintf(filename, "%s.log", zp->z_source);
+ zp->z_updatelog = savestr(filename, 1);
+ }
+
+ /* Check forward */
+ if (zp->z_optset & OPTION_FORWARD_ONLY) {
+ if (zp->z_type == z_hint) {
+ ns_error(ns_log_config,
+ "'forward' given for hint zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ }
+ /* Check forwarders */
+ if (zp->z_fwdtab) {
+ if (zp->z_type == z_hint) {
+ ns_error(ns_log_config,
+ "'forwarders' given for hint zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ }
+
if (zp->z_type == z_master) {
if (!zp->z_soaincrintvl)
zp->z_soaincrintvl = SOAINCRINTVL;
@@ -266,22 +375,36 @@ validate_zone(struct zoneinfo *zp) {
zp->z_dumpintvl = DUMPINTVL;
if (!zp->z_deferupdcnt)
zp->z_deferupdcnt = DEFERUPDCNT;
- if (!zp->z_updatelog) {
- /* XXX OS-specific filename validation here */
- if ((strlen(zp->z_source) + (sizeof ".log" - 1)) >
- MAXPATHLEN) {
- ns_error(ns_log_config,
- "filename too long for dynamic zone '%s'",
- zp->z_origin);
- return (0);
- }
- /* this sprintf() is now safe */
- sprintf(filename, "%s.log", zp->z_source);
- zp->z_updatelog = savestr(filename, 1);
- }
}
#endif /* BIND_UPDATE */
+ if (!zp->z_ixfr_base && zp->z_source) {
+ /* XXX OS-specific filename validation here */
+ if ((strlen(zp->z_source) + (sizeof ".ixfr" - 1)) >
+ MAXPATHLEN) {
+ ns_error(ns_log_config,
+ "filename too long for dynamic zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ /* this sprintf() is now safe */
+ sprintf(filename, "%s.ixfr", zp->z_source);
+ zp->z_ixfr_base = savestr(filename, 1);
+ }
+ if (!zp->z_ixfr_tmp && zp->z_source) {
+ /* XXX OS-specific filename validation here */
+ if ((strlen(zp->z_source) + (sizeof ".ixfr.tmp" - 1)) >
+ MAXPATHLEN) {
+ ns_error(ns_log_config,
+ "filename too long for dynamic zone '%s'",
+ zp->z_origin);
+ return (0);
+ }
+ /* this sprintf() is now safe */
+ sprintf(filename, "%s.ixfr.tmp", zp->z_source);
+ zp->z_ixfr_tmp = savestr(filename, 1);
+ }
+
return (1);
}
@@ -308,6 +431,12 @@ begin_zone(char *name, int class) {
zp->z_origin = name;
zp->z_class = class;
zp->z_checknames = not_set;
+ zp->z_log_size_ixfr = 0;
+ if (server_options->flags & OPTION_MAINTAIN_IXFR_BASE)
+ zp->z_maintain_ixfr_base = 1;
+ else
+ zp->z_maintain_ixfr_base = 0;
+ zp->z_max_log_size_ixfr = server_options->max_log_size_ixfr;
zh.opaque = zp;
return (zh);
}
@@ -318,7 +447,6 @@ begin_zone(char *name, int class) {
*/
static void
update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
- struct stat f_time;
char buf[MAXPATHLEN+1];
int i;
@@ -337,7 +465,7 @@ update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
if ((zp->z_flags & Z_DYNAMIC) && !(new_zp->z_flags & Z_DYNAMIC) &&
((zp->z_flags & Z_NEED_SOAUPDATE) ||
(zp->z_flags & Z_NEED_DUMP)))
- (void)zonedump(zp);
+ (void) zonedump(zp, ISNOTIXFR);
#endif
/*
@@ -348,6 +476,9 @@ update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
freestr(zp->z_origin);
zp->z_origin = new_zp->z_origin;
new_zp->z_origin = NULL;
+ zp->z_maintain_ixfr_base = new_zp->z_maintain_ixfr_base;
+ zp->z_max_log_size_ixfr = new_zp->z_max_log_size_ixfr;
+ zp->z_log_size_ixfr = new_zp->z_log_size_ixfr;
zp->z_class = new_zp->z_class;
zp->z_type = new_zp->z_type;
zp->z_checknames = new_zp->z_checknames;
@@ -368,11 +499,28 @@ update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
zp->z_transfer_acl = new_zp->z_transfer_acl;
new_zp->z_transfer_acl = NULL;
zp->z_max_transfer_time_in = new_zp->z_max_transfer_time_in;
-
+#ifdef BIND_NOTIFY
zp->z_notify = new_zp->z_notify;
- for (i = 0; i < new_zp->z_notify_count; i++)
- zp->z_also_notify[i] = new_zp->z_also_notify[i];
+ if (zp->z_also_notify)
+ memput(zp->z_also_notify,
+ zp->z_notify_count * sizeof *zp->z_also_notify);
+ zp->z_also_notify = new_zp->z_also_notify;
zp->z_notify_count = new_zp->z_notify_count;
+ new_zp->z_also_notify = NULL;
+ new_zp->z_notify_count = 0;
+#endif
+ if ((new_zp->z_flags & Z_FORWARD_SET) != 0)
+ zp->z_flags |= Z_FORWARD_SET;
+ else
+ zp->z_flags &= ~Z_FORWARD_SET;
+ if (zp->z_fwdtab != NULL)
+ free_forwarders(zp->z_fwdtab);
+ zp->z_fwdtab = new_zp->z_fwdtab;
+ new_zp->z_fwdtab = NULL;
+
+ zp->z_dialup = new_zp->z_dialup;
+ zp->z_options = new_zp->z_options;
+ zp->z_optset = new_zp->z_optset;
#ifdef BIND_UPDATE
if (new_zp->z_flags & Z_DYNAMIC)
@@ -387,24 +535,21 @@ update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
zp->z_updatelog = new_zp->z_updatelog;
new_zp->z_updatelog = NULL;
#endif /* BIND_UPDATE */
+ zp->z_port = new_zp->z_port;
/*
- * now deal with files
+ * Now deal with files.
*/
switch (zp->z_type) {
+ case z_cache:
+ ns_panic(ns_log_config, 1, "impossible condition");
+ break;
case z_hint:
ns_debug(ns_log_config, 1, "source = %s", new_zp->z_source);
zp->z_refresh = 0; /* No dumping. */
- /*
- * If we've loaded this file, and the file has
- * not been modified and contains no $include,
- * then there's no need to reload.
- */
- if (zp->z_source &&
- !strcmp(new_zp->z_source, zp->z_source) &&
- !(zp->z_flags & Z_INCLUDE) &&
- stat(zp->z_source, &f_time) != -1 &&
- zp->z_ftime == f_time.st_mtime) {
+ if (zp->z_source != NULL &&
+ strcmp(new_zp->z_source, zp->z_source) == 0 &&
+ (reconfiging || !zonefile_changed_p(zp))) {
ns_debug(ns_log_config, 1, "cache is up to date");
break;
}
@@ -412,28 +557,37 @@ update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
/* File has changed, or hasn't been loaded yet. */
if (zp->z_source) {
freestr(zp->z_source);
- clean_cache(fcachetab, 1);
+ purge_zone(zp->z_origin, fcachetab, zp->z_class);
}
zp->z_source = new_zp->z_source;
new_zp->z_source = NULL;
- ns_debug(ns_log_config, 1, "reloading zone");
- (void) db_load(zp->z_source, zp->z_origin, zp, NULL);
+
+ if (zp->z_ixfr_base)
+ freestr(zp->z_ixfr_base);
+ zp->z_ixfr_base = new_zp->z_ixfr_base;
+ new_zp->z_ixfr_base = NULL;
+
+ if (zp->z_ixfr_tmp)
+ freestr(zp->z_ixfr_tmp);
+ zp->z_ixfr_tmp = new_zp->z_ixfr_tmp;
+ new_zp->z_ixfr_tmp = NULL;
+
+ ns_debug(ns_log_config, 1, "reloading hint zone");
+ (void) db_load(zp->z_source, zp->z_origin, zp, NULL,
+ ISNOTIXFR);
break;
case z_master:
ns_debug(ns_log_config, 1, "source = %s", new_zp->z_source);
/*
- * If we've loaded this file, and the file has
- * not been modified and contains no $include,
+ * If we've loaded this file, and the file hasn't changed
* then there's no need to reload.
*/
- if (zp->z_source &&
- !strcmp(new_zp->z_source, zp->z_source) &&
- !(zp->z_flags & Z_INCLUDE) &&
- stat(zp->z_source, &f_time) != -1 &&
- zp->z_ftime == f_time.st_mtime) {
+ if (zp->z_source != NULL &&
+ strcmp(new_zp->z_source, zp->z_source) == 0 &&
+ (reconfiging || !zonefile_changed_p(zp))) {
ns_debug(ns_log_config, 1, "zone is up to date");
- break; /* zone is already up to date */
+ break;
}
#ifdef BIND_UPDATE
if (zp->z_source && (zp->z_flags & Z_DYNAMIC))
@@ -447,41 +601,27 @@ update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
freestr(zp->z_source);
zp->z_source = new_zp->z_source;
new_zp->z_source = NULL;
- zp->z_flags &= ~Z_AUTH;
- ns_stopxfrs(zp);
- purge_zone(zp->z_origin, hashtab, zp->z_class);
- ns_debug(ns_log_config, 1, "reloading zone");
-#ifdef BIND_UPDATE
- if (zp->z_flags & Z_DYNAMIC) {
- struct stat sb;
- if (stat(zp->z_source, &sb) < 0)
- ns_error(ns_log_config, "stat(%s) failed: %s",
- zp->z_source, strerror(errno));
- else {
- if (sb.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))
- ns_warning(ns_log_config,
- "dynamic zone file '%s' is writable",
- zp->z_source);
- }
- }
-#endif
- if (!db_load(zp->z_source, zp->z_origin, zp, NULL))
- zp->z_flags |= Z_AUTH;
- zp->z_refresh = 0; /* no maintenance needed */
- zp->z_time = 0;
-#ifdef BIND_UPDATE
- zp->z_lastupdate = 0;
- if (zp->z_flags & Z_DYNAMIC)
+ if (zp->z_ixfr_base != NULL)
+ freestr(zp->z_ixfr_base);
+ zp->z_ixfr_base = new_zp->z_ixfr_base;
+ new_zp->z_ixfr_base = NULL;
+
+ if (zp->z_ixfr_tmp != NULL)
+ freestr(zp->z_ixfr_tmp);
+ zp->z_ixfr_tmp = new_zp->z_ixfr_tmp;
+ new_zp->z_ixfr_tmp = NULL;
+
+ if (reload_master(zp) == 1) {
/*
* Note that going to primary_reload
* unconditionally reloads the zone.
*/
- if (merge_logs(zp) == 1) {
- new_zp->z_source = savestr(zp->z_source, 1);
- goto primary_reload;
- }
-#endif
+ new_zp->z_source = savestr(zp->z_source, 1);
+ new_zp->z_ixfr_base = savestr(zp->z_ixfr_base, 1);
+ new_zp->z_ixfr_tmp = savestr(zp->z_ixfr_tmp, 1);
+ goto primary_reload;
+ }
break;
case z_slave:
@@ -505,10 +645,9 @@ update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
* current zone contents, try again now in case
* we have a new server on the list.
*/
- if (zp->z_source &&
- (strcmp(new_zp->z_source, zp->z_source) ||
- (stat(zp->z_source, &f_time) == -1 ||
- (zp->z_ftime != f_time.st_mtime)))) {
+ if (zp->z_source != NULL &&
+ (strcmp(new_zp->z_source, zp->z_source) != 0 ||
+ ((!reconfiging) && zonefile_changed_p(zp)))) {
ns_debug(ns_log_config, 1,
"backup file changed or missing");
freestr(zp->z_source);
@@ -516,42 +655,60 @@ update_zone_info(struct zoneinfo *zp, struct zoneinfo *new_zp) {
zp->z_serial = 0; /* force xfer */
ns_stopxfrs(zp);
/*
- * We only need to do_reload if we have
+ * We only need to reload if we have ever
* successfully transferred the zone.
*/
- if (zp->z_flags & Z_AUTH) {
+ if ((zp->z_flags & Z_AUTH) != 0) {
zp->z_flags &= ~Z_AUTH;
/*
- * Purge old data and reload parent so that
- * NS records are present during the zone
- * transfer.
+ * Purge old data and mark the parent for
+ * reloading so that NS records are present
+ * during the zone transfer.
*/
do_reload(zp->z_origin, zp->z_type,
- zp->z_class);
+ zp->z_class, 1);
}
}
if (zp->z_source == NULL) {
zp->z_source = new_zp->z_source;
new_zp->z_source = NULL;
}
- if (!(zp->z_flags & Z_AUTH))
+
+ if (zp->z_ixfr_base != NULL)
+ freestr(zp->z_ixfr_base);
+ zp->z_ixfr_base = new_zp->z_ixfr_base;
+ new_zp->z_ixfr_base = NULL;
+
+ if (zp->z_ixfr_tmp != NULL)
+ freestr(zp->z_ixfr_tmp);
+ zp->z_ixfr_tmp = new_zp->z_ixfr_tmp;
+ new_zp->z_ixfr_tmp = NULL;
+
+ if ((zp->z_flags & Z_AUTH) == 0)
zoneinit(zp);
-#ifdef FORCED_RELOAD
else {
/*
** Force secondary to try transfer soon
** after SIGHUP.
*/
- if (!(zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING))
- && reloading) {
+ if ((zp->z_flags & (Z_QSERIAL|Z_XFER_RUNNING)) == 0 &&
+ reloading && !reconfiging) {
qserial_retrytime(zp, tt.tv_sec);
sched_zone_maint(zp);
}
}
-#endif /* FORCED_RELOAD */
+ break;
+ case z_forward:
+ /*
+ * We don't know if the forwarder's list has changed
+ * so just purge the cache. In the future we may want
+ * see if the forwarders list has changed and only
+ * do this then.
+ */
+ clean_cache_from(zp->z_origin, hashtab);
break;
}
- if ((zp->z_flags & Z_FOUND) && /* already found? */
+ if ((zp->z_flags & Z_FOUND) != 0 && /* already found? */
(zp - zones) != DB_Z_CACHE) /* cache never sets Z_FOUND */
ns_error(ns_log_config, "Zone \"%s\" declared more than once",
zp->z_origin);
@@ -582,40 +739,43 @@ end_zone(zone_config zh, int should_install) {
should_install);
if (!should_install) {
- free_zone(new_zp);
+ release_zone(new_zp);
return;
}
if (!validate_zone(new_zp)) {
ns_error(ns_log_config,
"zone '%s' did not validate, skipping", zname);
- free_zone(new_zp);
+ release_zone(new_zp);
return;
}
- zp = find_zone(new_zp->z_origin, new_zp->z_type, new_zp->z_class);
+ zp = find_zone(new_zp->z_origin, new_zp->z_class);
+ if (zp != NULL && zp->z_type != new_zp->z_type) {
+ remove_zone(zp, "redefined");
+ zp = NULL;
+ }
if (zp == NULL) {
zp = new_zone(new_zp->z_class, new_zp->z_type);
INSIST(zp != NULL);
value.integer = (zp - zones);
define_symbol(zone_symbol_table, savestr(new_zp->z_origin, 1),
- (new_zp->z_type << 16) | new_zp->z_class,
- value, SYMBOL_FREE_KEY);
+ new_zp->z_class, value, SYMBOL_FREE_KEY);
}
ns_debug(ns_log_config, 5, "zone '%s', type = %d, class = %d", zname,
new_zp->z_type, new_zp->z_class);
if (new_zp->z_source != NULL)
ns_debug(ns_log_config, 5, " file = %s", new_zp->z_source);
ns_debug(ns_log_config, 5, " checknames = %d", new_zp->z_checknames);
- if (new_zp->z_addrcnt) {
+ if (new_zp->z_addrcnt != 0) {
int i;
ns_debug(ns_log_config, 5, " masters:");
- for (i=0; i<new_zp->z_addrcnt; i++)
+ for (i = 0; i < new_zp->z_addrcnt; i++)
ns_debug(ns_log_config, 5, " %s",
inet_ntoa(new_zp->z_addr[i]));
}
update_zone_info(zp, new_zp);
- free_zone(new_zp);
+ release_zone(new_zp);
zh.opaque = NULL;
}
@@ -662,7 +822,63 @@ set_zone_checknames(zone_config zh, enum severity s) {
}
int
+set_zone_ixfr_file(zone_config zh, char *filename) {
+ struct zoneinfo *zp;
+
+ zp = zh.opaque;
+ INSIST(zp != NULL);
+
+ /* Fail if filename already set for this zone */
+ if (zp->z_ixfr_base != NULL)
+ return (0);
+ zp->z_ixfr_base = filename;
+ if (zp->z_ixfr_tmp == NULL) {
+ int len = strlen(zp->z_ixfr_base) + (sizeof ".tmp" - 1);
+ char *str = (char *) memget(len);
+
+ sprintf(str, "%s.tmp", zp->z_ixfr_base);
+ zp->z_ixfr_tmp = savestr(str, 1);
+ memput(str, len);
+ }
+
+ return (1);
+}
+
+int
+set_zone_ixfr_tmp(zone_config zh, char *filename) {
+ struct zoneinfo *zp;
+
+ zp = zh.opaque;
+ INSIST(zp != NULL);
+
+ /* Fail if filename already set for this zone */
+ if (zp->z_ixfr_tmp != NULL)
+ return (0);
+ zp->z_ixfr_tmp = filename;
+ return (1);
+}
+
+int
+set_zone_dialup(zone_config zh, int value) {
+ struct zoneinfo *zp;
+
+ zp = zh.opaque;
+ INSIST(zp != NULL);
+
+ if (value) {
+ zp->z_dialup = zdialup_yes;
+#ifdef BIND_NOTIFY
+ zp->z_notify = znotify_yes;
+#endif
+ } else
+ zp->z_dialup = zdialup_no;
+
+ return (1);
+}
+
+int
set_zone_notify(zone_config zh, int value) {
+#ifdef BIND_NOTIFY
struct zoneinfo *zp;
zp = zh.opaque;
@@ -672,6 +888,17 @@ set_zone_notify(zone_config zh, int value) {
zp->z_notify = znotify_yes;
else
zp->z_notify = znotify_no;
+#endif
+ return (1);
+}
+
+int
+set_zone_maintain_ixfr_base(zone_config zh, int value) {
+ struct zoneinfo *zp;
+
+ zp = zh.opaque;
+ INSIST(zp != NULL);
+ zp->z_maintain_ixfr_base = value;
return (1);
}
@@ -683,7 +910,7 @@ set_zone_update_acl(zone_config zh, ip_match_list iml) {
zp = zh.opaque;
INSIST(zp != NULL);
- /* Fail if checknames already set for this zone */
+ /* Fail if update_acl already set for this zone */
if (zp->z_update_acl != NULL)
return (0);
zp->z_update_acl = iml;
@@ -712,6 +939,14 @@ set_zone_query_acl(zone_config zh, ip_match_list iml) {
}
int
+set_zone_master_port(zone_config zh, u_short port) {
+ struct zoneinfo *zp = zh.opaque;
+
+ zp->z_port = port;
+ return (1);
+}
+
+int
set_zone_transfer_source(zone_config zh, struct in_addr ina) {
struct zoneinfo *zp = zh.opaque;
@@ -748,6 +983,37 @@ set_zone_transfer_time_in(zone_config zh, long max_time) {
}
int
+set_zone_max_log_size_ixfr(zone_config zh, int size) {
+ struct zoneinfo *zp;
+
+ zp = zh.opaque;
+ INSIST(zp != NULL);
+
+ zp->z_max_log_size_ixfr = size;
+ return (0);
+}
+
+int
+set_zone_pubkey(zone_config zh, const int flags, const int proto,
+ const int alg, const char *str)
+{
+ struct zoneinfo *zp;
+
+ zp = zh.opaque;
+ INSIST(zp != NULL);
+
+ INSIST(zp != NULL && zp->z_origin != NULL);
+ return (add_trusted_key(zp->z_origin, flags, proto, alg, str));
+}
+
+int
+set_trusted_key(const char *name, const int flags, const int proto,
+ const int alg, const char *str) {
+ INSIST(name != NULL);
+ return (add_trusted_key(name, flags, proto, alg, str));
+}
+
+int
add_zone_master(zone_config zh, struct in_addr address) {
struct zoneinfo *zp;
@@ -766,18 +1032,51 @@ add_zone_master(zone_config zh, struct in_addr address) {
int
add_zone_notify(zone_config zh, struct in_addr address) {
+#ifdef BIND_NOTIFY
struct zoneinfo *zp;
+ int i;
zp = zh.opaque;
INSIST(zp != NULL);
- zp->z_also_notify[zp->z_notify_count] = address;
- zp->z_notify_count++;
- if (zp->z_notify_count >= NSMAX) {
- ns_warning(ns_log_config, "also-notify set full for zone '%s'",
- zp->z_origin);
- zp->z_notify_count = NSMAX - 1;
+ /* Check for duplicates. */
+
+ for (i = 0; i < zp->z_notify_count; i++) {
+ if (memcmp(zp->z_also_notify + i,
+ &address, sizeof address) == 0) {
+ ns_warning(ns_log_config,
+ "duplicate also-notify address ignored [%s] for zone '%s'",
+ inet_ntoa(address), zp->z_origin);
+ return (1);
+ }
}
+ i = 0;
+
+ if (zp->z_also_notify == NULL) {
+ zp->z_also_notify = memget(sizeof *zp->z_also_notify);
+ if (zp->z_also_notify == NULL)
+ i = 1;
+ } else {
+ register size_t size;
+ register struct in_addr *an_tmp;
+ size = zp->z_notify_count * sizeof *zp->z_also_notify;
+ an_tmp = memget(size + sizeof *zp->z_also_notify);
+ if (an_tmp == NULL) {
+ i = 1;
+ } else {
+ memcpy(an_tmp, zp->z_also_notify, size);
+ memput(zp->z_also_notify, size);
+ zp->z_also_notify = an_tmp;
+ }
+ }
+ if (i == 0) {
+ zp->z_also_notify[zp->z_notify_count] = address;
+ zp->z_notify_count++;
+ } else {
+ ns_warning(ns_log_config, "also-notify add failed (memget) [%s] for zone '%s'",
+ inet_ntoa(address), zp->z_origin);
+ }
+#endif
return (1);
}
@@ -786,13 +1085,12 @@ add_zone_notify(zone_config zh, struct in_addr address) {
options
new_options() {
options op;
- ip_match_list iml;
- ip_match_element ime;
op = (options)memget(sizeof (struct options));
if (op == NULL)
panic("memget failed in new_options()", NULL);
+ op->version = savestr(ShortVersion, 1);
op->directory = savestr(".", 1);
op->pid_filename = savestr(_PATH_PIDFILE, 1);
op->named_xfer = savestr(_PATH_XFER, 1);
@@ -803,21 +1101,24 @@ new_options() {
op->transfers_in = DEFAULT_XFERS_RUNNING;
op->transfers_per_ns = DEFAULT_XFERS_PER_NS;
op->transfers_out = 0;
+ op->serial_queries = MAXQSERIAL;
op->transfer_format = axfr_one_answer;
op->max_transfer_time_in = MAX_XFER_TIME;
memset(&op->query_source, 0, sizeof op->query_source);
op->query_source.sin_family = AF_INET;
op->query_source.sin_addr.s_addr = htonl(INADDR_ANY);
op->query_source.sin_port = htons(0); /* INPORT_ANY */
+ op->axfr_src.s_addr = 0;
+#ifdef BIND_NOTIFY
+ op->notify_count = 0;
+ op->also_notify = NULL;
+#endif
+ op->blackhole_acl = NULL;
op->query_acl = NULL;
op->transfer_acl = NULL;
- /* default topology is { localhost; localnets; } */
- iml = new_ip_match_list();
- ime = new_ip_match_localhost();
- add_to_ip_match_list(iml, ime);
- ime = new_ip_match_localnets();
- add_to_ip_match_list(iml, ime);
- op->topology = iml;
+ op->recursion_acl = NULL;
+ op->sortlist = NULL;
+ op->topology = NULL;
op->data_size = 0UL; /* use system default */
op->stack_size = 0UL; /* use system default */
op->core_size = 0UL; /* use system default */
@@ -831,6 +1132,12 @@ new_options() {
op->clean_interval = 3600;
op->interface_interval = 3600;
op->stats_interval = 3600;
+ op->ordering = NULL;
+ op->max_ncache_ttl = DEFAULT_MAX_NCACHE_TTL;
+ op->lame_ttl = NTTL;
+ op->heartbeat_interval = 3600;
+ op->max_log_size_ixfr = 20;
+ op->minroots = MINROOTS;
return (op);
}
@@ -838,6 +1145,8 @@ void
free_options(options op) {
INSIST(op != NULL);
+ if (op->version)
+ freestr(op->version);
if (op->directory)
freestr(op->directory);
if (op->pid_filename)
@@ -850,10 +1159,22 @@ free_options(options op) {
freestr(op->stats_filename);
if (op->memstats_filename)
freestr(op->memstats_filename);
+#ifdef BIND_NOTIFY
+ if (op->also_notify)
+ free_also_notify(op);
+#endif
+ if (op->blackhole_acl)
+ free_ip_match_list(op->blackhole_acl);
if (op->query_acl)
free_ip_match_list(op->query_acl);
+ if (op->recursion_acl)
+ free_ip_match_list(op->recursion_acl);
if (op->transfer_acl)
free_ip_match_list(op->transfer_acl);
+ if (op->sortlist)
+ free_ip_match_list(op->sortlist);
+ if (op->ordering)
+ free_rrset_order_list(op->ordering);
if (op->topology)
free_ip_match_list(op->topology);
if (op->listen_list)
@@ -863,9 +1184,9 @@ free_options(options op) {
memput(op, sizeof *op);
}
-void
-set_boolean_option(options op, int bool_opt, int value) {
- INSIST(op != NULL);
+static void
+set_boolean_option(u_int *op_flags, int bool_opt, int value) {
+ INSIST(op_flags != NULL);
switch (bool_opt) {
case OPTION_NORECURSE:
@@ -875,18 +1196,45 @@ set_boolean_option(options op, int bool_opt, int value) {
case OPTION_NONOTIFY:
case OPTION_NONAUTH_NXDOMAIN:
case OPTION_MULTIPLE_CNAMES:
+ case OPTION_USE_IXFR:
+ case OPTION_MAINTAIN_IXFR_BASE:
case OPTION_HOSTSTATS:
case OPTION_DEALLOC_ON_EXIT:
+ case OPTION_USE_ID_POOL:
+ case OPTION_NORFC2308_TYPE1:
+ case OPTION_NODIALUP:
+ case OPTION_TREAT_CR_AS_SPACE:
if (value)
- op->flags |= bool_opt;
+ *op_flags |= bool_opt;
else
- op->flags &= ~bool_opt;
+ *op_flags &= ~bool_opt;
break;
default:
panic("unexpected option in set_boolean_option", NULL);
}
}
+void
+set_global_boolean_option(options op, int bool_opt, int value) {
+
+ INSIST(op != NULL);
+
+ set_boolean_option(&op->flags, bool_opt, value);
+}
+
+void
+set_zone_boolean_option(zone_config zh, int bool_opt, int value) {
+ struct zoneinfo *zp;
+
+ zp = zh.opaque;
+ INSIST(zp != NULL);
+
+ set_boolean_option(&zp->z_options, bool_opt, value);
+
+ /* Flag that zone option overrides corresponding global option */
+ zp->z_optset |= bool_opt;
+}
+
#ifdef HAVE_GETRUSAGE
enum limit { Datasize, Stacksize, Coresize, Files };
@@ -897,6 +1245,8 @@ static struct rlimit initial_num_files;
static void
get_initial_limits() {
+ int fdlimit = evHighestFD(ev) + 1;
+
# ifdef RLIMIT_DATA
if (getrlimit(RLIMIT_DATA, &initial_data_size) < 0)
ns_warning(ns_log_config, "getrlimit(DATA): %s",
@@ -916,6 +1266,19 @@ get_initial_limits() {
if (getrlimit(RLIMIT_NOFILE, &initial_num_files) < 0)
ns_warning(ns_log_config, "getrlimit(NOFILE): %s",
strerror(errno));
+ else if (initial_num_files.rlim_cur > fdlimit) {
+ initial_num_files.rlim_cur = fdlimit;
+ if (initial_num_files.rlim_cur > initial_num_files.rlim_max)
+ initial_num_files.rlim_max = fdlimit;
+ if (setrlimit(RLIMIT_NOFILE, &initial_num_files) < 0) {
+ ns_warning(ns_log_config, "setrlimit(files): %s",
+ strerror(errno));
+ } else {
+ ns_warning(ns_log_config,
+ "limit files set to fdlimit (%d)",
+ fdlimit);
+ }
+ }
# endif
}
@@ -923,13 +1286,14 @@ static void
ns_rlimit(enum limit limit, u_long limit_value) {
struct rlimit limits, old_limits;
int rlimit = -1;
+ int fdlimit = evHighestFD(ev) + 1;
char *name;
rlimit_type value;
if (limit_value == ULONG_MAX) {
#ifndef RLIMIT_FILE_INFINITY
if (limit == Files)
- value = MAX((rlimit_type)sysconf(_SC_OPEN_MAX),
+ value = MIN((rlimit_type)evHighestFD(ev) + 1,
initial_num_files.rlim_max);
else
#endif
@@ -970,7 +1334,8 @@ ns_rlimit(enum limit limit, u_long limit_value) {
name = "max number of open files";
if (value == 0)
limits = initial_num_files;
- /* XXX check < FD_SETSIZE? */
+ if (value > fdlimit)
+ limits.rlim_cur = limits.rlim_max = value = fdlimit;
break;
default:
name = NULL; /* Make gcc happy. */
@@ -994,8 +1359,7 @@ ns_rlimit(enum limit limit, u_long limit_value) {
return;
} else {
if (value == 0)
- ns_debug(ns_log_config, 3, "%s is default",
- name);
+ ns_debug(ns_log_config, 3, "%s is default", name);
else if (value == RLIM_INFINITY)
ns_debug(ns_log_config, 3, "%s is unlimited", name);
else
@@ -1155,7 +1519,7 @@ periodic_getnetconf(evContext ctx, void *uap, struct timespec due,
{
getnetconf(1);
}
-
+
static void
set_interval_timer(int which_timer, int interval) {
evTimerID *tid = NULL;
@@ -1174,6 +1538,10 @@ set_interval_timer(int which_timer, int interval) {
tid = &stats_timer;
func = ns_logstats;
break;
+ case HEARTBEAT_TIMER:
+ tid = &heartbeat_timer;
+ func = ns_heartbeat;
+ break;
default:
ns_panic(ns_log_config, 1,
"set_interval_timer: unknown timer %d", which_timer);
@@ -1215,7 +1583,6 @@ set_interval_timer(int which_timer, int interval) {
*/
void
set_options(options op, int is_default) {
- listen_info li;
INSIST(op != NULL);
if (op->listen_list == NULL) {
@@ -1231,6 +1598,18 @@ set_options(options op, int is_default) {
add_to_ip_match_list(iml, ime);
add_listen_on(op, htons(NS_DEFAULTPORT), iml);
}
+ if (op->topology == NULL) {
+ ip_match_list iml;
+ ip_match_element ime;
+
+ /* default topology is { localhost; localnets; } */
+ iml = new_ip_match_list();
+ ime = new_ip_match_localhost();
+ add_to_ip_match_list(iml, ime);
+ ime = new_ip_match_localnets();
+ add_to_ip_match_list(iml, ime);
+ op->topology = iml;
+ }
if (server_options != NULL)
free_options(server_options);
server_options = op;
@@ -1263,6 +1642,14 @@ set_options(options op, int is_default) {
/* XXX currently transfers_out is not used */
+ if (!op->max_ncache_ttl)
+ op->max_ncache_ttl = DEFAULT_MAX_NCACHE_TTL;
+ else if (op->max_ncache_ttl > max_cache_ttl)
+ op->max_ncache_ttl = max_cache_ttl;
+
+ if (op->lame_ttl > (3 * NTTL))
+ op->lame_ttl = 3 * NTTL;
+
/*
* Limits
*/
@@ -1276,7 +1663,6 @@ set_options(options op, int is_default) {
ns_info(ns_log_config, "cannot set resource limits on this system");
#endif
-
/*
* Timers
*/
@@ -1284,6 +1670,8 @@ set_options(options op, int is_default) {
set_interval_timer(INTERFACE_TIMER,
server_options->interface_interval);
set_interval_timer(STATS_TIMER, server_options->stats_interval);
+ set_interval_timer(HEARTBEAT_TIMER,
+ server_options->heartbeat_interval);
options_installed = 1;
default_options_installed = is_default;
@@ -1295,6 +1683,129 @@ use_default_options() {
}
/*
+ * rrset order types
+ */
+static struct res_sym order_table [] = {
+ { unknown_order, " unknown " }, /* can't match */
+ { fixed_order, "fixed" },
+ { cyclic_order, "cyclic" },
+ { random_order, "random" },
+ { unknown_order, NULL }
+};
+
+/*
+ * Return the print name of the ordering value.
+ */
+const char *
+p_order(int order) {
+ return (__sym_ntos(order_table, order, (int *)0));
+}
+
+/*
+ * Lookup the ordering by name and return the matching enum value.
+ */
+enum ordering
+lookup_ordering(const char *name) {
+ int i;
+
+ for (i = 0; order_table[i].name != NULL; i++)
+ if (strcasecmp(name,order_table[i].name) == 0)
+ return ((enum ordering)order_table[i].number);
+ return (unknown_order);
+}
+
+/*
+ * rrset-order Lists
+ */
+rrset_order_list
+new_rrset_order_list() {
+ rrset_order_list rol ;
+
+ rol = (rrset_order_list)memget(sizeof (struct rrset_order_list));
+ if (rol == NULL)
+ panic("memget failed in new_rrset_order_list", NULL);
+ rol->first = NULL;
+ rol->last = NULL;
+
+ return (rol);
+}
+
+void
+free_rrset_order_list(rrset_order_list rol) {
+ rrset_order_element roe, next_element;
+
+ for (roe = rol->first; roe != NULL; roe = next_element) {
+ next_element = roe->next;
+ freestr(roe->name);
+ memput(roe, sizeof (*roe));
+ }
+ memput(rol, sizeof (*rol));
+}
+
+
+void
+add_to_rrset_order_list(rrset_order_list rol, rrset_order_element roe) {
+ INSIST(rol != NULL);
+ INSIST(roe != NULL);
+
+ if (rol->last != NULL)
+ rol->last->next = roe;
+ roe->next = NULL;
+ rol->last = roe;
+ if (rol->first == NULL)
+ rol->first = roe;
+}
+
+/* XXX this isn't being used yet, but it probably should be. Where? */
+void
+dprint_rrset_order_list(int category, rrset_order_list rol, int indent,
+ char *allow, char *deny) {
+ rrset_order_element roe ;
+ char spaces[40+1];
+
+ INSIST(rol != NULL);
+
+ if (indent > 40)
+ indent = 40;
+ if (indent)
+ memset(spaces, ' ', indent);
+ spaces[indent] = '\0';
+
+ for (roe = rol->first; roe != NULL; roe = roe->next) {
+ ns_debug(category, 7, "%sclass %s type %s name %s order %s",
+ spaces, p_class(roe->class), p_type(roe->type),
+ roe->name, p_order(roe->order));
+ }
+}
+
+
+rrset_order_element
+new_rrset_order_element(int class, int type, char *name, enum ordering order)
+{
+ rrset_order_element roe;
+ int i ;
+
+ roe = (rrset_order_element)memget(sizeof (struct rrset_order_element));
+ if (roe == NULL)
+ panic("memget failed in new_rrset_order_element", NULL);
+ roe->class = class ;
+ roe->type = type ;
+ roe->name = name;
+ roe->order = order;
+
+ i = strlen(roe->name) - 1;
+ INSIST (i >= 0);
+ if (roe->name[i - 1] == '.') {
+ /* We compare from right to left so we don't need a dot on
+ the end. */
+ roe->name[i - 1] = '\0' ;
+ }
+
+ return roe ;
+}
+
+
+/*
* IP Matching Lists
*/
@@ -1390,6 +1901,19 @@ new_ip_match_indirect(ip_match_list iml) {
}
ip_match_element
+new_ip_match_key(DST_KEY *dst_key) {
+ ip_match_element ime;
+
+ ime = (ip_match_element)memget(sizeof (struct ip_match_element));
+ if (ime == NULL)
+ panic("memget failed in new_ip_match_key", NULL);
+ ime->type = ip_match_key;
+ ime->flags = 0;
+ ime->u.key.key = dst_key;
+ return (ime);
+}
+
+ip_match_element
new_ip_match_localhost() {
ip_match_element ime;
@@ -1445,7 +1969,6 @@ dprint_ip_match_list(int category, ip_match_list iml, int indent,
char spaces[40+1];
char addr_text[sizeof "255.255.255.255"];
char mask_text[sizeof "255.255.255.255"];
- char *tmp;
INSIST(iml != NULL);
@@ -1488,6 +2011,11 @@ dprint_ip_match_list(int category, ip_match_list iml, int indent,
ime->u.indirect.list,
indent+2, allow, deny);
break;
+ case ip_match_key:
+ ns_debug(category, 7, "%s%skey %s", spaces,
+ (ime->flags & IP_MATCH_NEGATE) ? deny : allow,
+ ime->u.key.key->dk_key_name);
+ break;
default:
panic("unexpected ime type in dprint_ip_match_list()",
NULL);
@@ -1496,7 +2024,9 @@ dprint_ip_match_list(int category, ip_match_list iml, int indent,
}
int
-ip_match_address(ip_match_list iml, struct in_addr address) {
+ip_match_addr_or_key(ip_match_list iml, struct in_addr address,
+ DST_KEY *key)
+{
ip_match_element ime;
int ret;
int indirect;
@@ -1518,13 +2048,25 @@ ip_match_address(ip_match_list iml, struct in_addr address) {
ime->u.indirect.list = local_networks;
indirect = 1;
break;
+ case ip_match_key:
+ if (key == NULL) {
+ indirect = 0;
+ break;
+ }
+ else {
+ if (ns_samename(ime->u.key.key->dk_key_name,
+ key->dk_key_name) == 1)
+ return (1);
+ else
+ continue;
+ }
default:
- indirect = 0; /* Make gcc happy. */
- panic("unexpected ime type in ip_match_address()",
+ panic("unexpected ime type in ip_match_addr_or_key()",
NULL);
}
if (indirect) {
- ret = ip_match_address(ime->u.indirect.list, address);
+ ret = ip_match_addr_or_key(ime->u.indirect.list,
+ address, key);
if (ret >= 0) {
if (ime->flags & IP_MATCH_NEGATE)
ret = (ret) ? 0 : 1;
@@ -1544,18 +2086,30 @@ ip_match_address(ip_match_list iml, struct in_addr address) {
}
int
-ip_address_allowed(ip_match_list iml, struct in_addr address) {
+ip_match_address(ip_match_list iml, struct in_addr address) {
+ return ip_match_addr_or_key(iml, address, NULL);
+}
+
+int
+ip_addr_or_key_allowed(ip_match_list iml, struct in_addr address,
+ DST_KEY *key)
+{
int ret;
if (iml == NULL)
return (0);
- ret = ip_match_address(iml, address);
+ ret = ip_match_addr_or_key(iml, address, key);
if (ret < 0)
ret = 0;
return (ret);
}
int
+ip_address_allowed(ip_match_list iml, struct in_addr address) {
+ return(ip_addr_or_key_allowed(iml, address, NULL));
+}
+
+int
ip_match_network(ip_match_list iml, struct in_addr address,
struct in_addr mask) {
ip_match_element ime;
@@ -1579,6 +2133,9 @@ ip_match_network(ip_match_list iml, struct in_addr address,
ime->u.indirect.list = local_networks;
indirect = 1;
break;
+ case ip_match_key:
+ indirect = 0;
+ break;
default:
indirect = 0; /* Make gcc happy. */
panic("unexpected ime type in ip_match_network()",
@@ -1630,6 +2187,9 @@ distance_of_address(ip_match_list iml, struct in_addr address) {
ime->u.indirect.list = local_networks;
indirect = 1;
break;
+ case ip_match_key:
+ indirect = 0;
+ return (-1);
default:
indirect = 0; /* Make gcc happy. */
panic("unexpected ime type in distance_of_address()",
@@ -1666,14 +2226,14 @@ int
ip_match_is_none(ip_match_list iml) {
ip_match_element ime;
- if (iml == NULL)
+ if ((iml == NULL) || (iml->first == NULL))
return (1);
ime = iml->first;
if (ime->type == ip_match_indirect) {
if (ime->flags & IP_MATCH_NEGATE)
return (0);
iml = ime->u.indirect.list;
- if (iml == NULL)
+ if ((iml == NULL) || (iml->first == NULL))
return (0);
ime = iml->first;
}
@@ -1694,30 +2254,13 @@ ip_match_is_none(ip_match_list iml) {
* forward zones.
*/
-void
-add_forwarder(options op, struct in_addr address) {
- struct fwdinfo *fip = NULL, *ftp = NULL;
-
-#ifdef SLAVE_FORWARD
- int forward_count = 0;
-#endif
-
- INSIST(op != NULL);
+static void
+add_forwarder(struct fwdinfo **fipp, struct in_addr address) {
+ struct fwdinfo *fip = *fipp, *ftp = NULL;
/* On multiple forwarder lines, move to end of the list. */
-#ifdef SLAVE_FORWARD
- if (op->fwdtab != NULL) {
- forward_count++;
- for (fip = op->fwdtab; fip->next != NULL; fip = fip->next)
- forward_count++;
- }
-#else
- if (op->fwdtab != NULL) {
- for (fip = op->fwdtab; fip->next != NULL; fip = fip->next) {
- ;
- }
- }
-#endif /* SLAVE_FORWARD */
+ while (fip != NULL && fip->next != NULL)
+ fip = fip->next;
ftp = (struct fwdinfo *)memget(sizeof(struct fwdinfo));
if (!ftp)
@@ -1733,19 +2276,95 @@ add_forwarder(options op, struct in_addr address) {
return;
}
#endif /* FWD_LOOP */
- ns_debug(ns_log_config, 2, "added forwarder %s", inet_ntoa(address));
ftp->next = NULL;
- if (op->fwdtab == NULL)
- op->fwdtab = ftp; /* First time only */
+ if (fip == NULL)
+ *fipp = ftp; /* First time only */
else
fip->next = ftp;
+}
+
+void
+free_also_notify(options op) {
+#ifdef BIND_NOTIFY
+ memput(op->also_notify, op->notify_count * sizeof *op->also_notify);
+ op->also_notify = NULL;
+ op->notify_count = 0;
+#endif
+}
+
+int
+add_global_also_notify(options op, struct in_addr address) {
+#ifdef BIND_NOTIFY
+ int i;
+
+ INSIST(op != NULL);
+
+ ns_debug(ns_log_config, 2, "adding global notify %s",
+ inet_ntoa(address));
+
+ /* Check for duplicates. */
+
+ for (i = 0; i < op->notify_count; i++) {
+ if (memcmp(op->also_notify + i,
+ &address, sizeof address) == 0) {
+ ns_warning(ns_log_config,
+ "duplicate global also-notify address ignored [%s]",
+ inet_ntoa(address));
+ return (1);
+ }
+ }
+ i = 0;
+
+ if (op->also_notify == NULL) {
+ op->also_notify = memget(sizeof *op->also_notify);
+ if (op->also_notify == NULL)
+ i = 1;
+ } else {
+ register size_t size;
+ register struct in_addr *an_tmp;
+ size = op->notify_count * sizeof *op->also_notify;
+ an_tmp = memget(size + sizeof *op->also_notify);
+ if (an_tmp == NULL) {
+ i = 1;
+ } else {
+ memcpy(an_tmp, op->also_notify, size);
+ memput(op->also_notify, size);
+ op->also_notify = an_tmp;
+ }
+ }
+ if (i == 0) {
+ op->also_notify[op->notify_count] = address;
+ op->notify_count++;
+ } else {
+ ns_warning(ns_log_config,
+ "global also-notify add failed (memget) [%s]",
+ inet_ntoa(address));
+ }
+#endif
+ return (1);
+}
+
+void
+add_global_forwarder(options op, struct in_addr address) {
#ifdef SLAVE_FORWARD
- forward_count++;
+ struct fwdinfo *fip;
+ int forward_count;
+#endif
+
+ INSIST(op != NULL);
+
+ ns_debug(ns_log_config, 2, "adding default forwarder %s",
+ inet_ntoa(address));
+ add_forwarder(&op->fwdtab, address);
+
+#ifdef SLAVE_FORWARD
/*
** Set the slave retry time to 60 seconds total divided
** between each forwarder
*/
+ for (forward_count = 0, fip = op->fwdtab; fip != NULL; fip = fip->next)
+ forward_count++;
if (forward_count != 0) {
slave_retry = (int) (60 / forward_count);
if(slave_retry <= 0)
@@ -1755,6 +2374,32 @@ add_forwarder(options op, struct in_addr address) {
}
void
+set_zone_forward(zone_config zh) {
+ struct zoneinfo *zp;
+ zp = zh.opaque;
+
+ zp->z_flags |= Z_FORWARD_SET;
+ set_zone_boolean_option(zh, OPTION_FORWARD_ONLY, 0);
+}
+
+void
+add_zone_forwarder(zone_config zh, struct in_addr address) {
+ struct zoneinfo *zp;
+ char *zname;
+
+ zp = zh.opaque;
+ INSIST(zp != NULL);
+
+ zname = (zp->z_origin[0] == '\0') ? "." : zp->z_origin;
+ ns_debug(ns_log_config, 2, "adding forwarder %s for zone zone '%s'",
+ inet_ntoa(address), zname);
+
+ zp->z_flags |= Z_FORWARD_SET;
+
+ add_forwarder(&zp->z_fwdtab, address);
+}
+
+void
free_forwarders(struct fwdinfo *fwdtab) {
struct fwdinfo *ftp, *fnext;
@@ -1762,13 +2407,13 @@ free_forwarders(struct fwdinfo *fwdtab) {
fnext = ftp->next;
memput(ftp, sizeof *ftp);
}
+ fwdtab = NULL;
}
/*
* Servers
*/
-
static server_info
new_server(struct in_addr address) {
server_info si;
@@ -1782,7 +2427,11 @@ new_server(struct in_addr address) {
si->transfer_format = axfr_use_default;
si->key_list = NULL;
si->next = NULL;
- return si;
+ if (server_options->flags & OPTION_MAINTAIN_IXFR_BASE)
+ si->flags |= SERVER_INFO_SUPPORT_IXFR;
+ else
+ si->flags &= ~SERVER_INFO_SUPPORT_IXFR;
+ return (si);
}
static void
@@ -1839,6 +2488,14 @@ free_nameserver_info() {
}
}
+static void
+free_secretkey_info() {
+ if (secretkey_info != NULL) {
+ free_key_info_list(secretkey_info);
+ secretkey_info = NULL;
+ }
+}
+
server_config
begin_server(struct in_addr address) {
server_config sc;
@@ -1872,6 +2529,7 @@ set_server_option(server_config sc, int bool_opt, int value) {
switch (bool_opt) {
case SERVER_INFO_BOGUS:
+ case SERVER_INFO_SUPPORT_IXFR:
if (value)
si->flags |= bool_opt;
else
@@ -1908,7 +2566,7 @@ set_server_transfer_format(server_config sc,
}
void
-add_server_key_info(server_config sc, key_info ki) {
+add_server_key_info(server_config sc, DST_KEY *dst_key) {
server_info si;
si = sc.opaque;
@@ -1917,44 +2575,75 @@ add_server_key_info(server_config sc, key_info ki) {
if (si->key_list == NULL)
si->key_list = new_key_info_list();
- add_to_key_info_list(si->key_list, ki);
+ add_to_key_info_list(si->key_list, dst_key);
}
/*
* Keys
*/
-key_info
+DST_KEY *
new_key_info(char *name, char *algorithm, char *secret) {
- key_info ki;
+ DST_KEY *dst_key;
+ int alg, blen;
+ u_char buffer[1024];
INSIST(name != NULL);
INSIST(algorithm != NULL);
INSIST(secret != NULL);
- ki = (key_info)memget(sizeof (struct key_info));
- if (ki == NULL)
- panic("memget failed in new_key_info", NULL);
- ki->name = name;
- ki->algorithm = algorithm;
- ki->secret = secret;
- return (ki);
+ alg = tsig_alg_value(algorithm);
+ if (alg == -1) {
+ ns_warning(ns_log_config, "Unsupported TSIG algorithm %s",
+ algorithm);
+ return (NULL);
+ }
+
+ blen = b64_pton(secret, buffer, sizeof(buffer));
+ if (blen < 0) {
+ ns_warning(ns_log_config, "Invalid TSIG secret \"%s\"", secret);
+ return (NULL);
+ }
+ dst_key = dst_buffer_to_key(name, alg,
+ NS_KEY_TYPE_AUTH_ONLY|NS_KEY_NAME_ENTITY,
+ NS_KEY_PROT_ANY, buffer, blen);
+ if (dst_key == NULL)
+ ns_warning(ns_log_config,
+ "dst_buffer_to_key failed in new_key_info");
+ return (dst_key);
}
void
-free_key_info(key_info ki) {
- INSIST(ki != NULL);
- freestr(ki->name);
- freestr(ki->algorithm);
- freestr(ki->secret);
- memput(ki, sizeof *ki);
+free_key_info(DST_KEY *dst_key) {
+ INSIST(dst_key != NULL);
+ dst_free_key(dst_key);
+}
+
+DST_KEY *
+find_key(char *name, char *algorithm) {
+ key_list_element ke;
+
+ if (secretkey_info == NULL)
+ return (NULL);
+
+ for (ke = secretkey_info->first; ke != NULL; ke = ke->next) {
+ DST_KEY *dst_key = ke->key;
+
+ if (ns_samename(name, dst_key->dk_key_name) != 1)
+ continue;
+ if (algorithm == NULL ||
+ dst_key->dk_alg == tsig_alg_value(algorithm))
+ break;
+ }
+ if (ke == NULL)
+ return (NULL);
+ return (ke->key);
}
void
-dprint_key_info(key_info ki) {
- INSIST(ki != NULL);
- ns_debug(ns_log_config, 7, "key %s", ki->name);
- ns_debug(ns_log_config, 7, " algorithm %s", ki->algorithm);
- ns_debug(ns_log_config, 7, " secret %s", ki->secret);
+dprint_key_info(DST_KEY *dst_key) {
+ INSIST(dst_key != NULL);
+ ns_debug(ns_log_config, 7, "key %s", dst_key->dk_key_name);
+ ns_debug(ns_log_config, 7, " algorithm %d", dst_key->dk_alg);
}
key_info_list
@@ -1983,16 +2672,16 @@ free_key_info_list(key_info_list kil) {
}
void
-add_to_key_info_list(key_info_list kil, key_info ki) {
+add_to_key_info_list(key_info_list kil, DST_KEY *dst_key) {
key_list_element kle;
INSIST(kil != NULL);
- INSIST(ki != NULL);
+ INSIST(dst_key != NULL);
kle = (key_list_element)memget(sizeof (struct key_list_element));
if (kle == NULL)
panic("memget failed in add_to_key_info_list()", NULL);
- kle->info = ki;
+ kle->key = dst_key;
if (kil->last != NULL)
kil->last->next = kle;
kle->next = NULL;
@@ -2008,7 +2697,7 @@ dprint_key_info_list(key_info_list kil) {
INSIST(kil != NULL);
for (kle = kil->first; kle != NULL; kle = kle->next)
- dprint_key_info(kle->info);
+ dprint_key_info(kle->key);
}
/*
@@ -2098,7 +2787,6 @@ open_special_channels() {
void
set_logging(log_config log_cfg, int is_default) {
log_context lc;
- int skip_debug = 0;
INSIST(log_cfg != NULL);
lc = log_cfg->log_ctx;
@@ -2203,7 +2891,6 @@ use_default_logging() {
static void
init_default_log_channels() {
- FILE *null_stream;
u_int flags;
char *name;
FILE *stream;
@@ -2244,9 +2931,8 @@ shutdown_default_log_channels() {
log_free_channel(null_channel);
}
-void
+void
init_logging() {
- int i;
int size;
const struct ns_sym *s;
char category_name[256];
@@ -2266,7 +2952,7 @@ init_logging() {
use_default_logging();
}
-void
+void
shutdown_logging() {
int size;
const struct ns_sym *s;
@@ -2279,6 +2965,7 @@ shutdown_logging() {
freestr(logging_categories[s->number]);
size = ns_log_max_category * (sizeof (char *));
memput(logging_categories, size);
+ logging_categories = NULL;
}
/*
@@ -2297,6 +2984,7 @@ init_configuration() {
zone_symbol_table = new_symbol_table(ZONE_SYM_TABLE_SIZE, NULL);
use_default_options();
parser_initialize();
+ ns_ctl_initialize();
config_initialized = 1;
}
@@ -2304,6 +2992,7 @@ void
shutdown_configuration() {
REQUIRE(config_initialized);
+ ns_ctl_shutdown();
if (server_options != NULL) {
free_options(server_options);
server_options = NULL;
@@ -2311,6 +3000,7 @@ shutdown_configuration() {
if (current_pid_filename != NULL)
freestr(current_pid_filename);
free_nameserver_info();
+ free_secretkey_info();
free_symbol_table(zone_symbol_table);
parser_shutdown();
config_initialized = 0;
@@ -2329,6 +3019,7 @@ load_configuration(const char *filename) {
* global data structures we'll be updating.
*/
free_nameserver_info();
+ free_secretkey_info();
bogus_nameservers = new_ip_match_list();
options_installed = 0;
OpenPOWER on IntegriCloud