/* true iff we will use the 0x20 hack to prevent poisoning attacks. */
int global_randomize_case;
+ /* The first time that a nameserver fails, how long do we wait before
+ * probing to see if it has returned? */
+ struct timeval global_nameserver_probe_initial_timeout;
+
/** Port to bind to for outgoing DNS packets. */
struct sockaddr_storage global_outgoing_address;
/** ev_socklen_t for global_outgoing_address. 0 if it isn't set. */
#define REQ_HEAD(base, id) ((base)->req_heads[id % (base)->n_req_heads])
-/* These are the timeout values for nameservers. If we find a nameserver is down */
-/* we try to probe it at intervals as given below. Values are in seconds. */
-static const struct timeval global_nameserver_timeouts[] = {{10, 0}, {60, 0}, {300, 0}, {900, 0}, {3600, 0}};
-static const int global_nameserver_timeouts_length = sizeof(global_nameserver_timeouts)/sizeof(struct timeval);
-
static struct nameserver *nameserver_pick(struct evdns_base *base);
static void evdns_request_insert(struct evdns_request *req, struct evdns_request **head);
static void evdns_request_remove(struct evdns_request *req, struct evdns_request **head);
/* and wait longer to send the next probe packet. */
static void
nameserver_probe_failed(struct nameserver *const ns) {
- const struct timeval * timeout;
+ struct timeval timeout;
+ int i;
ASSERT_LOCKED(ns->base);
(void) evtimer_del(&ns->timeout_event);
return;
}
- timeout =
- &global_nameserver_timeouts[MIN(ns->failed_times,
- global_nameserver_timeouts_length - 1)];
+#define MAX_PROBE_TIMEOUT 3600
+#define TIMEOUT_BACKOFF_FACTOR 3
+
+ memcpy(&timeout, &ns->base->global_nameserver_probe_initial_timeout,
+ sizeof(struct timeval));
+ for (i=ns->failed_times; i > 0 && timeout.tv_sec < MAX_PROBE_TIMEOUT; --i) {
+ timeout.tv_sec *= TIMEOUT_BACKOFF_FACTOR;
+ timeout.tv_usec *= TIMEOUT_BACKOFF_FACTOR;
+ if (timeout.tv_usec > 1000000) {
+ timeout.tv_sec += timeout.tv_usec / 1000000;
+ timeout.tv_usec %= 1000000;
+ }
+ }
+ if (timeout.tv_sec > MAX_PROBE_TIMEOUT) {
+ timeout.tv_sec = MAX_PROBE_TIMEOUT;
+ timeout.tv_usec = 0;
+ }
+
ns->failed_times++;
- if (evtimer_add(&ns->timeout_event, (struct timeval *) timeout) < 0) {
+ if (evtimer_add(&ns->timeout_event, &timeout) < 0) {
log(EVDNS_LOG_WARN,
"Error from libevent when adding timer event for %s",
debug_ntop((struct sockaddr *)&ns->address));
ns->state = 0;
ns->failed_times = 1;
- if (evtimer_add(&ns->timeout_event, (struct timeval *) &global_nameserver_timeouts[0]) < 0) {
+ if (evtimer_add(&ns->timeout_event,
+ &base->global_nameserver_probe_initial_timeout) < 0) {
log(EVDNS_LOG_WARN,
"Error from libevent when adding timer event for %s",
debug_ntop((struct sockaddr*)&ns->address));
(struct sockaddr*)&base->global_outgoing_address, &len))
return -1;
base->global_outgoing_addrlen = len;
+ } else if (str_matches_option(option, "initial-probe-timeout:")) {
+ struct timeval tv;
+ if (strtotimeval(val, &tv) == -1) return -1;
+ if (tv.tv_sec > 3600)
+ tv.tv_sec = 3600;
+ if (!(flags & DNS_OPTION_MISC)) return 0;
+ log(EVDNS_LOG_DEBUG, "Setting initial probe timeout to %s",
+ val);
+ memcpy(&base->global_nameserver_probe_initial_timeout, &tv,
+ sizeof(tv));
}
return 0;
}
base->global_randomize_case = 1;
base->global_getaddrinfo_allow_skew.tv_sec = 3;
base->global_getaddrinfo_allow_skew.tv_usec = 0;
+ base->global_nameserver_probe_initial_timeout.tv_sec = 10;
+ base->global_nameserver_probe_initial_timeout.tv_usec = 0;
if (initialize_nameservers) {
int r;
tt_assert(!evdns_base_nameserver_ip_add(dns, "127.0.0.1:53900"));
tt_assert(! evdns_base_set_option(dns, "timeout", "0.3", DNS_OPTIONS_ALL));
tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "10", DNS_OPTIONS_ALL));
+ tt_assert(! evdns_base_set_option(dns, "initial-probe-timeout", "0.5", DNS_OPTIONS_ALL));
evdns_base_resolve_ipv4(dns, "host.example.com", 0,
generic_dns_callback, &r1);
tt_int_op(r1.count, ==, 1);
tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080));
-
/* Now try again, but this time have the server get treated as
* failed, so we can send it a test probe. */
drop_count = 4;
n_replies_left = 2;
/* This will run until it answers the "google.com" probe request. */
- /* XXXX It takes 10 seconds to retry the probe, which makes the test
- * slow. */
event_base_dispatch(base);
/* We'll treat the server as failed here. */