diff --git a/bin/named/server.c b/bin/named/server.c index 085d0baea2..38fe7ef642 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -7037,7 +7037,7 @@ tat_send(void *arg) { if (result == ISC_R_SUCCESS) { result = dns_resolver_createfetch( tat->view->resolver, tatname, dns_rdatatype_null, - domain, &nameservers, NULL, NULL, 0, 0, 0, NULL, + domain, &nameservers, NULL, NULL, 0, 0, 0, NULL, NULL, tat->loop, tat_done, tat, &tat->rdataset, &tat->sigrdataset, &tat->fetch); } diff --git a/lib/dns/adb.c b/lib/dns/adb.c index 13e6bca9b8..23017a759a 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -333,7 +333,7 @@ static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t, dns_rdatatype_t); static isc_result_t fetch_name(dns_adbname_t *, bool, unsigned int, isc_counter_t *qc, - dns_rdatatype_t); + isc_counter_t *gqc, dns_rdatatype_t); static void destroy(dns_adb_t *); static void @@ -1923,7 +1923,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_loop_t *loop, isc_job_cb cb, void *cbarg, const dns_name_t *name, const dns_name_t *qname, dns_rdatatype_t qtype ISC_ATTR_UNUSED, unsigned int options, isc_stdtime_t now, dns_name_t *target, in_port_t port, - unsigned int depth, isc_counter_t *qc, + unsigned int depth, isc_counter_t *qc, isc_counter_t *gqc, dns_adbfind_t **findp) { isc_result_t result = ISC_R_UNEXPECTED; dns_adbfind_t *find = NULL; @@ -2133,7 +2133,7 @@ fetch: * Start V4. */ if (WANT_INET(wanted_fetches) && - fetch_name(adbname, start_at_zone, depth, qc, + fetch_name(adbname, start_at_zone, depth, qc, gqc, dns_rdatatype_a) == ISC_R_SUCCESS) { DP(DEF_LEVEL, @@ -2146,7 +2146,7 @@ fetch: * Start V6. */ if (WANT_INET6(wanted_fetches) && - fetch_name(adbname, start_at_zone, depth, qc, + fetch_name(adbname, start_at_zone, depth, qc, gqc, dns_rdatatype_aaaa) == ISC_R_SUCCESS) { DP(DEF_LEVEL, @@ -2952,7 +2952,7 @@ out: static isc_result_t fetch_name(dns_adbname_t *adbname, bool start_at_zone, unsigned int depth, - isc_counter_t *qc, dns_rdatatype_t type) { + isc_counter_t *qc, isc_counter_t *gqc, dns_rdatatype_t type) { isc_result_t result; dns_adbfetch_t *fetch = NULL; dns_adb_t *adb = NULL; @@ -3008,7 +3008,7 @@ fetch_name(dns_adbname_t *adbname, bool start_at_zone, unsigned int depth, */ result = dns_resolver_createfetch( adb->res, adbname->name, type, name, nameservers, NULL, NULL, 0, - options, depth, qc, isc_loop(), fetch_callback, adbname, + options, depth, qc, gqc, isc_loop(), fetch_callback, adbname, &fetch->rdataset, NULL, &fetch->fetch); if (result != ISC_R_SUCCESS) { DP(ENTER_LEVEL, "fetch_name: createfetch failed with %s", diff --git a/lib/dns/client.c b/lib/dns/client.c index 96043e0266..26c7acf8d4 100644 --- a/lib/dns/client.c +++ b/lib/dns/client.c @@ -456,7 +456,7 @@ start_fetch(resctx_t *rctx) { result = dns_resolver_createfetch( rctx->view->resolver, dns_fixedname_name(&rctx->name), - rctx->type, NULL, NULL, NULL, NULL, 0, fopts, 0, NULL, + rctx->type, NULL, NULL, NULL, NULL, 0, fopts, 0, NULL, NULL, rctx->client->loop, fetch_done, rctx, rctx->rdataset, rctx->sigrdataset, &rctx->fetch); diff --git a/lib/dns/include/dns/adb.h b/lib/dns/include/dns/adb.h index 7288cdd527..585f0f6c9b 100644 --- a/lib/dns/include/dns/adb.h +++ b/lib/dns/include/dns/adb.h @@ -281,7 +281,8 @@ dns_adb_createfind(dns_adb_t *adb, isc_loop_t *loop, isc_job_cb cb, void *cbarg, const dns_name_t *name, const dns_name_t *qname, dns_rdatatype_t qtype, unsigned int options, isc_stdtime_t now, dns_name_t *target, in_port_t port, - unsigned int depth, isc_counter_t *qc, dns_adbfind_t **find); + unsigned int depth, isc_counter_t *qc, isc_counter_t *gqc, + dns_adbfind_t **find); /*%< * Main interface for clients. The adb will look up the name given in * "name" and will build up a list of found addresses, and perhaps start diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h index b65e2aa78c..579bce623a 100644 --- a/lib/dns/include/dns/resolver.h +++ b/lib/dns/include/dns/resolver.h @@ -272,9 +272,10 @@ dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name, dns_forwarders_t *forwarders, const isc_sockaddr_t *client, dns_messageid_t id, unsigned int options, unsigned int depth, - isc_counter_t *qc, isc_loop_t *loop, isc_job_cb cb, - void *arg, dns_rdataset_t *rdataset, - dns_rdataset_t *sigrdataset, dns_fetch_t **fetchp); + isc_counter_t *qc, isc_counter_t *gqc, + isc_loop_t *loop, isc_job_cb cb, void *arg, + dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp); /*%< * Recurse to answer a question. * diff --git a/lib/dns/include/dns/validator.h b/lib/dns/include/dns/validator.h index 249687d756..09dc3a13a3 100644 --- a/lib/dns/include/dns/validator.h +++ b/lib/dns/include/dns/validator.h @@ -154,6 +154,7 @@ struct dns_validator { uint32_t *nvalidations; uint32_t *nfails; isc_counter_t *qc; + isc_counter_t *gqc; }; /*% @@ -172,7 +173,8 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, dns_message_t *message, unsigned int options, isc_loop_t *loop, isc_job_cb cb, void *arg, uint32_t *nvalidations, uint32_t *nfails, - isc_counter_t *qc, dns_validator_t **validatorp); + isc_counter_t *qc, isc_counter_t *gqc, + dns_validator_t **validatorp); /*%< * Start a DNSSEC validation. * diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index a82d860d98..88c888c7dc 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -1348,5 +1348,4 @@ dns_view_setmaxqueries(dns_view_t *view, uint16_t max_queries); *\li 'max_queries' is greater than 0. */ - ISC_LANG_ENDDECLS diff --git a/lib/dns/nta.c b/lib/dns/nta.c index acd788795f..e428b5c7ef 100644 --- a/lib/dns/nta.c +++ b/lib/dns/nta.c @@ -240,8 +240,9 @@ checkbogus(void *arg) { dns__nta_ref(nta); /* for dns_resolver_createfetch */ result = dns_resolver_createfetch( resolver, &nta->name, dns_rdatatype_nsec, NULL, NULL, NULL, - NULL, 0, DNS_FETCHOPT_NONTA, 0, NULL, nta->loop, fetch_done, - nta, &nta->rdataset, &nta->sigrdataset, &nta->fetch); + NULL, 0, DNS_FETCHOPT_NONTA, 0, NULL, NULL, nta->loop, + fetch_done, nta, &nta->rdataset, &nta->sigrdataset, + &nta->fetch); if (result != ISC_R_SUCCESS) { dns__nta_detach(&nta); /* for dns_resolver_createfetch() */ } diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 5d5b094743..af402c1b95 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -388,6 +388,7 @@ struct fetchctx { bool ns_ttl_ok; uint32_t ns_ttl; isc_counter_t *qc; + isc_counter_t *gqc; bool minimized; unsigned int qmin_labels; isc_result_t qmin_warning; @@ -707,7 +708,7 @@ 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, unsigned int options, unsigned int depth, isc_counter_t *qc, - fetchctx_t **fctxp, bool *new_fctx); + isc_counter_t *gqc, fetchctx_t **fctxp, bool *new_fctx); static void release_fctx(fetchctx_t *fctx); @@ -981,7 +982,7 @@ valcreate(fetchctx_t *fctx, dns_message_t *message, dns_adbaddrinfo_t *addrinfo, result = dns_validator_create( fctx->res->view, name, type, rdataset, sigrdataset, message, valoptions, fctx->loop, validated, valarg, &fctx->nvalidations, - &fctx->nfails, fctx->qc, &validator); + &fctx->nfails, fctx->qc, fctx->gqc, &validator); RUNTIME_CHECK(result == ISC_R_SUCCESS); inc_stats(fctx->res, dns_resstatscounter_val); if ((valoptions & DNS_VALIDATOR_DEFER) == 0) { @@ -3279,7 +3280,7 @@ findname(fetchctx_t *fctx, const dns_name_t *name, in_port_t port, result = dns_adb_createfind(fctx->adb, fctx->loop, fctx_finddone, fctx, name, fctx->name, fctx->type, options, now, NULL, res->view->dstport, fctx->depth + 1, - fctx->qc, &find); + fctx->qc, fctx->gqc, &find); isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), "fctx %p(%s): createfind for %s - %s", @@ -3989,6 +3990,9 @@ fctx_try(fetchctx_t *fctx, bool retrying) { dns_resolver_t *res = NULL; FCTXTRACE5("try", "fctx->qc=", isc_counter_used(fctx->qc)); + if (fctx->gqc != NULL) { + FCTXTRACE5("try", "fctx->gqc=", isc_counter_used(fctx->gqc)); + } REQUIRE(!ADDRWAIT(fctx)); REQUIRE(fctx->tid == isc_tid()); @@ -3996,13 +4000,27 @@ fctx_try(fetchctx_t *fctx, bool retrying) { res = fctx->res; /* We've already exceeded maximum query count */ - if (isc_counter_used(fctx->qc) > res->maxqueries) { + if (isc_counter_used(fctx->qc) > isc_counter_getlimit(fctx->qc)) { + isc_log_write( + DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER, + ISC_LOG_DEBUG(3), + "exceeded max queries resolving '%s' " + "(max-recursion-queries, querycount=%u, maxqueries=%u)", + fctx->info, isc_counter_used(fctx->qc), + isc_counter_getlimit(fctx->qc)); + result = DNS_R_SERVFAIL; + goto done; + } + + if (fctx->gqc != NULL && + isc_counter_used(fctx->gqc) > isc_counter_getlimit(fctx->gqc)) + { isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), - "exceeded max queries resolving '%s' " - "(querycount=%u, maxqueries=%u)", - fctx->info, isc_counter_used(fctx->qc), - res->maxqueries); + "exceeded global max queries resolving '%s' " + "(max-query-count, querycount=%u, maxqueries=%u)", + fctx->info, isc_counter_used(fctx->gqc), + isc_counter_getlimit(fctx->gqc)); result = DNS_R_SERVFAIL; goto done; } @@ -4100,8 +4118,8 @@ fctx_try(fetchctx_t *fctx, bool retrying) { result = dns_resolver_createfetch( fctx->res, fctx->qminname, fctx->qmintype, fctx->domain, &fctx->nameservers, NULL, NULL, 0, options, 0, fctx->qc, - fctx->loop, resume_qmin, fctx, &fctx->qminrrset, NULL, - &fctx->qminfetch); + fctx->gqc, fctx->loop, resume_qmin, fctx, + &fctx->qminrrset, NULL, &fctx->qminfetch); if (result != ISC_R_SUCCESS) { fetchctx_unref(fctx); goto done; @@ -4113,11 +4131,24 @@ fctx_try(fetchctx_t *fctx, bool retrying) { if (result != ISC_R_SUCCESS) { isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), - "exceeded max queries resolving '%s'", - fctx->info); + "exceeded max queries resolving '%s' " + "(max-recursion-queries, querycount=%u)", + fctx->info, isc_counter_used(fctx->qc)); goto done; } + if (fctx->gqc != NULL) { + result = isc_counter_increment(fctx->gqc); + if (result != ISC_R_SUCCESS) { + isc_log_write(DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), + "exceeded global max queries resolving " + "'%s' (max-query-count, querycount=%u)", + fctx->info, isc_counter_used(fctx->gqc)); + goto done; + } + } + result = fctx_query(fctx, addrinfo, fctx->options); if (result != ISC_R_SUCCESS) { goto done; @@ -4349,6 +4380,9 @@ fctx_destroy(fetchctx_t *fctx) { } isc_counter_detach(&fctx->qc); + if (fctx->gqc != NULL) { + isc_counter_detach(&fctx->gqc); + } fcount_decr(fctx); dns_message_detach(&fctx->qmessage); if (dns_rdataset_isassociated(&fctx->nameservers)) { @@ -4506,7 +4540,7 @@ 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, unsigned int options, unsigned int depth, isc_counter_t *qc, - fetchctx_t **fctxp) { + isc_counter_t *gqc, fetchctx_t **fctxp) { fetchctx_t *fctx = NULL; isc_result_t result; isc_result_t iresult; @@ -4574,6 +4608,15 @@ fctx_create(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name, fctx->info, fctx->qc); } + if (gqc != NULL) { + isc_counter_attach(gqc, &fctx->gqc); + isc_log_write(DNS_LOGCATEGORY_RESOLVER, DNS_LOGMODULE_RESOLVER, + ISC_LOG_DEBUG(9), + "fctx %p(%s): attached to counter %p (%d)", fctx, + fctx->info, fctx->gqc, + isc_counter_used(fctx->gqc)); + } + #if DNS_RESOLVER_TRACE fprintf(stderr, "fetchctx__init:%s:%s:%d:%p:%p->references = 1\n", __func__, __FILE__, __LINE__, fctx, fctx); @@ -4783,6 +4826,9 @@ cleanup_nameservers: } isc_mem_free(fctx->mctx, fctx->info); isc_counter_detach(&fctx->qc); + if (fctx->gqc != NULL) { + isc_counter_detach(&fctx->gqc); + } cleanup_fetch: dns_resolver_detach(&fctx->res); @@ -7147,8 +7193,8 @@ resume_dslookup(void *arg) { fetchctx_ref(fctx); result = dns_resolver_createfetch( res, fctx->nsname, dns_rdatatype_ns, domain, nsrdataset, - NULL, NULL, 0, fctx->options, 0, fctx->qc, loop, - resume_dslookup, fctx, &fctx->nsrrset, NULL, + NULL, NULL, 0, fctx->options, 0, fctx->qc, fctx->gqc, + loop, resume_dslookup, fctx, &fctx->nsrrset, NULL, &fctx->nsfetch); if (result != ISC_R_SUCCESS) { fetchctx_unref(fctx); @@ -9571,7 +9617,7 @@ rctx_chaseds(respctx_t *rctx, dns_message_t *message, fetchctx_ref(fctx); result = dns_resolver_createfetch( fctx->res, fctx->nsname, dns_rdatatype_ns, NULL, NULL, NULL, - NULL, 0, fctx->options, 0, fctx->qc, fctx->loop, + NULL, 0, fctx->options, 0, fctx->qc, fctx->gqc, fctx->loop, resume_dslookup, fctx, &fctx->nsrrset, NULL, &fctx->nsfetch); if (result != ISC_R_SUCCESS) { if (result == DNS_R_DUPLICATE) { @@ -10145,8 +10191,9 @@ dns_resolver_prime(dns_resolver_t *res) { LOCK(&res->primelock); result = dns_resolver_createfetch( res, dns_rootname, dns_rdatatype_ns, NULL, NULL, NULL, - NULL, 0, DNS_FETCHOPT_NOFORWARD, 0, NULL, isc_loop(), - prime_done, res, rdataset, NULL, &res->primefetch); + NULL, 0, DNS_FETCHOPT_NOFORWARD, 0, NULL, NULL, + isc_loop(), prime_done, res, rdataset, NULL, + &res->primefetch); UNLOCK(&res->primelock); if (result != ISC_R_SUCCESS) { @@ -10344,7 +10391,7 @@ 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, unsigned int options, unsigned int depth, isc_counter_t *qc, - fetchctx_t **fctxp, bool *new_fctx) { + isc_counter_t *gqc, fetchctx_t **fctxp, bool *new_fctx) { isc_result_t result; fetchctx_t key = { .name = UNCONST(name), @@ -10364,7 +10411,7 @@ again: break; case ISC_R_NOTFOUND: result = fctx_create(res, loop, name, type, domain, nameservers, - client, options, depth, qc, &fctx); + client, options, depth, qc, gqc, &fctx); if (result != ISC_R_SUCCESS) { goto unlock; } @@ -10419,9 +10466,10 @@ dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name, dns_forwarders_t *forwarders, const isc_sockaddr_t *client, dns_messageid_t id, unsigned int options, unsigned int depth, - isc_counter_t *qc, isc_loop_t *loop, isc_job_cb cb, - void *arg, dns_rdataset_t *rdataset, - dns_rdataset_t *sigrdataset, dns_fetch_t **fetchp) { + isc_counter_t *qc, isc_counter_t *gqc, + isc_loop_t *loop, isc_job_cb cb, void *arg, + dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp) { dns_fetch_t *fetch = NULL; fetchctx_t *fctx = NULL; isc_result_t result = ISC_R_SUCCESS; @@ -10472,7 +10520,7 @@ dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name, result = get_attached_fctx(res, loop, name, type, domain, nameservers, client, options, depth, - qc, &fctx, &new_fctx); + qc, gqc, &fctx, &new_fctx); if (result != ISC_R_SUCCESS) { goto fail; } @@ -10508,7 +10556,7 @@ dns_resolver_createfetch(dns_resolver_t *res, const dns_name_t *name, } } else { result = fctx_create(res, loop, name, type, domain, nameservers, - client, options, depth, qc, &fctx); + client, options, depth, qc, gqc, &fctx); if (result != ISC_R_SUCCESS) { goto unlock; } diff --git a/lib/dns/validator.c b/lib/dns/validator.c index a210c773a9..92ab963ffe 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -939,7 +939,7 @@ create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, dns_validator_ref(val); result = dns_resolver_createfetch( val->view->resolver, name, type, NULL, NULL, NULL, NULL, 0, - fopts, 0, NULL, val->loop, callback, val, &val->frdataset, + fopts, 0, NULL, NULL, val->loop, callback, val, &val->frdataset, &val->fsigrdataset, &val->fetch); if (result != ISC_R_SUCCESS) { dns_validator_detach(&val); @@ -977,7 +977,7 @@ create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, result = dns_validator_create(val->view, name, type, rdataset, sig, NULL, vopts, val->loop, cb, val, val->nvalidations, val->nfails, val->qc, - &val->subvalidator); + val->gqc, &val->subvalidator); if (result == ISC_R_SUCCESS) { dns_validator_attach(val, &val->subvalidator->parent); val->subvalidator->depth = val->depth + 1; @@ -3393,7 +3393,8 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, dns_message_t *message, unsigned int options, isc_loop_t *loop, isc_job_cb cb, void *arg, uint32_t *nvalidations, uint32_t *nfails, - isc_counter_t *qc, dns_validator_t **validatorp) { + isc_counter_t *qc, isc_counter_t *gqc, + dns_validator_t **validatorp) { isc_result_t result = ISC_R_FAILURE; dns_validator_t *val = NULL; dns_keytable_t *kt = NULL; @@ -3436,6 +3437,9 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, if (qc != NULL) { isc_counter_attach(qc, &val->qc); } + if (gqc != NULL) { + isc_counter_attach(gqc, &val->gqc); + } val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name); dns_rdataset_init(&val->fdsset); @@ -3526,6 +3530,9 @@ destroy_validator(dns_validator_t *val) { if (val->qc != NULL) { isc_counter_detach(&val->qc); } + if (val->gqc != NULL) { + isc_counter_detach(&val->gqc); + } dns_view_detach(&val->view); isc_loop_detach(&val->loop); isc_mem_put(mctx, val, sizeof(*val)); diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 01c670aa16..c1f639f941 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -10943,7 +10943,7 @@ do_keyfetch(void *arg) { */ result = dns_resolver_createfetch( resolver, kname, dns_rdatatype_dnskey, NULL, NULL, NULL, NULL, - 0, options, 0, NULL, zone->loop, keyfetch_done, kfetch, + 0, options, 0, NULL, NULL, zone->loop, keyfetch_done, kfetch, &kfetch->dnskeyset, &kfetch->dnskeysigset, &kfetch->fetch); dns_resolver_detach(&resolver); @@ -12461,7 +12461,7 @@ notify_find_address(dns_notify_t *notify) { result = dns_adb_createfind( adb, notify->zone->loop, process_notify_adb_event, notify, ¬ify->ns, dns_rootname, 0, options, 0, NULL, - notify->zone->view->dstport, 0, NULL, ¬ify->find); + notify->zone->view->dstport, 0, NULL, NULL, ¬ify->find); dns_adb_detach(&adb); /* Something failed? */ @@ -21228,7 +21228,7 @@ checkds_find_address(dns_checkds_t *checkds) { result = dns_adb_createfind( adb, checkds->zone->loop, process_checkds_adb_event, checkds, &checkds->ns, dns_rootname, 0, options, 0, NULL, - checkds->zone->view->dstport, 0, NULL, &checkds->find); + checkds->zone->view->dstport, 0, NULL, NULL, &checkds->find); dns_adb_detach(&adb); /* Something failed? */ @@ -21813,8 +21813,9 @@ do_nsfetch(void *arg) { */ result = dns_resolver_createfetch( resolver, &nsfetch->pname, dns_rdatatype_ns, NULL, NULL, NULL, - NULL, 0, options, 0, NULL, zone->loop, nsfetch_done, nsfetch, - &nsfetch->nsrrset, &nsfetch->nssigset, &nsfetch->fetch); + NULL, 0, options, 0, NULL, NULL, zone->loop, nsfetch_done, + nsfetch, &nsfetch->nsrrset, &nsfetch->nssigset, + &nsfetch->fetch); dns_resolver_detach(&resolver); diff --git a/lib/isc/counter.c b/lib/isc/counter.c index 5cfac452f7..0c70c78d1a 100644 --- a/lib/isc/counter.c +++ b/lib/isc/counter.c @@ -80,7 +80,7 @@ isc_counter_setlimit(isc_counter_t *counter, int limit) { atomic_store(&counter->limit, limit); } -int +unsigned int isc_counter_getlimit(isc_counter_t *counter) { REQUIRE(VALID_COUNTER(counter)); diff --git a/lib/isc/include/isc/counter.h b/lib/isc/include/isc/counter.h index 30ae273ae0..385b08cd4f 100644 --- a/lib/isc/include/isc/counter.h +++ b/lib/isc/include/isc/counter.h @@ -68,7 +68,7 @@ isc_counter_setlimit(isc_counter_t *counter, int limit); * Set the counter limit. */ -int +unsigned int isc_counter_getlimit(isc_counter_t *counter); /*%< * Get the counter limit. diff --git a/lib/ns/include/ns/query.h b/lib/ns/include/ns/query.h index 572e5ad94e..b340c59e3a 100644 --- a/lib/ns/include/ns/query.h +++ b/lib/ns/include/ns/query.h @@ -105,6 +105,7 @@ typedef struct ns_query_recparam { struct ns_query { unsigned int attributes; unsigned int restarts; + isc_counter_t *qc; bool timerset; dns_name_t *qname; dns_name_t *origqname; diff --git a/lib/ns/query.c b/lib/ns/query.c index b7f6e53b37..36441dab57 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -861,6 +862,9 @@ query_reset(ns_client_t *client, bool everything) { client->query.rpz_st = NULL; } } + if (client->query.qc != NULL) { + isc_counter_detach(&client->query.qc); + } client->query.origqname = NULL; client->query.dboptions = 0; client->query.fetchoptions = 0; @@ -2799,7 +2803,8 @@ fetch_and_forget(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t qtype, result = dns_resolver_createfetch( client->view->resolver, qname, qtype, NULL, NULL, NULL, peeraddr, client->message->id, options, 0, NULL, - client->manager->loop, cb, client, tmprdataset, NULL, fetchp); + client->query.qc, client->manager->loop, cb, client, + tmprdataset, NULL, fetchp); if (result != ISC_R_SUCCESS) { ns_client_putrdataset(client, &tmprdataset); isc_nmhandle_detach(handlep); @@ -6394,8 +6399,9 @@ ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, result = dns_resolver_createfetch( client->view->resolver, qname, qtype, qdomain, nameservers, NULL, peeraddr, client->message->id, client->query.fetchoptions, - 0, NULL, client->manager->loop, fetch_callback, client, - rdataset, sigrdataset, &FETCH_RECTYPE_NORMAL(client)); + 0, NULL, client->query.qc, client->manager->loop, + fetch_callback, client, rdataset, sigrdataset, + &FETCH_RECTYPE_NORMAL(client)); if (result != ISC_R_SUCCESS) { release_recursionquota(client); @@ -12058,5 +12064,16 @@ ns_query_start(ns_client_t *client, isc_nmhandle_t *handle) { message->flags |= DNS_MESSAGEFLAG_AD; } + /* + * Start global outgoing query count. + */ + result = isc_counter_create(client->manager->mctx, + client->view->max_queries, + &client->query.qc); + if (result != ISC_R_SUCCESS) { + query_next(client, result); + return; + } + query_setup(client, qtype); }