summaryrefslogtreecommitdiffstats
path: root/usr.sbin/nsd
diff options
context:
space:
mode:
authorflorian <florian@openbsd.org>2017-01-17 06:21:41 +0000
committerflorian <florian@openbsd.org>2017-01-17 06:21:41 +0000
commit6a6b9a23b4a8887e42cfb3bb27132265346775ce (patch)
tree043c8d8783d138a6bc42943a3f28222441f0f7bc /usr.sbin/nsd
parentSimplify the usage of print_otag() by making it accept a variable (diff)
downloadwireguard-openbsd-6a6b9a23b4a8887e42cfb3bb27132265346775ce.tar.xz
wireguard-openbsd-6a6b9a23b4a8887e42cfb3bb27132265346775ce.zip
Update to nsd 4.1.14
OK sthen@
Diffstat (limited to 'usr.sbin/nsd')
-rw-r--r--usr.sbin/nsd/configlexer.lex34
-rw-r--r--usr.sbin/nsd/configure.ac2
-rw-r--r--usr.sbin/nsd/radtree.c6
-rw-r--r--usr.sbin/nsd/remote.c2
-rw-r--r--usr.sbin/nsd/xfrd-disk.c32
-rw-r--r--usr.sbin/nsd/xfrd-disk.h2
-rw-r--r--usr.sbin/nsd/xfrd-tcp.c10
-rw-r--r--usr.sbin/nsd/xfrd.c59
-rw-r--r--usr.sbin/nsd/xfrd.h6
9 files changed, 105 insertions, 48 deletions
diff --git a/usr.sbin/nsd/configlexer.lex b/usr.sbin/nsd/configlexer.lex
index e6b26f947e1..42dbd152f16 100644
--- a/usr.sbin/nsd/configlexer.lex
+++ b/usr.sbin/nsd/configlexer.lex
@@ -66,15 +66,6 @@ static void config_start_include(const char* filename)
c_error_msg("include %s: malloc failure", filename);
return;
}
- if (cfg_parser->chroot) {
- int l = strlen(cfg_parser->chroot); /* chroot has trailing slash */
- if (strncmp(cfg_parser->chroot, filename, l) != 0) {
- c_error_msg("include file '%s' is not relative to chroot '%s'",
- filename, cfg_parser->chroot);
- return;
- }
- filename += l - 1; /* strip chroot without trailing slash */
- }
nm = strdup(filename);
if(!nm) {
c_error_msg("include %s: strdup failure", filename);
@@ -103,12 +94,23 @@ static void config_start_include(const char* filename)
static void config_start_include_glob(const char* filename)
{
- /* check for wildcards */
+ /* check for wildcards */
#ifdef HAVE_GLOB
- glob_t g;
- size_t i;
- int r, flags;
- if(!(!strchr(filename, '*') && !strchr(filename, '?') &&
+ glob_t g;
+ size_t i;
+ int r, flags;
+#endif /* HAVE_GLOB */
+ if (cfg_parser->chroot) {
+ int l = strlen(cfg_parser->chroot); /* chroot has trailing slash */
+ if (strncmp(cfg_parser->chroot, filename, l) != 0) {
+ c_error_msg("include file '%s' is not relative to chroot '%s'",
+ filename, cfg_parser->chroot);
+ return;
+ }
+ filename += l - 1; /* strip chroot without trailing slash */
+ }
+#ifdef HAVE_GLOB
+ if(!(!strchr(filename, '*') && !strchr(filename, '?') &&
!strchr(filename, '[') && !strchr(filename, '{') &&
!strchr(filename, '~'))) {
flags = 0
@@ -141,9 +143,9 @@ static void config_start_include_glob(const char* filename)
}
globfree(&g);
return;
- }
+ }
#endif /* HAVE_GLOB */
- config_start_include(filename);
+ config_start_include(filename);
}
static void config_end_include(void)
diff --git a/usr.sbin/nsd/configure.ac b/usr.sbin/nsd/configure.ac
index e2aca4d531e..029193574f0 100644
--- a/usr.sbin/nsd/configure.ac
+++ b/usr.sbin/nsd/configure.ac
@@ -4,7 +4,7 @@ dnl
sinclude(acx_nlnetlabs.m4)
-AC_INIT(NSD,4.1.13,nsd-bugs@nlnetlabs.nl)
+AC_INIT(NSD,4.1.14,nsd-bugs@nlnetlabs.nl)
AC_CONFIG_HEADER([config.h])
CFLAGS="$CFLAGS"
diff --git a/usr.sbin/nsd/radtree.c b/usr.sbin/nsd/radtree.c
index 8ca4a5bd5ba..fd003795a4a 100644
--- a/usr.sbin/nsd/radtree.c
+++ b/usr.sbin/nsd/radtree.c
@@ -636,11 +636,13 @@ radnode_cleanup_onechild(struct region* region, struct radnode* n,
return 0;
}
/* we know that .str and join are malloced, thus aligned */
- memcpy(join, par->array[pidx].str, par->array[pidx].len);
+ if(par->array[pidx].str)
+ memcpy(join, par->array[pidx].str, par->array[pidx].len);
/* the array lookup is gone, put its character in the lookup string*/
join[par->array[pidx].len] = child->pidx + n->offset;
/* but join+len may not be aligned */
- memmove(join+par->array[pidx].len+1, n->array[0].str, n->array[0].len);
+ if(n->array[0].str)
+ memmove(join+par->array[pidx].len+1, n->array[0].str, n->array[0].len);
region_recycle(region, par->array[pidx].str, par->array[pidx].len);
par->array[pidx].str = join;
par->array[pidx].len = joinlen;
diff --git a/usr.sbin/nsd/remote.c b/usr.sbin/nsd/remote.c
index d961dbf4146..baa9985389a 100644
--- a/usr.sbin/nsd/remote.c
+++ b/usr.sbin/nsd/remote.c
@@ -1469,7 +1469,7 @@ repat_interrupt_zones(xfrd_state_t* xfrd, nsd_options_t* newopt)
xz->master = 0;
xz->master_num = 0;
xz->next_master = -1;
- xz->round_num = 0; /* fresh set of retries */
+ xz->round_num = -1; /* fresh set of retries */
}
}
/* if notify list changed:
diff --git a/usr.sbin/nsd/xfrd-disk.c b/usr.sbin/nsd/xfrd-disk.c
index c724a2c9cc6..a86240d4a57 100644
--- a/usr.sbin/nsd/xfrd-disk.c
+++ b/usr.sbin/nsd/xfrd-disk.c
@@ -165,8 +165,15 @@ xfrd_read_state(struct xfrd_state* xfrd)
region_destroy(tempregion);
return;
}
- if(!xfrd_read_check_str(in, XFRD_FILE_MAGIC) ||
- !xfrd_read_check_str(in, "filetime:") ||
+ if(!xfrd_read_check_str(in, XFRD_FILE_MAGIC)) {
+ /* older file version; reset everything */
+ DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: file %s is old version. refreshing all zones.",
+ statefile));
+ fclose(in);
+ region_destroy(tempregion);
+ return;
+ }
+ if(!xfrd_read_check_str(in, "filetime:") ||
!xfrd_read_i32(in, &filetime) ||
(time_t)filetime > xfrd_time()+15 ||
!xfrd_read_check_str(in, "numzones:") ||
@@ -183,7 +190,7 @@ xfrd_read_state(struct xfrd_state* xfrd)
char *p;
xfrd_zone_t* zone;
const dname_type* dname;
- uint32_t state, masnum, nextmas, round_num, timeout;
+ uint32_t state, masnum, nextmas, round_num, timeout, backoff;
xfrd_soa_t soa_nsd_read, soa_disk_read, soa_notified_read;
time_t soa_nsd_acquired_read,
soa_disk_acquired_read, soa_notified_acquired_read;
@@ -214,6 +221,8 @@ xfrd_read_state(struct xfrd_state* xfrd)
!xfrd_read_i32(in, &round_num) ||
!xfrd_read_check_str(in, "next_timeout:") ||
!xfrd_read_i32(in, &timeout) ||
+ !xfrd_read_check_str(in, "backoff:") ||
+ !xfrd_read_i32(in, &backoff) ||
!xfrd_read_state_soa(in, "soa_nsd_acquired:", "soa_nsd:",
&soa_nsd_read, &soa_nsd_acquired_read) ||
!xfrd_read_state_soa(in, "soa_disk_acquired:", "soa_disk:",
@@ -249,6 +258,7 @@ xfrd_read_state(struct xfrd_state* xfrd)
zone->round_num = round_num;
zone->timeout.tv_sec = timeout;
zone->timeout.tv_usec = 0;
+ zone->fresh_xfr_timeout = backoff*XFRD_TRANSFER_TIMEOUT_START;
/* read the zone OK, now set the master properly */
zone->master = acl_find_num(zone->zone_options->pattern->
@@ -296,10 +306,14 @@ xfrd_read_state(struct xfrd_state* xfrd)
zone->state = state;
xfrd_set_timer(zone, timeout);
}
- if(zone->soa_nsd_acquired == 0 && soa_nsd_acquired_read == 0 &&
- soa_disk_acquired_read == 0) {
- /* continue expon backoff where we were + check now */
- zone->fresh_xfr_timeout = timeout;
+ if((zone->soa_nsd_acquired == 0 && soa_nsd_acquired_read == 0 &&
+ soa_disk_acquired_read == 0) ||
+ (zone->state != xfrd_zone_ok && timeout != 0)) {
+ /* but don't check now, because that would mean a
+ * storm of attempts on some master servers */
+ xfrd_deactivate_zone(zone);
+ zone->state = state;
+ xfrd_set_timer(zone, timeout);
}
/* handle as an incoming SOA. */
@@ -318,7 +332,8 @@ xfrd_read_state(struct xfrd_state* xfrd)
{
xfrd_send_expire_notification(zone);
}
- xfrd_handle_incoming_soa(zone, &incoming_soa, incoming_acquired);
+ if(incoming_acquired != 0)
+ xfrd_handle_incoming_soa(zone, &incoming_soa, incoming_acquired);
}
if(!xfrd_read_check_str(in, XFRD_FILE_MAGIC)) {
@@ -477,6 +492,7 @@ xfrd_write_state(struct xfrd_state* xfrd)
neato_timeout(out, "\t# =", zone->timeout.tv_sec);
}
fprintf(out, "\n");
+ fprintf(out, "\tbackoff: %d\n", zone->fresh_xfr_timeout/XFRD_TRANSFER_TIMEOUT_START);
xfrd_write_state_soa(out, "soa_nsd", &zone->soa_nsd,
zone->soa_nsd_acquired, zone->apex);
xfrd_write_state_soa(out, "soa_disk", &zone->soa_disk,
diff --git a/usr.sbin/nsd/xfrd-disk.h b/usr.sbin/nsd/xfrd-disk.h
index b7e2d10b237..acd4e4c8333 100644
--- a/usr.sbin/nsd/xfrd-disk.h
+++ b/usr.sbin/nsd/xfrd-disk.h
@@ -14,7 +14,7 @@ struct xfrd_state;
struct nsd;
/* magic string to identify xfrd state file */
-#define XFRD_FILE_MAGIC "NSDXFRD1"
+#define XFRD_FILE_MAGIC "NSDXFRD2"
/* read from state file as many zones as possible (until error/eof).*/
void xfrd_read_state(struct xfrd_state* xfrd);
diff --git a/usr.sbin/nsd/xfrd-tcp.c b/usr.sbin/nsd/xfrd-tcp.c
index a4a7a23fe29..506b2520589 100644
--- a/usr.sbin/nsd/xfrd-tcp.c
+++ b/usr.sbin/nsd/xfrd-tcp.c
@@ -490,6 +490,14 @@ xfrd_tcp_open(xfrd_tcp_set_t* set, struct xfrd_tcp_pipeline* tp,
int fd, family, conn;
struct timeval tv;
assert(zone->tcp_conn != -1);
+
+ /* if there is no next master, fallback to use the first one */
+ /* but there really should be a master set */
+ if(!zone->master) {
+ zone->master = zone->zone_options->pattern->request_xfr;
+ zone->master_num = 0;
+ }
+
DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: zone %s open tcp conn to %s",
zone->apex_str, zone->master->ip_address_spec));
tp->tcp_r->is_reading = 1;
@@ -879,7 +887,7 @@ xfrd_tcp_read(struct xfrd_tcp_pipeline* tp)
assert(zone->round_num == -1);
break;
case xfrd_packet_notimpl:
- zone->master->ixfr_disabled = time(NULL);
+ xfrd_disable_ixfr(zone);
xfrd_tcp_release(xfrd->tcp_set, zone);
/* query next server */
xfrd_make_request(zone);
diff --git a/usr.sbin/nsd/xfrd.c b/usr.sbin/nsd/xfrd.c
index a0b34446ae5..415602f014b 100644
--- a/usr.sbin/nsd/xfrd.c
+++ b/usr.sbin/nsd/xfrd.c
@@ -30,13 +30,11 @@
#include "ipc.h"
#include "remote.h"
-#define XFRD_TRANSFER_TIMEOUT_START 10 /* empty zone timeout is between x and 2*x seconds */
-#define XFRD_TRANSFER_TIMEOUT_MAX 86400 /* empty zone timeout max expbackoff */
#define XFRD_UDP_TIMEOUT 10 /* seconds, before a udp request times out */
#define XFRD_NO_IXFR_CACHE 172800 /* 48h before retrying ixfr's after notimpl */
#define XFRD_LOWERBOUND_REFRESH 1 /* seconds, smallest refresh timeout */
#define XFRD_LOWERBOUND_RETRY 1 /* seconds, smallest retry timeout */
-#define XFRD_MAX_ROUNDS 3 /* max number of rounds along the masters */
+#define XFRD_MAX_ROUNDS 1 /* max number of rounds along the masters */
#define XFRD_TSIG_MAX_UNSIGNED 103 /* max number of packets without tsig in a tcp stream. */
/* rfc recommends 100, +3 for offbyone errors/interoperability. */
#define XFRD_CHILD_REAP_TIMEOUT 60 /* seconds to wakeup and reap lost children */
@@ -412,7 +410,7 @@ xfrd_init_slave_zone(xfrd_state_t* xfrd, zone_options_t* zone_opt)
xzone->state = xfrd_zone_refreshing;
xzone->zone_options = zone_opt;
/* first retry will use first master */
- xzone->master = 0;
+ xzone->master = xzone->zone_options->pattern->request_xfr;
xzone->master_num = 0;
xzone->next_master = 0;
xzone->fresh_xfr_timeout = XFRD_TRANSFER_TIMEOUT_START;
@@ -727,11 +725,24 @@ static void
xfrd_set_timer_retry(xfrd_zone_t* zone)
{
time_t set_retry;
+ int mult;
+ /* perform exponential backoff in all the cases */
+ if(zone->fresh_xfr_timeout == 0)
+ zone->fresh_xfr_timeout = XFRD_TRANSFER_TIMEOUT_START;
+ else {
+ /* exponential backoff - some master data in zones is paid-for
+ but non-working, and will not get fixed. */
+ zone->fresh_xfr_timeout *= 2;
+ if(zone->fresh_xfr_timeout > XFRD_TRANSFER_TIMEOUT_MAX)
+ zone->fresh_xfr_timeout = XFRD_TRANSFER_TIMEOUT_MAX;
+ }
+ /* exponential backoff multiplier, starts at 1, backs off */
+ mult = zone->fresh_xfr_timeout / XFRD_TRANSFER_TIMEOUT_START;
+ if(mult == 0) mult = 1;
+
/* set timer for next retry or expire timeout if earlier. */
if(zone->soa_disk_acquired == 0) {
/* if no information, use reasonable timeout */
- if(zone->fresh_xfr_timeout == 0)
- zone->fresh_xfr_timeout = XFRD_TRANSFER_TIMEOUT_START;
#ifdef HAVE_ARC4RANDOM_UNIFORM
xfrd_set_timer(zone, zone->fresh_xfr_timeout
+ arc4random_uniform(zone->fresh_xfr_timeout));
@@ -742,16 +753,12 @@ xfrd_set_timer_retry(xfrd_zone_t* zone)
xfrd_set_timer(zone, zone->fresh_xfr_timeout
+ random()%zone->fresh_xfr_timeout);
#endif
- /* exponential backoff - some master data in zones is paid-for
- but non-working, and will not get fixed. */
- zone->fresh_xfr_timeout *= 2;
- if(zone->fresh_xfr_timeout > XFRD_TRANSFER_TIMEOUT_MAX)
- zone->fresh_xfr_timeout = XFRD_TRANSFER_TIMEOUT_MAX;
} else if(zone->state == xfrd_zone_expired ||
- xfrd_time() + (time_t)ntohl(zone->soa_disk.retry) <
+ xfrd_time() + (time_t)ntohl(zone->soa_disk.retry)*mult <
zone->soa_disk_acquired + (time_t)ntohl(zone->soa_disk.expire))
{
set_retry = ntohl(zone->soa_disk.retry);
+ set_retry *= mult;
if(set_retry > (time_t)zone->zone_options->pattern->max_retry_time)
set_retry = zone->zone_options->pattern->max_retry_time;
else if(set_retry < (time_t)zone->zone_options->pattern->min_retry_time)
@@ -760,13 +767,14 @@ xfrd_set_timer_retry(xfrd_zone_t* zone)
set_retry = XFRD_LOWERBOUND_RETRY;
xfrd_set_timer(zone, set_retry);
} else {
- if(ntohl(zone->soa_disk.expire) < XFRD_LOWERBOUND_RETRY)
+ set_retry = ntohl(zone->soa_disk.expire);
+ if(set_retry < XFRD_LOWERBOUND_RETRY)
xfrd_set_timer(zone, XFRD_LOWERBOUND_RETRY);
else {
- if(zone->soa_disk_acquired + (time_t)ntohl(zone->soa_disk.expire) < xfrd_time())
+ if(zone->soa_disk_acquired + set_retry < xfrd_time())
xfrd_set_timer(zone, XFRD_LOWERBOUND_RETRY);
else xfrd_set_timer(zone, zone->soa_disk_acquired +
- ntohl(zone->soa_disk.expire) - xfrd_time());
+ set_retry - xfrd_time());
}
}
}
@@ -1130,6 +1138,8 @@ xfrd_handle_incoming_soa(xfrd_zone_t* zone,
zone->soa_nsd = zone->soa_disk;
zone->soa_nsd_acquired = zone->soa_disk_acquired;
xfrd->write_zonefile_needed = 1;
+ /* reset exponential backoff, we got a normal timer now */
+ zone->fresh_xfr_timeout = 0;
if(xfrd_time() - zone->soa_disk_acquired
< (time_t)ntohl(zone->soa_disk.refresh))
{
@@ -1269,6 +1279,19 @@ xfrd_udp_release(xfrd_zone_t* zone)
xfrd->udp_use_num--;
}
+/** disable ixfr for master */
+void
+xfrd_disable_ixfr(xfrd_zone_t* zone)
+{
+ if(!(zone->master->ixfr_disabled &&
+ (zone->master->ixfr_disabled + XFRD_NO_IXFR_CACHE) <= time(NULL))) {
+ /* start new round, with IXFR disabled */
+ zone->round_num = 0;
+ zone->next_master = zone->master_num;
+ }
+ zone->master->ixfr_disabled = time(NULL);
+}
+
static void
xfrd_udp_read(xfrd_zone_t* zone)
{
@@ -1276,7 +1299,7 @@ xfrd_udp_read(xfrd_zone_t* zone)
if(!xfrd_udp_read_packet(xfrd->packet, zone->zone_handler.ev_fd)) {
zone->master->bad_xfr_count++;
if (zone->master->bad_xfr_count > 2) {
- zone->master->ixfr_disabled = time(NULL);
+ xfrd_disable_ixfr(zone);
zone->master->bad_xfr_count = 0;
}
/* drop packet */
@@ -1303,7 +1326,7 @@ xfrd_udp_read(xfrd_zone_t* zone)
xfrd_udp_release(zone);
break;
case xfrd_packet_notimpl:
- zone->master->ixfr_disabled = time(NULL);
+ xfrd_disable_ixfr(zone);
/* drop packet */
xfrd_udp_release(zone);
/* query next server */
@@ -1320,7 +1343,7 @@ xfrd_udp_read(xfrd_zone_t* zone)
default:
zone->master->bad_xfr_count++;
if (zone->master->bad_xfr_count > 2) {
- zone->master->ixfr_disabled = time(NULL);
+ xfrd_disable_ixfr(zone);
zone->master->bad_xfr_count = 0;
}
/* drop packet */
diff --git a/usr.sbin/nsd/xfrd.h b/usr.sbin/nsd/xfrd.h
index 24541dbfc44..b601c2aae3e 100644
--- a/usr.sbin/nsd/xfrd.h
+++ b/usr.sbin/nsd/xfrd.h
@@ -244,6 +244,9 @@ enum xfrd_packet_result {
#define XFRD_MAX_UDP 64 /* max number of UDP sockets at a time for IXFR */
#define XFRD_MAX_UDP_NOTIFY 64 /* max concurrent UDP sockets for NOTIFY */
+#define XFRD_TRANSFER_TIMEOUT_START 10 /* empty zone timeout is between x and 2*x seconds */
+#define XFRD_TRANSFER_TIMEOUT_MAX 86400 /* empty zone timeout max expbackoff */
+
extern xfrd_state_t* xfrd;
/* start xfrd, new start. Pass socket to server_main. */
@@ -256,6 +259,9 @@ void xfrd_init_slave_zone(xfrd_state_t* xfrd, zone_options_t* zone_opt);
/* delete slave zone */
void xfrd_del_slave_zone(xfrd_state_t* xfrd, const dname_type* dname);
+/* disable ixfr for a while for zone->master */
+void xfrd_disable_ixfr(xfrd_zone_t* zone);
+
/* get the current time epoch. Cached for speed. */
time_t xfrd_time(void);