mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-22 10:10:14 -04:00
Resolver is parent-centric
The resolver now uses glue addresses from `dns_deleg_t` objects stored in the delegation database. The main cache is still used for ADB A/AAAA lookups when no glue is available for a nameserver name. The resolver's `fctx_getaddresses()` is refactored to, for each delegation of the delegation set, try to get the address-based finds, then nameserver name lookups. (Later, the logic to handle DELEG `include-delegparm=` will be hooked there too.)
This commit is contained in:
parent
cfac5f3974
commit
6ed7a8a723
3 changed files with 162 additions and 54 deletions
|
|
@ -1716,23 +1716,29 @@ dns_adb_shutdown(dns_adb_t *adb) {
|
|||
|
||||
static void
|
||||
findaddrinfo(dns_adb_t *adb, const isc_sockaddr_t *addr,
|
||||
dns_adbaddrinfo_t **adbaddrp, isc_stdtime_t now) {
|
||||
dns_adbaddrinfo_t **adbaddrp, isc_stdtime_t now,
|
||||
unsigned int options) {
|
||||
dns_adbentry_t *adbentry = get_attached_and_locked_entry(adb, now,
|
||||
addr);
|
||||
if ((options & DNS_ADBFIND_QUOTAEXEMPT) == 0 &&
|
||||
adbentry_overquota(adbentry))
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
in_port_t port = isc_sockaddr_getport(addr);
|
||||
*adbaddrp = new_adbaddrinfo(adb, adbentry, port);
|
||||
|
||||
out:
|
||||
UNLOCK(&adbentry->lock);
|
||||
dns_adbentry_detach(&adbentry);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
void
|
||||
dns_adb_createaddrinfosfind(dns_adb_t *adb, isc_netaddrlist_t *addrs,
|
||||
in_port_t port, unsigned int options,
|
||||
isc_stdtime_t now, size_t maxaddrs,
|
||||
dns_adbfind_t **findp, size_t *findlen) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
dns_adbfind_t *find = NULL;
|
||||
isc_sockaddr_t sockaddr = {};
|
||||
|
||||
|
|
@ -1743,7 +1749,8 @@ dns_adb_createaddrinfosfind(dns_adb_t *adb, isc_netaddrlist_t *addrs,
|
|||
rcu_read_lock();
|
||||
|
||||
if (atomic_load(&adb->shuttingdown)) {
|
||||
CLEANUP(ISC_R_SHUTTINGDOWN);
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (now == 0) {
|
||||
|
|
@ -1779,7 +1786,12 @@ dns_adb_createaddrinfosfind(dns_adb_t *adb, isc_netaddrlist_t *addrs,
|
|||
UNREACHABLE();
|
||||
}
|
||||
|
||||
findaddrinfo(adb, &sockaddr, &addrinfo, now);
|
||||
findaddrinfo(adb, &sockaddr, &addrinfo, now, options);
|
||||
if (addrinfo == NULL) {
|
||||
find->options |= DNS_ADBFIND_OVERQUOTA;
|
||||
continue;
|
||||
}
|
||||
|
||||
ISC_LIST_APPEND(find->list, addrinfo, publink);
|
||||
(*findlen)++;
|
||||
|
||||
|
|
@ -1789,9 +1801,7 @@ dns_adb_createaddrinfosfind(dns_adb_t *adb, isc_netaddrlist_t *addrs,
|
|||
}
|
||||
|
||||
*findp = find;
|
||||
cleanup:
|
||||
rcu_read_unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -3217,7 +3227,7 @@ dns_adb_findaddrinfo(dns_adb_t *adb, const isc_sockaddr_t *addr,
|
|||
return ISC_R_SHUTTINGDOWN;
|
||||
}
|
||||
|
||||
findaddrinfo(adb, addr, adbaddrp, now);
|
||||
findaddrinfo(adb, addr, adbaddrp, now, DNS_ADBFIND_QUOTAEXEMPT);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_loop_t *loop, isc_job_cb cb, void *cbarg,
|
|||
* returns.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
void
|
||||
dns_adb_createaddrinfosfind(dns_adb_t *adb, isc_netaddrlist_t *addrs,
|
||||
in_port_t port, unsigned int options,
|
||||
isc_stdtime_t now, size_t maxaddrs,
|
||||
|
|
|
|||
|
|
@ -3654,47 +3654,123 @@ fctx_getaddresses_forwarders(fetchctx_t *fctx) {
|
|||
return DNS_R_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
fctx_getaddresses_addresses(fetchctx_t *fctx, isc_stdtime_t now,
|
||||
unsigned int options, bool *allspilledp,
|
||||
size_t *ns_processed) {
|
||||
dns_adbfindlist_t finds = ISC_LIST_INITIALIZER;
|
||||
size_t max_delegation_servers = fctx->res->view->max_delegation_servers;
|
||||
|
||||
if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0) {
|
||||
options |= DNS_ADBFIND_QUOTAEXEMPT;
|
||||
}
|
||||
|
||||
ISC_LIST_FOREACH(fctx->delegset->delegs, deleg, link) {
|
||||
dns_adbfind_t *find = NULL;
|
||||
size_t maxaddrs = max_delegation_servers - *ns_processed;
|
||||
size_t findlen = 0;
|
||||
|
||||
if (*ns_processed >= max_delegation_servers) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (deleg->type != DNS_DELEGTYPE_DELEG_ADDRESSES &&
|
||||
deleg->type != DNS_DELEGTYPE_NS_GLUES)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ISC_LIST_EMPTY(deleg->addresses)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fetchctx_ref(fctx);
|
||||
dns_adb_createaddrinfosfind(fctx->adb, &deleg->addresses,
|
||||
fctx->res->view->dstport, options,
|
||||
now, maxaddrs, &find, &findlen);
|
||||
|
||||
if (find == NULL) {
|
||||
fetchctx_unref(fctx);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((find->options & DNS_ADBFIND_OVERQUOTA) != 0) {
|
||||
*allspilledp = true;
|
||||
fctx->quotacount++;
|
||||
}
|
||||
|
||||
if (ISC_LIST_EMPTY(find->list)) {
|
||||
fetchctx_unref(fctx);
|
||||
dns_adb_destroyfind(&find);
|
||||
break;
|
||||
}
|
||||
|
||||
*ns_processed += findlen;
|
||||
INSIST(*ns_processed <= max_delegation_servers);
|
||||
ISC_LIST_APPEND(finds, find, publink);
|
||||
}
|
||||
|
||||
if (!ISC_LIST_EMPTY(finds)) {
|
||||
ISC_LIST_APPENDLIST(fctx->finds, finds, publink);
|
||||
}
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
fctx_getaddresses_nameservers(fetchctx_t *fctx, isc_stdtime_t now,
|
||||
unsigned int stdoptions, size_t fetches_allowed,
|
||||
bool *need_alternatep, bool *all_spilledp) {
|
||||
bool *need_alternatep, bool *all_spilledp,
|
||||
size_t *ns_processed) {
|
||||
bool have_address = false;
|
||||
unsigned int ns_processed = 0;
|
||||
uint32_t ns_processing_limit = fctx->res->view->max_delegation_servers;
|
||||
dns_namelist_t *availablens = NULL;
|
||||
unsigned int name_processed = 0;
|
||||
static thread_local dns_name_t *nameservers[MAX_DELEGATION_SERVERS];
|
||||
size_t max_delegation_servers = fctx->res->view->max_delegation_servers;
|
||||
|
||||
/*
|
||||
* For now, only NS-based deleg is supported, and this can be only in a
|
||||
* single list element.
|
||||
* Lookup through each delegation for this zonecut (represented by
|
||||
* `delegset`).
|
||||
*
|
||||
* If this is an NS-based delegation, each `deleg` represents an NS RR
|
||||
* and will have a single server name.
|
||||
*
|
||||
* If this is a DELEG-based delegation, each `deleg` represents a DELEG
|
||||
* RR and might have multiple server names.
|
||||
*/
|
||||
INSIST(ISC_LIST_HEAD(fctx->delegset->deleg) ==
|
||||
ISC_LIST_TAIL(fctx->delegset->deleg));
|
||||
availablens = &ISC_LIST_HEAD(fctx->delegset->deleg)->nameserver;
|
||||
ISC_LIST_FOREACH(fctx->delegset->delegs, deleg, link) {
|
||||
if (deleg->type != DNS_DELEGTYPE_DELEG_NAMES &&
|
||||
deleg->type != DNS_DELEGTYPE_NS_NAMES)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ISC_LIST_FOREACH(*availablens, ns, link) {
|
||||
nameservers[ns_processed] = ns;
|
||||
if (ISC_LIST_EMPTY(deleg->names)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (++ns_processed >= ns_processing_limit) {
|
||||
break;
|
||||
ISC_LIST_FOREACH(deleg->names, ns, link) {
|
||||
nameservers[name_processed++] = ns;
|
||||
|
||||
if (name_processed >= max_delegation_servers) {
|
||||
goto shufflens;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ns_processed > 1 && ns_processed > fetches_allowed) {
|
||||
shufflens:
|
||||
if (name_processed > 1 && name_processed > fetches_allowed) {
|
||||
/*
|
||||
* Skip the shuffle if:
|
||||
* - there's nothing to shuffle (no or one nameserver)
|
||||
* - there are less nameserver than allowed fetches as
|
||||
* we are going to start fetches for all of them.
|
||||
*/
|
||||
for (size_t i = 0; i < ns_processed - 1; i++) {
|
||||
size_t j = i + isc_random_uniform(ns_processed - i);
|
||||
for (size_t i = 0; i < name_processed - 1; i++) {
|
||||
size_t j = i + isc_random_uniform(name_processed - i);
|
||||
|
||||
ISC_SWAP(nameservers[i], nameservers[j]);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ns_processed; i++) {
|
||||
for (size_t i = 0; i < name_processed; i++) {
|
||||
bool overquota = false;
|
||||
unsigned int static_stub = 0;
|
||||
unsigned int no_fetch = 0;
|
||||
|
|
@ -3720,6 +3796,10 @@ fctx_getaddresses_nameservers(fetchctx_t *fctx, isc_stdtime_t now,
|
|||
if (!overquota) {
|
||||
*all_spilledp = false;
|
||||
}
|
||||
|
||||
if (++(*ns_processed) >= max_delegation_servers) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fctx->pending_running == 0 && !have_address) {
|
||||
|
|
@ -3782,6 +3862,7 @@ fctx_getaddresses(fetchctx_t *fctx) {
|
|||
bool need_alternate = false;
|
||||
bool all_spilled = false;
|
||||
size_t fetches_allowed = 0;
|
||||
size_t ns_processed = 0;
|
||||
|
||||
FCTXTRACE5("getaddresses", "fctx->depth=", fctx->depth);
|
||||
|
||||
|
|
@ -3867,25 +3948,45 @@ fctx_getaddresses(fetchctx_t *fctx) {
|
|||
}
|
||||
|
||||
now = isc_stdtime_now();
|
||||
all_spilled = true; /* resets to false below after the first success */
|
||||
|
||||
INSIST(ISC_LIST_EMPTY(fctx->finds));
|
||||
INSIST(ISC_LIST_EMPTY(fctx->altfinds));
|
||||
|
||||
/*
|
||||
* A dns_delegset_t can only have either
|
||||
*
|
||||
* - addresses (either from DELEG-based delegation with only addresses,
|
||||
* or NS-based delegation with glues)
|
||||
* - name servers to lookup (either from DELEG-based delegation with
|
||||
* only name servers, or NS-based delegation without glues)
|
||||
* - include-delegparam (from DELEG-based delegation only -- NYI).
|
||||
*
|
||||
* So let's try in this order. If nothing's found, then we can attempt
|
||||
* alternates.
|
||||
*
|
||||
* Either way, the maximum number of nameserver names and addresses used
|
||||
* for this resolution is at most `max_delegation_servers`. This is why
|
||||
* `ns_processed` is shared with `fctx_getaddresses_addresses` and
|
||||
* `fctx_getaddresses_nameservers`.
|
||||
* */
|
||||
|
||||
fctx_getaddresses_addresses(fctx, now, stdoptions, &all_spilled,
|
||||
&ns_processed);
|
||||
|
||||
fetches_allowed = fctx_getaddresses_allowed(fctx);
|
||||
|
||||
result = fctx_getaddresses_nameservers(fctx, now, stdoptions,
|
||||
fetches_allowed, &need_alternate,
|
||||
&all_spilled);
|
||||
&all_spilled, &ns_processed);
|
||||
if (result == DNS_R_CONTINUE && fetches_allowed == 0) {
|
||||
/*
|
||||
* We have no addresses and we haven't allowed any
|
||||
* fetches to be started. Allow one extra fetch and try
|
||||
* again.
|
||||
*/
|
||||
(void)fctx_getaddresses_nameservers(fctx, now, stdoptions, 1,
|
||||
&need_alternate,
|
||||
&all_spilled);
|
||||
(void)fctx_getaddresses_nameservers(
|
||||
fctx, now, stdoptions, 1, &need_alternate, &all_spilled,
|
||||
&ns_processed);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -6229,15 +6330,13 @@ cleanup:
|
|||
|
||||
static isc_result_t
|
||||
rctx_cachemessage(respctx_t *rctx) {
|
||||
isc_result_t result;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
fetchctx_t *fctx = rctx->fctx;
|
||||
resquery_t *query = rctx->query;
|
||||
dns_message_t *message = query->rmessage;
|
||||
|
||||
FCTXTRACE("rctx_cachemessage");
|
||||
|
||||
FCTX_ATTR_CLR(fctx, FCTX_ATTR_WANTCACHE);
|
||||
|
||||
LOCK(&fctx->lock);
|
||||
|
||||
for (dns_section_t section = DNS_SECTION_ANSWER;
|
||||
|
|
@ -6250,6 +6349,8 @@ rctx_cachemessage(respctx_t *rctx) {
|
|||
}
|
||||
}
|
||||
|
||||
FCTX_ATTR_CLR(fctx, FCTX_ATTR_WANTCACHE);
|
||||
|
||||
cleanup:
|
||||
UNLOCK(&fctx->lock);
|
||||
return result;
|
||||
|
|
@ -9136,26 +9237,6 @@ rctx_referral(respctx_t *rctx) {
|
|||
return ISC_R_COMPLETE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark any additional data related to this rdataset.
|
||||
* It's important that we do this before we change the
|
||||
* query domain.
|
||||
*/
|
||||
INSIST(rctx->ns_rdataset != NULL);
|
||||
FCTX_ATTR_SET(fctx, FCTX_ATTR_GLUING);
|
||||
/*
|
||||
* We want to append **all** the GLUE records here.
|
||||
*/
|
||||
(void)dns_rdataset_additionaldata(rctx->ns_rdataset, rctx->ns_name,
|
||||
check_related, rctx, 0);
|
||||
FCTX_ATTR_CLR(fctx, FCTX_ATTR_GLUING);
|
||||
|
||||
/*
|
||||
* An NS-based delegation can be cached immediately (i.e. there is
|
||||
* no DNSSEC validation).
|
||||
*/
|
||||
cache_delegns(rctx);
|
||||
|
||||
/*
|
||||
* NS rdatasets with 0 TTL cause problems.
|
||||
* dns_view_findzonecut() will not find them when we
|
||||
|
|
@ -9167,6 +9248,17 @@ rctx_referral(respctx_t *rctx) {
|
|||
rctx->ns_rdataset->ttl = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* An NS-based delegation can be cached immediately (i.e. there is no
|
||||
* DNSSEC validation).
|
||||
*
|
||||
* For now we don't do anything if the delegation already exists and is
|
||||
* not expired in the DB. Might be worth a warning? This should never
|
||||
* happen.
|
||||
*/
|
||||
INSIST(rctx->ns_rdataset != NULL);
|
||||
(void)cache_delegns(rctx);
|
||||
|
||||
/*
|
||||
* Set the current query domain to the referral name.
|
||||
*
|
||||
|
|
@ -9192,7 +9284,13 @@ rctx_referral(respctx_t *rctx) {
|
|||
return ISC_R_COMPLETE;
|
||||
}
|
||||
|
||||
/*
|
||||
* While NS and glue records in referral responses are stored in the
|
||||
* delegation database and not the main cache, other records, such as
|
||||
* DS, do still need to be stored in the main cache.
|
||||
*/
|
||||
FCTX_ATTR_SET(fctx, FCTX_ATTR_WANTCACHE);
|
||||
|
||||
fctx->ns_ttl_ok = false;
|
||||
log_ns_ttl(fctx, "DELEGATION");
|
||||
rctx->result = DNS_R_DELEGATION;
|
||||
|
|
|
|||
Loading…
Reference in a new issue