/*% Locked by loop event serialization. */
dns_fixedname_t dfname;
dns_name_t *domain;
- dns_rdataset_t nameservers;
+ dns_delegset_t *delegset;
atomic_uint_fast32_t attributes;
isc_timer_t *timer;
isc_time_t expires;
#define BADCOOKIE(a) (((a)->flags & FCTX_ADDRINFO_BADCOOKIE) != 0)
#define ISDUALSTACK(a) (((a)->flags & FCTX_ADDRINFO_DUALSTACK) != 0)
-#define NXDOMAIN(r) (((r)->attributes.nxdomain))
-#define NEGATIVE(r) (((r)->attributes.negative))
-#define STATICSTUB(r) (((r)->attributes.staticstub))
+#define NXDOMAIN(r) (((r)->attributes.nxdomain))
+#define NEGATIVE(r) (((r)->attributes.negative))
#ifdef ENABLE_AFL
bool dns_fuzzing_resolver = false;
static isc_result_t
get_attached_fctx(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
dns_rdatatype_t type, const dns_name_t *domain,
- dns_rdataset_t *nameservers, const isc_sockaddr_t *client,
+ dns_delegset_t *delegset, const isc_sockaddr_t *client,
unsigned int options, unsigned int depth, isc_counter_t *qc,
isc_counter_t *gqc, fetchctx_t *parent, fetchctx_t **fctxp,
bool *new_fctx);
fctx_getaddresses_nameservers(fetchctx_t *fctx, isc_stdtime_t now,
unsigned int stdoptions, size_t fetches_allowed,
bool *need_alternatep, bool *all_spilledp) {
- dns_rdata_ns_t ns;
bool have_address = false;
unsigned int ns_processed = 0;
uint32_t ns_processing_limit = fctx->res->view->max_delegation_servers;
- static thread_local dns_rdata_t nameservers_s[MAX_DELEGATION_SERVERS];
- static thread_local dns_rdata_t *nameservers[MAX_DELEGATION_SERVERS];
+ dns_namelist_t *availablens = NULL;
+ static thread_local dns_name_t *nameservers[MAX_DELEGATION_SERVERS];
- DNS_RDATASET_FOREACH(&fctx->nameservers) {
- dns_rdata_t *rdata = nameservers[ns_processed] =
- &nameservers_s[ns_processed];
-
- dns_rdata_init(rdata);
+ /*
+ * For now, only NS-based deleg is supported, and this can be only in a
+ * single list element.
+ */
+ INSIST(ISC_LIST_HEAD(fctx->delegset->deleg) ==
+ ISC_LIST_TAIL(fctx->delegset->deleg));
+ availablens = &ISC_LIST_HEAD(fctx->delegset->deleg)->nameserver;
- dns_rdataset_current(&fctx->nameservers, rdata);
+ ISC_LIST_FOREACH(*availablens, ns, link) {
+ nameservers[ns_processed] = ns;
if (++ns_processed >= ns_processing_limit) {
break;
}
for (size_t i = 0; i < ns_processed; i++) {
- isc_result_t result = ISC_R_SUCCESS;
bool overquota = false;
unsigned int static_stub = 0;
unsigned int no_fetch = 0;
- dns_rdata_t *rdata = nameservers[i];
-
- /*
- * Extract the name from the NS record.
- */
- result = dns_rdata_tostruct(rdata, &ns, NULL);
- if (result != ISC_R_SUCCESS) {
- continue;
- }
+ dns_name_t *ns = nameservers[i];
- if (STATICSTUB(&fctx->nameservers) &&
- dns_name_equal(&ns.name, fctx->domain))
+ if (fctx->delegset->staticstub &&
+ dns_name_equal(ns, fctx->domain))
{
static_stub = DNS_ADBFIND_STATICSTUB;
}
no_fetch = DNS_ADBFIND_NOFETCH;
}
- findname(fctx, &ns.name, 0, stdoptions | static_stub | no_fetch,
- 0, now, &overquota, need_alternatep, &have_address);
+ findname(fctx, ns, 0, stdoptions | static_stub | no_fetch, 0,
+ now, &overquota, need_alternatep, &have_address);
if (!overquota) {
*all_spilledp = false;
}
-
- dns_rdata_freestruct(&ns);
}
if (fctx->pending_running == 0 && !have_address) {
fetchctx_ref(fctx);
result = dns_resolver_createfetch(
fctx->res, fctx->qmin.name, fctx->qmintype,
- fctx->domain, &fctx->nameservers, NULL, NULL, 0,
+ fctx->domain, fctx->delegset, NULL, NULL, 0,
options | DNS_FETCHOPT_QMINFETCH, 0, fctx->qc,
fctx->gqc, fctx, fctx->loop, resume_qmin, fctx,
&fctx->edectx, &fctx->qmin.rdataset,
}
clear_resp(&resp);
- dns_rdataset_cleanup(&fctx->nameservers);
+ dns_delegset_detach(&fctx->delegset);
if (dns_rdatatype_atparent(fctx->type)) {
findoptions |= DNS_DBFIND_NOEXACT;
}
result = dns_view_bestzonecut(res->view, fctx->name, fname, dcname,
fctx->now, findoptions, true, true,
- &fctx->nameservers);
+ &fctx->delegset);
FCTXTRACEN("resume_qmin findzonecut", fname, result);
if (result != ISC_R_SUCCESS) {
CHECK(fcount_incr(fctx, false));
dns_name_copy(dcname, fctx->qmin.dcname);
- fctx->ns_ttl = fctx->nameservers.ttl;
+ fctx->ns_ttl = fctx->delegset->expires - fctx->now;
fctx->ns_ttl_ok = true;
fctx_minimize_qname(fctx);
}
fcount_decr(fctx);
dns_message_detach(&fctx->qmessage);
- dns_rdataset_cleanup(&fctx->nameservers);
+ if (fctx->delegset != NULL) {
+ dns_delegset_detach(&fctx->delegset);
+ }
dns_db_detach(&fctx->cache);
dns_adb_detach(&fctx->adb);
dns_dispatchmgr_detach(&fctx->dispatchmgr);
static isc_result_t
fctx__create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
dns_rdatatype_t type, const dns_name_t *domain,
- dns_rdataset_t *nameservers, const isc_sockaddr_t *client,
+ dns_delegset_t *delegset, const isc_sockaddr_t *client,
unsigned int options, unsigned int depth, isc_counter_t *qc,
isc_counter_t *gqc, fetchctx_t *parent, fetchctx_t **fctxp,
const char *func, const char *file, const unsigned int line) {
.bad = ISC_LIST_INITIALIZER,
.edns = ISC_LIST_INITIALIZER,
.validators = ISC_LIST_INITIALIZER,
- .nameservers = DNS_RDATASET_INIT,
.nsrrset = DNS_RDATASET_INIT,
.resp_result = DNS_R_SERVFAIL,
.qmin.rdataset = DNS_RDATASET_INIT,
result = dns_view_bestzonecut(
res->view, name, fctx->fwdname, dcname,
fctx->now, findoptions, true, true,
- &fctx->nameservers);
+ &fctx->delegset);
if (result != ISC_R_SUCCESS) {
goto cleanup_nameservers;
}
dns_name_copy(fctx->fwdname, fctx->domain);
dns_name_copy(dcname, fctx->qmin.dcname);
- fctx->ns_ttl = fctx->nameservers.ttl;
+ fctx->ns_ttl = fctx->delegset->expires - fctx->now;
fctx->ns_ttl_ok = true;
}
} else {
- dns_rdataset_clone(nameservers, &fctx->nameservers);
+ dns_delegset_attach(delegset, &fctx->delegset);
dns_name_copy(domain, fctx->domain);
dns_name_copy(domain, fctx->qmin.dcname);
- fctx->ns_ttl = fctx->nameservers.ttl;
+ fctx->ns_ttl = fctx->delegset->expires - fctx->now;
fctx->ns_ttl_ok = true;
}
fcount_decr(fctx);
cleanup_nameservers:
- dns_rdataset_cleanup(&fctx->nameservers);
+ if (fctx->delegset != NULL) {
+ dns_delegset_detach(&fctx->delegset);
+ }
isc_mem_free(fctx->mctx, fctx->info);
if (fctx->nfails != NULL) {
isc_counter_detach(&fctx->nfails);
isc_loop_t *loop = resp->loop;
isc_result_t result;
dns_resolver_t *res = NULL;
- dns_rdataset_t *frdataset = NULL, *nsrdataset = NULL;
- dns_rdataset_t nameservers;
+ dns_rdataset_t *frdataset = NULL;
+ dns_delegset_t *delegset = NULL;
dns_fixedname_t fixed;
dns_name_t *domain = NULL;
unsigned int n;
}
/* Preserve data from resp before freeing it. */
- frdataset = resp->rdataset; /* a.k.a. fctx->nsrrset */
+ frdataset = resp->rdataset;
result = resp->result;
-
dns_resolver_freefresp(&resp);
LOCK(&fctx->lock);
case ISC_R_SUCCESS:
FCTXTRACE("resuming DS lookup");
- dns_rdataset_cleanup(&fctx->nameservers);
- dns_rdataset_clone(frdataset, &fctx->nameservers);
-
- /*
- * Disassociate now the NS's are saved.
- */
+ dns_delegset_fromnsrdataset(frdataset, &delegset);
dns_rdataset_cleanup(frdataset);
- fctx->ns_ttl = fctx->nameservers.ttl;
+ if (delegset == NULL) {
+ result = DNS_R_SERVFAIL;
+ break;
+ }
+
+ if (fctx->delegset != NULL) {
+ dns_delegset_detach(&fctx->delegset);
+ }
+
+ dns_delegset_attach(delegset, &fctx->delegset);
+
+ fctx->ns_ttl = fctx->delegset->expires - fctx->now;
fctx->ns_ttl_ok = true;
log_ns_ttl(fctx, "resume_dslookup");
case ISC_R_SHUTTINGDOWN:
case ISC_R_CANCELED:
- /* Don't try anymore. */
- /* Can't be done in cleanup. */
- dns_rdataset_cleanup(frdataset);
goto cleanup;
default:
}
/* Get nameservers from fetch before we destroy it. */
- dns_rdataset_init(&nameservers);
- if (dns_rdataset_isassociated(&fetch->private->nameservers)) {
- dns_rdataset_clone(&fetch->private->nameservers,
- &nameservers);
- nsrdataset = &nameservers;
+ if (fetch->private->delegset != NULL) {
+ dns_delegset_attach(fetch->private->delegset,
+ &delegset);
/* Get domain from fetch before we destroy it. */
domain = dns_fixedname_initname(&fixed);
fetchctx_ref(fctx);
result = dns_resolver_createfetch(
- res, fctx->nsname, dns_rdatatype_ns, domain, nsrdataset,
+ res, fctx->nsname, dns_rdatatype_ns, domain, delegset,
NULL, NULL, 0, fctx->options, 0, fctx->qc, fctx->gqc,
fctx, loop, resume_dslookup, fctx, &fctx->edectx,
&fctx->nsrrset, NULL, &fctx->nsfetch);
result = DNS_R_SERVFAIL;
}
}
-
- dns_rdataset_cleanup(&nameservers);
}
cleanup:
+ if (delegset != NULL) {
+ dns_delegset_detach(&delegset);
+ }
dns_resolver_destroyfetch(&fetch);
if (result != ISC_R_SUCCESS) {
INSIST(dns_name_countlabels(fctx->domain) > 0);
fcount_decr(fctx);
- dns_rdataset_cleanup(&fctx->nameservers);
+ dns_delegset_detach(&fctx->delegset);
dns_name_copy(rctx->ns_name, fctx->domain);
}
result = dns_view_bestzonecut(fctx->res->view, name, fname,
dcname, fctx->now, findoptions,
- true, true, &fctx->nameservers);
+ true, true, &fctx->delegset);
if (result != ISC_R_SUCCESS) {
FCTXTRACE("couldn't find a zonecut");
fctx_failure_detach(&rctx->fctx, DNS_R_SERVFAIL);
fctx_failure_detach(&rctx->fctx, DNS_R_SERVFAIL);
return;
}
- fctx->ns_ttl = fctx->nameservers.ttl;
+ fctx->ns_ttl = fctx->delegset->expires - fctx->now;
fctx->ns_ttl_ok = true;
fctx_cancelqueries(fctx, true, false);
fctx_cleanup(fctx);
static isc_result_t
get_attached_fctx(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
dns_rdatatype_t type, const dns_name_t *domain,
- dns_rdataset_t *nameservers, const isc_sockaddr_t *client,
+ dns_delegset_t *delegset, const isc_sockaddr_t *client,
unsigned int options, unsigned int depth, isc_counter_t *qc,
isc_counter_t *gqc, fetchctx_t *parent, fetchctx_t **fctxp,
bool *new_fctx) {
if (fctx == NULL) {
create:
- result = fctx_create(res, loop, name, type, domain, nameservers,
+ result = fctx_create(res, loop, name, type, domain, delegset,
client, options, depth, qc, gqc, parent,
&fctx);
if (result != ISC_R_SUCCESS) {
isc_result_t
dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name,
dns_rdatatype_t type, const dns_name_t *domain,
- dns_rdataset_t *nameservers,
- dns_forwarders_t *forwarders,
+ dns_delegset_t *delegset, dns_forwarders_t *forwarders,
const isc_sockaddr_t *client, dns_messageid_t id,
unsigned int options, unsigned int depth,
isc_counter_t *qc, isc_counter_t *gqc,
REQUIRE(res->frozen);
/* XXXRTH Check for meta type */
if (domain != NULL) {
- REQUIRE(DNS_RDATASET_VALID(nameservers));
- REQUIRE(nameservers->type == dns_rdatatype_ns);
+ REQUIRE(DNS_DELEGSET_VALID(delegset));
} else {
- REQUIRE(nameservers == NULL);
+ REQUIRE(delegset == NULL);
}
REQUIRE(forwarders == NULL);
REQUIRE(!dns_rdataset_isassociated(rdataset));
UNLOCK(&res->lock);
result = get_attached_fctx(res, loop, name, type, domain,
- nameservers, client, options, depth,
- qc, gqc, parent, &fctx, &new_fctx);
+ delegset, client, options, depth, qc,
+ gqc, parent, &fctx, &new_fctx);
if (result != ISC_R_SUCCESS) {
goto fail;
}
}
}
} else {
- result = fctx_create(res, loop, name, type, domain, nameservers,
+ result = fctx_create(res, loop, name, type, domain, delegset,
client, options, depth, qc, gqc, parent,
&fctx);
if (result != ISC_R_SUCCESS) {
}
static isc_result_t
-findzonecut_zone(dns_view_t *view, const dns_name_t *name, dns_name_t *fname,
+bestzonecut_zone(dns_view_t *view, const dns_name_t *name, dns_name_t *fname,
dns_name_t *dcname, isc_stdtime_t now, unsigned int options,
dns_rdataset_t *rdataset) {
dns_db_t *db = NULL;
}
static isc_result_t
-findzonecut_cache(dns_view_t *view, const dns_name_t *name, dns_name_t *fname,
- dns_name_t *dcname, isc_stdtime_t now, unsigned int options,
- dns_rdataset_t *rdataset) {
+bestzonecut_delegdb(dns_view_t *view, const dns_name_t *name, dns_name_t *fname,
+ dns_name_t *dcname, isc_stdtime_t now, unsigned int options,
+ dns_delegset_t **delegsetp) {
isc_result_t result = DNS_R_NXDOMAIN;
- if (view->cachedb != NULL) {
- result = dns_db_findzonecut(view->cachedb, name, options, now,
- NULL, fname, dcname, rdataset,
- NULL);
+ if (view->deleg != NULL) {
+ result = dns_delegdb_lookup(view->deleg, name, now, options,
+ fname, dcname, delegsetp);
}
/*
* keep DNS_R_NXDOMAIN, so the hints can be checked.
*/
if (result != ISC_R_SUCCESS) {
- dns_rdataset_cleanup(rdataset);
result = DNS_R_NXDOMAIN;
}
-
return result;
}
static void
-findzonecut_zoneorcache(dns_view_t *view, const dns_name_t *name,
+bestzonecut_zoneorcache(dns_view_t *view, const dns_name_t *name,
dns_name_t *fname, dns_name_t *dcname,
isc_stdtime_t now, unsigned int options,
- dns_rdataset_t *rdataset) {
+ dns_rdataset_t *rdataset, dns_delegset_t **delegsetp) {
isc_result_t result;
- dns_rdataset_t crdataset = DNS_RDATASET_INIT;
dns_fixedname_t f, dc;
dns_name_t *cfname = dns_fixedname_initname(&f);
dns_name_t *cdcname = dns_fixedname_initname(&dc);
- CHECK(findzonecut_cache(view, name, cfname, cdcname, now, options,
- &crdataset));
+ result = bestzonecut_delegdb(view, name, cfname, cdcname, now, options,
+ delegsetp);
+ if (result != ISC_R_SUCCESS) {
+ return;
+ }
bool cacheclosest = dns_name_issubdomain(cfname, fname);
bool staticstub = rdataset->attributes.staticstub &&
if (cacheclosest && !staticstub) {
dns_rdataset_cleanup(rdataset);
- dns_rdataset_clone(&crdataset, rdataset);
dns_name_copy(cfname, fname);
if (dcname != NULL) {
dns_name_copy(cdcname, dcname);
}
+ } else {
+ dns_delegset_detach(delegsetp);
}
-
-cleanup:
- dns_rdataset_cleanup(&crdataset);
}
static isc_result_t
-findzonecut_hints(dns_view_t *view, dns_name_t *fname, dns_name_t *dcname,
+bestzonecut_hints(dns_view_t *view, dns_name_t *fname, dns_name_t *dcname,
isc_stdtime_t now, dns_rdataset_t *rdataset) {
isc_result_t result = ISC_R_NOTFOUND;
dns_view_bestzonecut(dns_view_t *view, const dns_name_t *name,
dns_name_t *fname, dns_name_t *dcname, isc_stdtime_t now,
unsigned int options, bool usehints, bool usecache,
- dns_rdataset_t *rdataset) {
+ dns_delegset_t **delegsetp) {
isc_result_t result;
+ dns_rdataset_t rdatasetdata = DNS_RDATASET_INIT;
+ dns_rdataset_t *rdataset = NULL;
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(view->frozen);
- result = findzonecut_zone(view, name, fname, dcname, now, options,
+ if (delegsetp != NULL) {
+ REQUIRE(*delegsetp == NULL);
+ rdataset = &rdatasetdata;
+ }
+
+ result = bestzonecut_zone(view, name, fname, dcname, now, options,
rdataset);
if (result == DNS_R_NXDOMAIN && usecache) {
* No local zone matches `name`, but the cache might have a
* delegation.
*/
- result = findzonecut_cache(view, name, fname, dcname, now,
- options, rdataset);
+ result = bestzonecut_delegdb(view, name, fname, dcname, now,
+ options, delegsetp);
} else if (result == ISC_R_SUCCESS && usecache) {
/*
* A zone with a (possibly partial) delegation match but the
* cache can have a more precise delegation.
*/
- findzonecut_zoneorcache(view, name, fname, dcname, now, options,
- rdataset);
+ bestzonecut_zoneorcache(view, name, fname, dcname, now, options,
+ rdataset, delegsetp);
}
/*
* No local zone nor cache match. Last attempt with the hints.
*/
if (result == DNS_R_NXDOMAIN && usehints) {
- result = findzonecut_hints(view, fname, dcname, now, rdataset);
+ result = bestzonecut_hints(view, fname, dcname, now, rdataset);
}
if (result != ISC_R_SUCCESS) {
result = DNS_R_NXDOMAIN;
- dns_rdataset_cleanup(rdataset);
+ } else {
+ dns_delegset_fromrdataset(rdataset, delegsetp);
}
+ dns_rdataset_cleanup(rdataset);
return result;
}