diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c index d49beb2ec99..df5a358e5fa 100644 --- a/lib/dns/dst_api.c +++ b/lib/dns/dst_api.c @@ -164,7 +164,8 @@ computeid(dst_key_t *key); static isc_result_t frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags, unsigned int protocol, dns_rdataclass_t rdclass, - isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp); + isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata, + dst_key_t **keyp); static isc_result_t algorithm_status(unsigned int alg); @@ -780,6 +781,13 @@ dst_key_todns(const dst_key_t *key, isc_buffer_t *target) { isc_result_t dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass, isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) { + return (dst_key_fromdns_ex(name, rdclass, source, mctx, false, keyp)); +} + +isc_result_t +dst_key_fromdns_ex(const dns_name_t *name, dns_rdataclass_t rdclass, + isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata, + dst_key_t **keyp) { uint8_t alg, proto; uint32_t flags, extflags; dst_key_t *key = NULL; @@ -810,7 +818,7 @@ dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass, } result = frombuffer(name, alg, flags, proto, rdclass, source, mctx, - &key); + no_rdata, &key); if (result != ISC_R_SUCCESS) { return (result); } @@ -831,7 +839,7 @@ dst_key_frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags, REQUIRE(dst_initialized); result = frombuffer(name, alg, flags, protocol, rdclass, source, mctx, - &key); + false, &key); if (result != ISC_R_SUCCESS) { return (result); } @@ -2337,7 +2345,8 @@ computeid(dst_key_t *key) { static isc_result_t frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags, unsigned int protocol, dns_rdataclass_t rdclass, - isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) { + isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata, + dst_key_t **keyp) { dst_key_t *key; isc_result_t ret; @@ -2362,10 +2371,12 @@ frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags, return (DST_R_UNSUPPORTEDALG); } - ret = key->func->fromdns(key, source); - if (ret != ISC_R_SUCCESS) { - dst_key_free(&key); - return (ret); + if (!no_rdata) { + ret = key->func->fromdns(key, source); + if (ret != ISC_R_SUCCESS) { + dst_key_free(&key); + return (ret); + } } } diff --git a/lib/dns/include/dns/validator.h b/lib/dns/include/dns/validator.h index b435cd67fba..c5d7a31a419 100644 --- a/lib/dns/include/dns/validator.h +++ b/lib/dns/include/dns/validator.h @@ -149,6 +149,7 @@ struct dns_validator { unsigned int depth; unsigned int authcount; unsigned int authfail; + bool failed; isc_stdtime_t start; }; diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h index 3185e9f91b8..3e3cfe6a68c 100644 --- a/lib/dns/include/dst/dst.h +++ b/lib/dns/include/dst/dst.h @@ -471,6 +471,10 @@ dst_key_tofile(const dst_key_t *key, int type, const char *directory); */ isc_result_t +dst_key_fromdns_ex(const dns_name_t *name, dns_rdataclass_t rdclass, + isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata, + dst_key_t **keyp); +isc_result_t dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass, isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp); /*%< diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index a97aaa85e92..09526246899 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -10634,8 +10634,8 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, * Since we have a pool of tasks we bind them to task queues * to spread the load evenly */ - result = isc_task_create_bound(taskmgr, 0, - &res->buckets[i].task, i); + result = isc_task_create_bound( + taskmgr, 0, &res->buckets[i].task, ISC_NM_TASK_SLOW(i)); if (result != ISC_R_SUCCESS) { isc_mutex_destroy(&res->buckets[i].lock); goto cleanup_buckets; diff --git a/lib/dns/validator.c b/lib/dns/validator.c index 6cf717f8702..243b19f64e2 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -1104,8 +1104,8 @@ create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, * 'rdataset'. If found, build a dst_key_t for it and point val->key at * it. * - * If val->key is already non-NULL, locate it in the rdataset and then - * search past it for the *next* key that could have signed 'siginfo', then + * If val->key is already non-NULL, start searching from the next position in + * 'rdataset' to find the *next* key that could have signed 'siginfo', then * set val->key to that. * * Returns ISC_R_SUCCESS if a possible matching key has been found, @@ -1118,59 +1118,59 @@ select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) { isc_buffer_t b; dns_rdata_t rdata = DNS_RDATA_INIT; dst_key_t *oldkey = val->key; - bool foundold; + bool no_rdata = false; if (oldkey == NULL) { - foundold = true; + result = dns_rdataset_first(rdataset); } else { - foundold = false; + dst_key_free(&oldkey); val->key = NULL; + result = dns_rdataset_next(rdataset); } - - result = dns_rdataset_first(rdataset); if (result != ISC_R_SUCCESS) { - goto failure; + goto done; } + do { dns_rdataset_current(rdataset, &rdata); isc_buffer_init(&b, rdata.data, rdata.length); isc_buffer_add(&b, rdata.length); INSIST(val->key == NULL); - result = dst_key_fromdns(&siginfo->signer, rdata.rdclass, &b, - val->view->mctx, &val->key); + result = dst_key_fromdns_ex(&siginfo->signer, rdata.rdclass, &b, + val->view->mctx, no_rdata, + &val->key); if (result == ISC_R_SUCCESS) { if (siginfo->algorithm == (dns_secalg_t)dst_key_alg(val->key) && siginfo->keyid == (dns_keytag_t)dst_key_id(val->key) && + (dst_key_flags(val->key) & DNS_KEYFLAG_REVOKE) == + 0 && dst_key_iszonekey(val->key)) { - if (foundold) { - /* - * This is the key we're looking for. - */ - return (ISC_R_SUCCESS); - } else if (dst_key_compare(oldkey, val->key)) { - foundold = true; - dst_key_free(&oldkey); + if (no_rdata) { + /* Retry with full key */ + dns_rdata_reset(&rdata); + dst_key_free(&val->key); + no_rdata = false; + continue; } + /* This is the key we're looking for. */ + goto done; } dst_key_free(&val->key); } dns_rdata_reset(&rdata); result = dns_rdataset_next(rdataset); + no_rdata = true; } while (result == ISC_R_SUCCESS); +done: if (result == ISC_R_NOMORE) { result = ISC_R_NOTFOUND; } -failure: - if (oldkey != NULL) { - dst_key_free(&oldkey); - } - return (result); } @@ -1589,20 +1589,9 @@ validate_answer(dns_validator_t *val, bool resume) { continue; } - do { - isc_result_t tresult; - vresult = verify(val, val->key, &rdata, - val->siginfo->keyid); - if (vresult == ISC_R_SUCCESS) { - break; - } - - tresult = select_signing_key(val, val->keyset); - if (tresult != ISC_R_SUCCESS) { - break; - } - } while (1); + vresult = verify(val, val->key, &rdata, val->siginfo->keyid); if (vresult != ISC_R_SUCCESS) { + val->failed = true; validator_log(val, ISC_LOG_DEBUG(3), "failed to verify rdataset"); } else { @@ -1639,9 +1628,13 @@ validate_answer(dns_validator_t *val, bool resume) { } else { validator_log(val, ISC_LOG_DEBUG(3), "verify failure: %s", - isc_result_totext(result)); + isc_result_totext(vresult)); resume = false; } + if (val->failed) { + result = ISC_R_NOMORE; + break; + } } if (result != ISC_R_NOMORE) { validator_log(val, ISC_LOG_DEBUG(3), diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h index f1747be0583..efeb5f3d000 100644 --- a/lib/isc/include/isc/netmgr.h +++ b/lib/isc/include/isc/netmgr.h @@ -479,6 +479,9 @@ isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, * 'cb'. */ +#define ISC_NM_TASK_SLOW_OFFSET -2 +#define ISC_NM_TASK_SLOW(i) (ISC_NM_TASK_SLOW_OFFSET - 1 - i) + void isc_nm_task_enqueue(isc_nm_t *mgr, isc_task_t *task, int threadid); /*%< diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index 05fde1a791b..c3a176260b9 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -655,6 +655,7 @@ struct isc_nm { isc_refcount_t references; isc_mem_t *mctx; int nworkers; + int nlisteners; isc_mutex_t lock; isc_condition_t wkstatecond; isc_condition_t wkpausecond; diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index 6f42ec90ffb..7bff1cc9b3e 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -231,12 +231,12 @@ isc__nm_winsock_destroy(void) { #endif /* WIN32 */ static void -isc__nm_threadpool_initialize(uint32_t workers) { +isc__nm_threadpool_initialize(uint32_t nworkers) { char buf[11]; int r = uv_os_getenv("UV_THREADPOOL_SIZE", buf, &(size_t){ sizeof(buf) }); if (r == UV_ENOENT) { - snprintf(buf, sizeof(buf), "%" PRIu32, workers); + snprintf(buf, sizeof(buf), "%" PRIu32, nworkers); uv_os_setenv("UV_THREADPOOL_SIZE", buf); } } @@ -254,11 +254,11 @@ isc__nm_threadpool_initialize(uint32_t workers) { #endif void -isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) { +isc__netmgr_create(isc_mem_t *mctx, uint32_t nworkers, isc_nm_t **netmgrp) { isc_nm_t *mgr = NULL; char name[32]; - REQUIRE(workers > 0); + REQUIRE(nworkers > 0); #ifdef MAXIMAL_UV_VERSION if (uv_version() > MAXIMAL_UV_VERSION) { @@ -282,10 +282,13 @@ isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) { isc__nm_winsock_initialize(); #endif /* WIN32 */ - isc__nm_threadpool_initialize(workers); + isc__nm_threadpool_initialize(nworkers); mgr = isc_mem_get(mctx, sizeof(*mgr)); - *mgr = (isc_nm_t){ .nworkers = workers }; + *mgr = (isc_nm_t){ + .nworkers = nworkers * 2, + .nlisteners = nworkers, + }; isc_mem_attach(mctx, &mgr->mctx); isc_mutex_init(&mgr->lock); @@ -316,11 +319,12 @@ isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) { atomic_init(&mgr->keepalive, 30000); atomic_init(&mgr->advertised, 30000); - isc_barrier_init(&mgr->pausing, workers); - isc_barrier_init(&mgr->resuming, workers); + isc_barrier_init(&mgr->pausing, mgr->nworkers); + isc_barrier_init(&mgr->resuming, mgr->nworkers); - mgr->workers = isc_mem_get(mctx, workers * sizeof(isc__networker_t)); - for (size_t i = 0; i < workers; i++) { + mgr->workers = isc_mem_get(mctx, + mgr->nworkers * sizeof(isc__networker_t)); + for (int i = 0; i < mgr->nworkers; i++) { isc__networker_t *worker = &mgr->workers[i]; int r; @@ -354,7 +358,7 @@ isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) { mgr->workers_running++; isc_thread_create(nm_thread, &mgr->workers[i], &worker->thread); - snprintf(name, sizeof(name), "isc-net-%04zu", i); + snprintf(name, sizeof(name), "isc-net-%04d", i); isc_thread_setname(worker->thread, name); } @@ -840,9 +844,15 @@ isc_nm_task_enqueue(isc_nm_t *nm, isc_task_t *task, int threadid) { isc__networker_t *worker = NULL; if (threadid == -1) { - tid = (int)isc_random_uniform(nm->nworkers); + tid = (int)isc_random_uniform(nm->nlisteners); + } else if (threadid == ISC_NM_TASK_SLOW_OFFSET) { + tid = nm->nlisteners + + (int)isc_random_uniform(nm->nworkers - nm->nlisteners); + } else if (threadid < ISC_NM_TASK_SLOW_OFFSET) { + tid = nm->nlisteners + (ISC_NM_TASK_SLOW(threadid) % + (nm->nworkers - nm->nlisteners)); } else { - tid = threadid % nm->nworkers; + tid = threadid % nm->nlisteners; } worker = &nm->workers[tid]; diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c index 821d6c4568e..1666318453c 100644 --- a/lib/isc/netmgr/tcp.c +++ b/lib/isc/netmgr/tcp.c @@ -323,7 +323,7 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, isc__nm_connectcb(sock, req, result, false); } else { isc__nmsocket_clearcb(sock); - sock->tid = isc_random_uniform(mgr->nworkers); + sock->tid = isc_random_uniform(mgr->nlisteners); isc__nm_connectcb(sock, req, result, true); } atomic_store(&sock->closed, true); @@ -341,7 +341,7 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, isc__nm_put_netievent_tcpconnect(mgr, ievent); } else { atomic_init(&sock->active, false); - sock->tid = isc_random_uniform(mgr->nworkers); + sock->tid = isc_random_uniform(mgr->nlisteners); isc__nm_enqueue_ievent(&mgr->workers[sock->tid], (isc__netievent_t *)ievent); } @@ -445,7 +445,7 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_sockaddr_t *iface, #if defined(WIN32) sock->nchildren = 1; #else - sock->nchildren = mgr->nworkers; + sock->nchildren = mgr->nlisteners; #endif children_size = sock->nchildren * sizeof(sock->children[0]); sock->children = isc_mem_get(mgr->mctx, children_size); diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c index bd593ebf4f7..037d74c607b 100644 --- a/lib/isc/netmgr/tcpdns.c +++ b/lib/isc/netmgr/tcpdns.c @@ -303,7 +303,7 @@ isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, isc__nm_put_netievent_tcpdnsconnect(mgr, ievent); } else { atomic_init(&sock->active, false); - sock->tid = isc_random_uniform(mgr->nworkers); + sock->tid = isc_random_uniform(mgr->nlisteners); isc__nm_enqueue_ievent(&mgr->workers[sock->tid], (isc__netievent_t *)ievent); } @@ -410,7 +410,7 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_sockaddr_t *iface, #if defined(WIN32) sock->nchildren = 1; #else - sock->nchildren = mgr->nworkers; + sock->nchildren = mgr->nlisteners; #endif children_size = sock->nchildren * sizeof(sock->children[0]); sock->children = isc_mem_get(mgr->mctx, children_size); diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c index 00f9d40884f..bc59fca5436 100644 --- a/lib/isc/netmgr/udp.c +++ b/lib/isc/netmgr/udp.c @@ -136,7 +136,7 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_sockaddr_t *iface, isc_nm_recv_cb_t cb, uv_os_sock_t fd = -1; /* - * We are creating mgr->nworkers duplicated sockets, one + * We are creating mgr->nlisteners duplicated sockets, one * socket for each worker thread. */ sock = isc_mem_get(mgr->mctx, sizeof(isc_nmsocket_t)); @@ -146,7 +146,7 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_sockaddr_t *iface, isc_nm_recv_cb_t cb, #if defined(WIN32) sock->nchildren = 1; #else - sock->nchildren = mgr->nworkers; + sock->nchildren = mgr->nlisteners; #endif children_size = sock->nchildren * sizeof(sock->children[0]); @@ -847,7 +847,7 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, isc__nm_put_netievent_udpconnect(mgr, event); } else { atomic_init(&sock->active, false); - sock->tid = isc_random_uniform(mgr->nworkers); + sock->tid = isc_random_uniform(mgr->nlisteners); isc__nm_enqueue_ievent(&mgr->workers[sock->tid], (isc__netievent_t *)event); }