Commit f91c2ae7 authored by Bob Halley's avatar Bob Halley
Browse files

basic priming support

parent dafb96ea
......@@ -189,6 +189,24 @@ dns_resolver_freeze(dns_resolver_t *res);
* 'res' is frozen.
*/
void
dns_resolver_prime(dns_resolver_t *res);
/*
* Prime resolver.
*
* Notes:
*
* Resolvers which have a forwarding policy other than dns_fwdpolicy_only
* need to be primed with the root nameservers, otherwise the root
* nameserver hints data may be used indefinitely. This function requests
* that the resolver start a priming fetch, if it isn't already priming.
*
* Requires:
*
* 'res' is a valid, frozen resolver.
*/
void
dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task,
isc_event_t **eventp);
......
......@@ -227,6 +227,8 @@ struct dns_resolver {
isc_boolean_t exiting;
isc_eventlist_t whenshutdown;
unsigned int activebuckets;
isc_boolean_t priming;
dns_fetch_t * primefetch;
};
#define RES_MAGIC 0x52657321U /* Res! */
......@@ -3320,6 +3322,8 @@ destroy(dns_resolver_t *res) {
unsigned int i;
REQUIRE(res->references == 0);
REQUIRE(!res->priming);
REQUIRE(res->primefetch == NULL);
RTRACE("destroy");
......@@ -3497,6 +3501,8 @@ dns_resolver_create(dns_view_t *view,
res->exiting = ISC_FALSE;
res->frozen = ISC_FALSE;
ISC_LIST_INIT(res->whenshutdown);
res->priming = ISC_FALSE;
res->primefetch = NULL;
result = isc_mutex_init(&res->lock);
if (result != ISC_R_SUCCESS)
......@@ -3588,6 +3594,110 @@ dns_resolver_setfwdpolicy(dns_resolver_t *res, dns_fwdpolicy_t fwdpolicy) {
return (ISC_R_SUCCESS);
}
static void
prime_done(isc_task_t *task, isc_event_t *event) {
dns_resolver_t *res;
dns_fetchevent_t *fevent;
dns_fetch_t *fetch;
REQUIRE(event->type == DNS_EVENT_FETCHDONE);
fevent = (dns_fetchevent_t *)event;
res = event->arg;
REQUIRE(VALID_RESOLVER(res));
(void)task;
LOCK(&res->lock);
INSIST(res->priming);
res->priming = ISC_FALSE;
fetch = res->primefetch;
res->primefetch = NULL;
UNLOCK(&res->lock);
if (fevent->node != NULL)
dns_db_detachnode(fevent->db, &fevent->node);
if (fevent->db != NULL)
dns_db_detach(&fevent->db);
if (dns_rdataset_isassociated(fevent->rdataset))
dns_rdataset_disassociate(fevent->rdataset);
INSIST(fevent->sigrdataset == NULL);
isc_mem_put(res->mctx, fevent->rdataset, sizeof *fevent->rdataset);
isc_event_free(&event);
dns_resolver_destroyfetch(&fetch);
}
void
dns_resolver_prime(dns_resolver_t *res) {
isc_boolean_t want_priming = ISC_FALSE;
dns_fetch_t *fetch;
dns_rdataset_t *rdataset;
isc_result_t result;
REQUIRE(VALID_RESOLVER(res));
REQUIRE(res->frozen);
RTRACE("dns_resolver_prime");
/*
* Forwarding-only resolvers don't need to be
* primed.
*/
if (res->fwdpolicy == dns_fwdpolicy_only)
return;
LOCK(&res->lock);
if (!res->exiting && !res->priming) {
INSIST(res->primefetch == NULL);
res->priming = ISC_TRUE;
want_priming = ISC_TRUE;
}
UNLOCK(&res->lock);
if (want_priming) {
/*
* To avoid any possible recursive locking problems, we
* start the priming fetch like any other fetch, and holding
* no resolver locks. No one else will try to start it
* because we're the ones who set res->priming to true.
* Any other callers of dns_resolver_prime() while we're
* running will see that res->priming is already true and
* do nothing.
*/
RTRACE("priming");
rdataset = isc_mem_get(res->mctx, sizeof *rdataset);
if (rdataset == NULL) {
LOCK(&res->lock);
INSIST(res->priming);
INSIST(res->primefetch == NULL);
res->priming = ISC_FALSE;
UNLOCK(&res->lock);
return;
}
dns_rdataset_init(rdataset);
fetch = NULL;
result = dns_resolver_createfetch(res, dns_rootname,
dns_rdatatype_ns,
NULL, NULL, NULL, 0,
res->buckets[0].task,
prime_done,
res, rdataset, NULL, &fetch);
LOCK(&res->lock);
INSIST(res->priming);
INSIST(res->primefetch == NULL);
if (result == ISC_R_SUCCESS)
res->primefetch = fetch;
else
res->priming = ISC_FALSE;
UNLOCK(&res->lock);
}
}
void
dns_resolver_freeze(dns_resolver_t *res) {
......
......@@ -557,10 +557,15 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
result = dns_db_find(view->hints, name, NULL, type, options,
now, NULL, foundname,
rdataset, sigrdataset);
if (result == ISC_R_SUCCESS || result == DNS_R_GLUE)
if (result == ISC_R_SUCCESS || result == DNS_R_GLUE) {
/*
* We just used a hint. Let the resolver know it
* should consider priming.
*/
dns_resolver_prime(view->resolver);
result = DNS_R_HINT;
else if (result == DNS_R_NXDOMAIN ||
result == DNS_R_NXRDATASET)
} else if (result == DNS_R_NXDOMAIN ||
result == DNS_R_NXRDATASET)
result = DNS_R_NOTFOUND;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment