mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 15:05:23 +00:00
basic priming support
This commit is contained in:
@@ -189,6 +189,24 @@ dns_resolver_freeze(dns_resolver_t *res);
|
|||||||
* 'res' is frozen.
|
* '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
|
void
|
||||||
dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task,
|
dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task,
|
||||||
isc_event_t **eventp);
|
isc_event_t **eventp);
|
||||||
|
@@ -227,6 +227,8 @@ struct dns_resolver {
|
|||||||
isc_boolean_t exiting;
|
isc_boolean_t exiting;
|
||||||
isc_eventlist_t whenshutdown;
|
isc_eventlist_t whenshutdown;
|
||||||
unsigned int activebuckets;
|
unsigned int activebuckets;
|
||||||
|
isc_boolean_t priming;
|
||||||
|
dns_fetch_t * primefetch;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define RES_MAGIC 0x52657321U /* Res! */
|
#define RES_MAGIC 0x52657321U /* Res! */
|
||||||
@@ -3320,6 +3322,8 @@ destroy(dns_resolver_t *res) {
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
REQUIRE(res->references == 0);
|
REQUIRE(res->references == 0);
|
||||||
|
REQUIRE(!res->priming);
|
||||||
|
REQUIRE(res->primefetch == NULL);
|
||||||
|
|
||||||
RTRACE("destroy");
|
RTRACE("destroy");
|
||||||
|
|
||||||
@@ -3497,6 +3501,8 @@ dns_resolver_create(dns_view_t *view,
|
|||||||
res->exiting = ISC_FALSE;
|
res->exiting = ISC_FALSE;
|
||||||
res->frozen = ISC_FALSE;
|
res->frozen = ISC_FALSE;
|
||||||
ISC_LIST_INIT(res->whenshutdown);
|
ISC_LIST_INIT(res->whenshutdown);
|
||||||
|
res->priming = ISC_FALSE;
|
||||||
|
res->primefetch = NULL;
|
||||||
|
|
||||||
result = isc_mutex_init(&res->lock);
|
result = isc_mutex_init(&res->lock);
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
@@ -3588,6 +3594,110 @@ dns_resolver_setfwdpolicy(dns_resolver_t *res, dns_fwdpolicy_t fwdpolicy) {
|
|||||||
return (ISC_R_SUCCESS);
|
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
|
void
|
||||||
dns_resolver_freeze(dns_resolver_t *res) {
|
dns_resolver_freeze(dns_resolver_t *res) {
|
||||||
|
|
||||||
|
@@ -557,9 +557,14 @@ 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,
|
result = dns_db_find(view->hints, name, NULL, type, options,
|
||||||
now, NULL, foundname,
|
now, NULL, foundname,
|
||||||
rdataset, sigrdataset);
|
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;
|
result = DNS_R_HINT;
|
||||||
else if (result == DNS_R_NXDOMAIN ||
|
} else if (result == DNS_R_NXDOMAIN ||
|
||||||
result == DNS_R_NXRDATASET)
|
result == DNS_R_NXRDATASET)
|
||||||
result = DNS_R_NOTFOUND;
|
result = DNS_R_NOTFOUND;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user