diff options
author | florian <florian@openbsd.org> | 2017-01-17 06:21:41 +0000 |
---|---|---|
committer | florian <florian@openbsd.org> | 2017-01-17 06:21:41 +0000 |
commit | 6a6b9a23b4a8887e42cfb3bb27132265346775ce (patch) | |
tree | 043c8d8783d138a6bc42943a3f28222441f0f7bc /usr.sbin/nsd | |
parent | Simplify the usage of print_otag() by making it accept a variable (diff) | |
download | wireguard-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.lex | 34 | ||||
-rw-r--r-- | usr.sbin/nsd/configure.ac | 2 | ||||
-rw-r--r-- | usr.sbin/nsd/radtree.c | 6 | ||||
-rw-r--r-- | usr.sbin/nsd/remote.c | 2 | ||||
-rw-r--r-- | usr.sbin/nsd/xfrd-disk.c | 32 | ||||
-rw-r--r-- | usr.sbin/nsd/xfrd-disk.h | 2 | ||||
-rw-r--r-- | usr.sbin/nsd/xfrd-tcp.c | 10 | ||||
-rw-r--r-- | usr.sbin/nsd/xfrd.c | 59 | ||||
-rw-r--r-- | usr.sbin/nsd/xfrd.h | 6 |
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); |