diff options
Diffstat (limited to 'usr.sbin/nsd/xfrd.c')
-rw-r--r-- | usr.sbin/nsd/xfrd.c | 122 |
1 files changed, 57 insertions, 65 deletions
diff --git a/usr.sbin/nsd/xfrd.c b/usr.sbin/nsd/xfrd.c index 21a37448dff..65d6d955af6 100644 --- a/usr.sbin/nsd/xfrd.c +++ b/usr.sbin/nsd/xfrd.c @@ -40,8 +40,6 @@ #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 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. */ @@ -761,38 +759,28 @@ xfrd_set_timer_refresh(xfrd_zone_type* zone) { time_t set_refresh; time_t set_expire; - time_t set_min; time_t set; if(zone->soa_disk_acquired == 0 || zone->state != xfrd_zone_ok) { xfrd_set_timer_retry(zone); return; } /* refresh or expire timeout, whichever is earlier */ - set_refresh = ntohl(zone->soa_disk.refresh); - if (set_refresh > (time_t)zone->zone_options->pattern->max_refresh_time) - set_refresh = zone->zone_options->pattern->max_refresh_time; - else if (set_refresh < (time_t)zone->zone_options->pattern->min_refresh_time) - set_refresh = zone->zone_options->pattern->min_refresh_time; - set_refresh += zone->soa_disk_acquired; - set_expire = zone->soa_disk_acquired + ntohl(zone->soa_disk.expire); - if(set_refresh < set_expire) - set = set_refresh; - else set = set_expire; - set_min = zone->soa_disk_acquired + XFRD_LOWERBOUND_REFRESH; - if(set < set_min) - set = set_min; - if(set < xfrd_time()) - set = 0; - else set -= xfrd_time(); - if(set > XFRD_TRANSFER_TIMEOUT_MAX) - set = XFRD_TRANSFER_TIMEOUT_MAX; - xfrd_set_timer(zone, set); + set_refresh = bound_soa_disk_refresh(zone); + set_expire = bound_soa_disk_expire(zone); + set = zone->soa_disk_acquired + ( set_refresh < set_expire + ? set_refresh : set_expire ); + + /* set point in time to period for xfrd_set_timer() */ + xfrd_set_timer(zone, within_refresh_bounds(zone, + set > xfrd_time() + ? set - xfrd_time() : XFRD_LOWERBOUND_REFRESH)); } static void xfrd_set_timer_retry(xfrd_zone_type* zone) { time_t set_retry; + time_t set_expire; int mult; /* perform exponential backoff in all the cases */ if(zone->fresh_xfr_timeout == 0) @@ -810,37 +798,36 @@ xfrd_set_timer_retry(xfrd_zone_type* zone) /* set timer for next retry or expire timeout if earlier. */ if(zone->soa_disk_acquired == 0) { - /* if no information, use reasonable timeout */ - xfrd_set_timer(zone, zone->fresh_xfr_timeout - + random_generate(zone->fresh_xfr_timeout)); - } else if(zone->state == xfrd_zone_expired || - 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 > XFRD_TRANSFER_TIMEOUT_MAX) - set_retry = XFRD_TRANSFER_TIMEOUT_MAX; - 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) - set_retry = zone->zone_options->pattern->min_retry_time; - if(set_retry < XFRD_LOWERBOUND_RETRY) - set_retry = XFRD_LOWERBOUND_RETRY; + /* if no information, use reasonable timeout + * within configured and defined bounds + */ + xfrd_set_timer(zone, + within_retry_bounds(zone, zone->fresh_xfr_timeout + + random_generate(zone->fresh_xfr_timeout))); + return; + } + /* exponential backoff within configured and defined bounds */ + set_retry = within_retry_bounds(zone, + ntohl(zone->soa_disk.retry) * mult); + if(zone->state == xfrd_zone_expired) { xfrd_set_timer(zone, set_retry); - } else { - set_retry = ntohl(zone->soa_disk.expire); - if(set_retry > XFRD_TRANSFER_TIMEOUT_MAX) - set_retry = XFRD_TRANSFER_TIMEOUT_MAX; - if(set_retry < XFRD_LOWERBOUND_RETRY) - xfrd_set_timer(zone, XFRD_LOWERBOUND_RETRY); - else { - 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 + - set_retry - xfrd_time()); - } + return; } + /* retry or expire timeout, whichever is earlier */ + set_expire = zone->soa_disk_acquired + bound_soa_disk_expire(zone); + if(xfrd_time() + set_retry < set_expire) { + xfrd_set_timer(zone, set_retry); + return; + } + /* Not expired, but next retry will be > than expire timeout. + * Retry when the expire timeout runs out. + * set_expire is below retry upper bounds (if statement above), + * but not necessarily above lower bounds, + * so use within_retry_bounds() again. + */ + xfrd_set_timer(zone, within_retry_bounds(zone, + set_expire > xfrd_time() + ? set_expire - xfrd_time() : XFRD_LOWERBOUND_RETRY)); } void @@ -889,13 +876,15 @@ xfrd_handle_zone(int ATTR_UNUSED(fd), short event, void* arg) if(zone->soa_disk_acquired) { if (zone->state != xfrd_zone_expired && - xfrd_time() >= zone->soa_disk_acquired + (time_t)ntohl(zone->soa_disk.expire)) { + xfrd_time() >= zone->soa_disk_acquired + + bound_soa_disk_expire(zone)) { /* zone expired */ log_msg(LOG_ERR, "xfrd: zone %s has expired", zone->apex_str); xfrd_set_zone_state(zone, xfrd_zone_expired); } else if(zone->state == xfrd_zone_ok && - xfrd_time() >= zone->soa_disk_acquired + (time_t)ntohl(zone->soa_disk.refresh)) { + xfrd_time() >= zone->soa_disk_acquired + + bound_soa_disk_refresh(zone)) { /* zone goes to refreshing state. */ DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: zone %s is refreshing", zone->apex_str)); xfrd_set_zone_state(zone, xfrd_zone_refreshing); @@ -1152,6 +1141,8 @@ xfrd_set_timer(xfrd_zone_type* zone, time_t t) { int fd = zone->zone_handler.ev_fd; int fl = ((fd == -1)?EV_TIMEOUT:zone->zone_handler_flags); + if(t > XFRD_TRANSFER_TIMEOUT_MAX) + t = XFRD_TRANSFER_TIMEOUT_MAX; /* randomize the time, within 90%-100% of original */ /* not later so zones cannot expire too late */ /* only for times far in the future */ @@ -1180,6 +1171,7 @@ void xfrd_handle_incoming_soa(xfrd_zone_type* zone, xfrd_soa_type* soa, time_t acquired) { + time_t seconds_since_acquired; if(soa == NULL) { /* nsd no longer has a zone in memory */ zone->soa_nsd_acquired = 0; @@ -1201,22 +1193,22 @@ xfrd_handle_incoming_soa(xfrd_zone_type* zone, 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)) + seconds_since_acquired = + xfrd_time() > zone->soa_disk_acquired + ? xfrd_time() - zone->soa_disk_acquired : 0; + if(seconds_since_acquired < bound_soa_disk_refresh(zone)) { /* zone ok, wait for refresh time */ xfrd_set_zone_state(zone, xfrd_zone_ok); zone->round_num = -1; xfrd_set_timer_refresh(zone); - } else if(xfrd_time() - zone->soa_disk_acquired - < (time_t)ntohl(zone->soa_disk.expire)) + } else if(seconds_since_acquired < bound_soa_disk_expire(zone)) { /* zone refreshing */ xfrd_set_zone_state(zone, xfrd_zone_refreshing); xfrd_set_refresh_now(zone); } - if(xfrd_time() - zone->soa_disk_acquired - >= (time_t)ntohl(zone->soa_disk.expire)) { + if(seconds_since_acquired >= bound_soa_disk_expire(zone)) { /* zone expired */ xfrd_set_zone_state(zone, xfrd_zone_expired); xfrd_set_refresh_now(zone); @@ -1950,12 +1942,12 @@ xfrd_parse_received_xfr_packet(xfrd_zone_type* zone, buffer_type* packet, if(zone->soa_disk_acquired != 0 && zone->state != xfrd_zone_expired /* if expired - accept anything */ && compare_serial(ntohl(soa->serial), ntohl(zone->soa_disk.serial)) < 0) { - DEBUG(DEBUG_XFRD,1, (LOG_INFO, - "xfrd: zone %s ignoring old serial from %s", - zone->apex_str, zone->master->ip_address_spec)); - VERBOSITY(1, (LOG_INFO, - "xfrd: zone %s ignoring old serial from %s", - zone->apex_str, zone->master->ip_address_spec)); + DEBUG(DEBUG_XFRD,1, (LOG_INFO, + "xfrd: zone %s ignoring old serial (%u/%u) from %s", + zone->apex_str, ntohl(zone->soa_disk.serial), ntohl(soa->serial), zone->master->ip_address_spec)); + VERBOSITY(1, (LOG_INFO, + "xfrd: zone %s ignoring old serial (%u/%u) from %s", + zone->apex_str, ntohl(zone->soa_disk.serial), ntohl(soa->serial), zone->master->ip_address_spec)); region_destroy(tempregion); return xfrd_packet_bad; } |