From e2fc8e037ea6bb5de92b25ec9c12a624737ac5ca Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 8 Apr 2024 18:41:29 +0200 Subject: Merging upstream version 1:9.18.24. Signed-off-by: Daniel Baumann --- lib/dns/Makefile.in | 2 - lib/dns/adb.c | 10 +- lib/dns/catz.c | 16 ++ lib/dns/diff.c | 34 ++++ lib/dns/dst_api.c | 29 +++- lib/dns/include/dns/catz.h | 8 +- lib/dns/include/dns/dispatch.h | 2 +- lib/dns/include/dns/message.h | 40 +---- lib/dns/include/dns/name.h | 37 ++-- lib/dns/include/dns/rbt.h | 13 ++ lib/dns/include/dns/rpz.h | 5 +- lib/dns/include/dns/stats.h | 2 +- lib/dns/include/dns/validator.h | 1 + lib/dns/include/dst/dst.h | 4 + lib/dns/master.c | 2 +- lib/dns/message.c | 375 ++++++++++++++++++++++++++-------------- lib/dns/name.c | 1 + lib/dns/ncache.c | 2 +- lib/dns/nsec3.c | 14 +- lib/dns/opensslrsa_link.c | 6 +- lib/dns/private.c | 8 +- lib/dns/rbt.c | 8 + lib/dns/rbtdb.c | 237 +++++++++++++++++-------- lib/dns/rdata.c | 2 +- lib/dns/resolver.c | 30 ++-- lib/dns/rootns.c | 53 +++++- lib/dns/stats.c | 10 +- lib/dns/tsig.c | 22 ++- lib/dns/update.c | 53 +++--- lib/dns/validator.c | 67 ++++--- lib/dns/xfrin.c | 19 +- lib/dns/zone.c | 89 +++++----- 32 files changed, 752 insertions(+), 449 deletions(-) (limited to 'lib/dns') diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in index 7d71f13..a17d2a0 100644 --- a/lib/dns/Makefile.in +++ b/lib/dns/Makefile.in @@ -147,11 +147,9 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ $(top_srcdir)/m4/ax_jemalloc.m4 \ $(top_srcdir)/m4/ax_lib_lmdb.m4 \ - $(top_srcdir)/m4/ax_perl_module.m4 \ $(top_srcdir)/m4/ax_posix_shell.m4 \ $(top_srcdir)/m4/ax_prog_cc_for_build.m4 \ $(top_srcdir)/m4/ax_pthread.m4 \ - $(top_srcdir)/m4/ax_python_module.m4 \ $(top_srcdir)/m4/ax_restore_flags.m4 \ $(top_srcdir)/m4/ax_save_flags.m4 $(top_srcdir)/m4/ax_tls.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ diff --git a/lib/dns/adb.c b/lib/dns/adb.c index 449fe34..72390f2 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -448,8 +448,8 @@ enum { * These are currently used on simple unsigned ints, so they are * not really associated with any particular type. */ -#define WANT_INET(x) (((x)&DNS_ADBFIND_INET) != 0) -#define WANT_INET6(x) (((x)&DNS_ADBFIND_INET6) != 0) +#define WANT_INET(x) (((x) & DNS_ADBFIND_INET) != 0) +#define WANT_INET6(x) (((x) & DNS_ADBFIND_INET6) != 0) #define EXPIRE_OK(exp, now) ((exp == INT_MAX) || (exp < now)) @@ -458,12 +458,12 @@ enum { * glue, and compare this to the appropriate bits set in o, to see if * this is ok. */ -#define GLUE_OK(nf, o) (!NAME_GLUEOK(nf) || (((o)&DNS_ADBFIND_GLUEOK) != 0)) -#define HINT_OK(nf, o) (!NAME_HINTOK(nf) || (((o)&DNS_ADBFIND_HINTOK) != 0)) +#define GLUE_OK(nf, o) (!NAME_GLUEOK(nf) || (((o) & DNS_ADBFIND_GLUEOK) != 0)) +#define HINT_OK(nf, o) (!NAME_HINTOK(nf) || (((o) & DNS_ADBFIND_HINTOK) != 0)) #define GLUEHINT_OK(nf, o) (GLUE_OK(nf, o) || HINT_OK(nf, o)) #define STARTATZONE_MATCHES(nf, o) \ (((nf)->flags & DNS_ADBFIND_STARTATZONE) == \ - ((o)&DNS_ADBFIND_STARTATZONE)) + ((o) & DNS_ADBFIND_STARTATZONE)) #define ENTER_LEVEL ISC_LOG_DEBUG(50) #define EXIT_LEVEL ENTER_LEVEL diff --git a/lib/dns/catz.c b/lib/dns/catz.c index b18459e..a872701 100644 --- a/lib/dns/catz.c +++ b/lib/dns/catz.c @@ -881,6 +881,13 @@ dns_catz_add_zone(dns_catz_zones_t *catzs, const dns_name_t *name, LOCK(&catzs->lock); + /* + * This function is called only during a (re)configuration, while + * 'catzs->zones' can become NULL only during shutdown. + */ + INSIST(catzs->zones != NULL); + INSIST(!atomic_load(&catzs->shuttingdown)); + result = dns_catz_new_zone(catzs, &catz, name); if (result != ISC_R_SUCCESS) { goto cleanup; @@ -919,6 +926,10 @@ dns_catz_get_zone(dns_catz_zones_t *catzs, const dns_name_t *name) { REQUIRE(ISC_MAGIC_VALID(name, DNS_NAME_MAGIC)); LOCK(&catzs->lock); + if (catzs->zones == NULL) { + UNLOCK(&catzs->lock); + return (NULL); + } result = isc_ht_find(catzs->zones, name->ndata, name->length, (void **)&found); UNLOCK(&catzs->lock); @@ -2299,6 +2310,11 @@ dns__catz_update_cb(void *data) { */ dns_name_toregion(&updb->origin, &r); LOCK(&catzs->lock); + if (catzs->zones == NULL) { + UNLOCK(&catzs->lock); + result = ISC_R_SHUTTINGDOWN; + goto exit; + } result = isc_ht_find(catzs->zones, r.base, r.length, (void **)&oldcatz); is_active = (result == ISC_R_SUCCESS && oldcatz->active); UNLOCK(&catzs->lock); diff --git a/lib/dns/diff.c b/lib/dns/diff.c index 52f5aca..9daf16e 100644 --- a/lib/dns/diff.c +++ b/lib/dns/diff.c @@ -241,6 +241,22 @@ setownercase(dns_rdataset_t *rdataset, const dns_name_t *name) { } } +static const char * +optotext(dns_diffop_t op) { + switch (op) { + case DNS_DIFFOP_ADD: + return ("add"); + case DNS_DIFFOP_ADDRESIGN: + return ("add-resign"); + case DNS_DIFFOP_DEL: + return ("del"); + case DNS_DIFFOP_DELRESIGN: + return ("del-resign"); + default: + return ("unknown"); + } +} + static isc_result_t diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver, bool warn) { dns_difftuple_t *t; @@ -270,6 +286,7 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver, bool warn) { while (t != NULL && dns_name_equal(&t->name, name)) { dns_rdatatype_t type, covers; + dns_rdataclass_t rdclass; dns_diffop_t op; dns_rdatalist_t rdl; dns_rdataset_t rds; @@ -278,6 +295,7 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver, bool warn) { op = t->op; type = t->rdata.type; + rdclass = t->rdata.rdclass; covers = rdata_covers(&t->rdata); /* @@ -440,6 +458,22 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver, bool warn) { dns_rdataset_disassociate(&ardataset); } } else { + if (result == DNS_R_NOTEXACT) { + dns_name_format(name, namebuf, + sizeof(namebuf)); + dns_rdatatype_format(type, typebuf, + sizeof(typebuf)); + dns_rdataclass_format(rdclass, classbuf, + sizeof(classbuf)); + isc_log_write( + DIFF_COMMON_LOGARGS, + ISC_LOG_ERROR, + "dns_diff_apply: %s/%s/%s: %s " + "%s", + namebuf, typebuf, classbuf, + optotext(op), + isc_result_totext(result)); + } if (dns_rdataset_isassociated(&ardataset)) { dns_rdataset_disassociate(&ardataset); } diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c index f04ae2f..0658c69 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); @@ -753,6 +754,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; @@ -783,7 +791,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); } @@ -804,7 +812,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); } @@ -1647,7 +1655,7 @@ dst_key_read_public(const char *filename, int type, isc_mem_t *mctx, isc_token_t token; isc_result_t ret; dns_rdata_t rdata = DNS_RDATA_INIT; - unsigned int opt = ISC_LEXOPT_DNSMULTILINE; + unsigned int opt = ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE; dns_rdataclass_t rdclass = dns_rdataclass_in; isc_lexspecials_t specials; uint32_t ttl = 0; @@ -2351,7 +2359,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; @@ -2376,10 +2385,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/catz.h b/lib/dns/include/dns/catz.h index 1401380..ab5c614 100644 --- a/lib/dns/include/dns/catz.h +++ b/lib/dns/include/dns/catz.h @@ -13,10 +13,7 @@ #pragma once -/* - * Define this for reference count tracing in the unit - */ -#undef DNS_CATZ_TRACE +/* Add -DDNS_CATZ_TRACE=1 to CFLAGS for detailed reference tracing */ #include #include @@ -314,7 +311,8 @@ isc_result_t dns_catz_add_zone(dns_catz_zones_t *catzs, const dns_name_t *name, dns_catz_zone_t **catzp); /*%< - * Allocate a new catz named 'name' and put it in 'catzs' collection. + * Allocate a new catz named 'name' and put it in 'catzs' collection. This + * function is safe to call only during a (re)configuration. * * Requires: * \li 'catzs' is a valid dns_catz_zones_t. diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h index 96be0f4..ad377f0 100644 --- a/lib/dns/include/dns/dispatch.h +++ b/lib/dns/include/dns/dispatch.h @@ -58,7 +58,7 @@ #include -#undef DNS_DISPATCH_TRACE +/* Add -DDNS_DISPATCH_TRACE=1 to CFLAGS for detailed reference tracing */ ISC_LANG_BEGINDECLS diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index b5d9a5a..f15884a 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -597,7 +597,7 @@ dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx, * *\li 'cctx' be valid. * - *\li 'buffer' is a valid buffer. + *\li 'buffer' is a valid buffer with length less than 65536. * * Side Effects: * @@ -856,44 +856,6 @@ dns_message_findtype(const dns_name_t *name, dns_rdatatype_t type, *\li #ISC_R_NOTFOUND -- the desired type does not exist. */ -isc_result_t -dns_message_find(const dns_name_t *name, dns_rdataclass_t rdclass, - dns_rdatatype_t type, dns_rdatatype_t covers, - dns_rdataset_t **rdataset); -/*%< - * Search the name for the specified rdclass and type. If it is found, - * *rdataset is filled in with a pointer to that rdataset. - * - * Requires: - *\li if '**rdataset' is non-NULL, *rdataset needs to be NULL. - * - *\li 'type' be a valid type, and NOT dns_rdatatype_any. - * - *\li If 'type' is dns_rdatatype_rrsig, 'covers' must be a valid type. - * Otherwise it should be 0. - * - * Returns: - *\li #ISC_R_SUCCESS -- all is well. - *\li #ISC_R_NOTFOUND -- the desired type does not exist. - */ - -void -dns_message_movename(dns_message_t *msg, dns_name_t *name, - dns_section_t fromsection, dns_section_t tosection); -/*%< - * Move a name from one section to another. - * - * Requires: - * - *\li 'msg' be valid. - * - *\li 'name' must be a name already in 'fromsection'. - * - *\li 'fromsection' must be a valid section. - * - *\li 'tosection' must be a valid section. - */ - void dns_message_addname(dns_message_t *msg, dns_name_t *name, dns_section_t section); diff --git a/lib/dns/include/dns/name.h b/lib/dns/include/dns/name.h index a758c4d..199856a 100644 --- a/lib/dns/include/dns/name.h +++ b/lib/dns/include/dns/name.h @@ -68,6 +68,7 @@ #include #include +#include #include #include #include /* Required for storage size of dns_label_t. */ @@ -111,6 +112,7 @@ struct dns_name { isc_buffer_t *buffer; ISC_LINK(dns_name_t) link; ISC_LIST(dns_rdataset_t) list; + isc_ht_t *ht; }; #define DNS_NAME_MAGIC ISC_MAGIC('D', 'N', 'S', 'n') @@ -166,30 +168,24 @@ extern const dns_name_t *dns_wildcardname; * unsigned char offsets[] = { 0, 6 }; * dns_name_t value = DNS_NAME_INITABSOLUTE(data, offsets); */ -#define DNS_NAME_INITNONABSOLUTE(A, B) \ - { \ - DNS_NAME_MAGIC, A, (sizeof(A) - 1), sizeof(B), \ - DNS_NAMEATTR_READONLY, B, NULL, \ - { (void *)-1, (void *)-1 }, { \ - NULL, NULL \ - } \ +#define DNS_NAME_INITNONABSOLUTE(A, B) \ + { \ + DNS_NAME_MAGIC, A, (sizeof(A) - 1), sizeof(B), \ + DNS_NAMEATTR_READONLY, B, NULL, \ + { (void *)-1, (void *)-1 }, { NULL, NULL }, NULL \ } -#define DNS_NAME_INITABSOLUTE(A, B) \ - { \ - DNS_NAME_MAGIC, A, sizeof(A), sizeof(B), \ - DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, B, \ - NULL, { (void *)-1, (void *)-1 }, { \ - NULL, NULL \ - } \ +#define DNS_NAME_INITABSOLUTE(A, B) \ + { \ + DNS_NAME_MAGIC, A, sizeof(A), sizeof(B), \ + DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, B, \ + NULL, { (void *)-1, (void *)-1 }, { NULL, NULL }, NULL \ } -#define DNS_NAME_INITEMPTY \ - { \ - DNS_NAME_MAGIC, NULL, 0, 0, 0, NULL, NULL, \ - { (void *)-1, (void *)-1 }, { \ - NULL, NULL \ - } \ +#define DNS_NAME_INITEMPTY \ + { \ + DNS_NAME_MAGIC, NULL, 0, 0, 0, NULL, NULL, \ + { (void *)-1, (void *)-1 }, { NULL, NULL }, NULL \ } /*% @@ -1330,6 +1326,7 @@ ISC_LANG_ENDDECLS _n->buffer = NULL; \ ISC_LINK_INIT(_n, link); \ ISC_LIST_INIT(_n->list); \ + _n->ht = NULL; \ } while (0) #define DNS_NAME_RESET(n) \ diff --git a/lib/dns/include/dns/rbt.h b/lib/dns/include/dns/rbt.h index 3b62e12..40bf09e 100644 --- a/lib/dns/include/dns/rbt.h +++ b/lib/dns/include/dns/rbt.h @@ -124,6 +124,12 @@ struct dns_rbtnode { */ ISC_LINK(dns_rbtnode_t) deadlink; + /*% + * This linked list is used to store nodes from which tree pruning can + * be started. + */ + ISC_LINK(dns_rbtnode_t) prunelink; + /*@{*/ /*! * These values are used in the RBT DB implementation. The appropriate @@ -992,4 +998,11 @@ dns__rbtnode_namelen(dns_rbtnode_t *node); * Returns the length of the full name of the node. Used only internally * and in unit tests. */ + +unsigned int +dns__rbtnode_getsize(dns_rbtnode_t *node); +/* + * Return allocated size for a node. + */ + ISC_LANG_ENDDECLS diff --git a/lib/dns/include/dns/rpz.h b/lib/dns/include/dns/rpz.h index 364ad92..5885681 100644 --- a/lib/dns/include/dns/rpz.h +++ b/lib/dns/include/dns/rpz.h @@ -13,10 +13,7 @@ #pragma once -/* - * Define this for reference count tracing in the unit - */ -#undef DNS_RPZ_TRACE +/* Add -DDNS_RPZ_TRACE=1 to CFLAGS for detailed reference tracing */ #include #include diff --git a/lib/dns/include/dns/stats.h b/lib/dns/include/dns/stats.h index 683f870..3ea3956 100644 --- a/lib/dns/include/dns/stats.h +++ b/lib/dns/include/dns/stats.h @@ -493,7 +493,7 @@ extern const char *dns_statscounter_names[]; /*%< * Conversion macros among dns_rdatatype_t, attributes and isc_statscounter_t. */ -#define DNS_RDATASTATSTYPE_BASE(type) ((dns_rdatatype_t)((type)&0xFFFF)) +#define DNS_RDATASTATSTYPE_BASE(type) ((dns_rdatatype_t)((type) & 0xFFFF)) #define DNS_RDATASTATSTYPE_ATTR(type) ((type) >> 16) #define DNS_RDATASTATSTYPE_VALUE(b, a) (((a) << 16) | (b)) diff --git a/lib/dns/include/dns/validator.h b/lib/dns/include/dns/validator.h index 383dcb4..352a60a 100644 --- a/lib/dns/include/dns/validator.h +++ b/lib/dns/include/dns/validator.h @@ -148,6 +148,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 ca292b0..f845e9b 100644 --- a/lib/dns/include/dst/dst.h +++ b/lib/dns/include/dst/dst.h @@ -482,6 +482,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/master.c b/lib/dns/master.c index 97b9343..c785022 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -88,7 +88,7 @@ #define DNS_MASTER_LHS 2048 #define DNS_MASTER_RHS MINTSIZ -#define CHECKNAMESFAIL(x) (((x)&DNS_MASTER_CHECKNAMESFAIL) != 0) +#define CHECKNAMESFAIL(x) (((x) & DNS_MASTER_CHECKNAMESFAIL) != 0) typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t; diff --git a/lib/dns/message.c b/lib/dns/message.c index 1b983d9..8654e92 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -22,6 +22,8 @@ #include #include +#include +#include #include #include #include @@ -493,9 +495,11 @@ msgresetsigs(dns_message_t *msg, bool replying) { } else { dns_rdataset_disassociate(msg->tsig); isc_mempool_put(msg->rdspool, msg->tsig); + msg->tsig = NULL; if (msg->querytsig != NULL) { dns_rdataset_disassociate(msg->querytsig); isc_mempool_put(msg->rdspool, msg->querytsig); + msg->querytsig = NULL; } } dns_message_puttempname(msg, &msg->tsigname); @@ -790,6 +794,18 @@ dns_message_detach(dns_message_t **messagep) { } } +static isc_result_t +name_hash_add(isc_ht_t *ht, dns_name_t *name, dns_name_t **foundp) { + isc_result_t result = isc_ht_find(ht, name->ndata, name->length, + (void **)foundp); + if (result == ISC_R_SUCCESS) { + return (ISC_R_EXISTS); + } + result = isc_ht_add(ht, name->ndata, name->length, (void *)name); + INSIST(result == ISC_R_SUCCESS); + return (ISC_R_SUCCESS); +} + static isc_result_t findname(dns_name_t **foundname, const dns_name_t *target, dns_namelist_t *section) { @@ -809,29 +825,26 @@ findname(dns_name_t **foundname, const dns_name_t *target, return (ISC_R_NOTFOUND); } -isc_result_t -dns_message_find(const dns_name_t *name, dns_rdataclass_t rdclass, - dns_rdatatype_t type, dns_rdatatype_t covers, - dns_rdataset_t **rdataset) { - dns_rdataset_t *curr; - - REQUIRE(name != NULL); - REQUIRE(rdataset == NULL || *rdataset == NULL); - - for (curr = ISC_LIST_TAIL(name->list); curr != NULL; - curr = ISC_LIST_PREV(curr, link)) - { - if (curr->rdclass == rdclass && curr->type == type && - curr->covers == covers) - { - if (rdataset != NULL) { - *rdataset = curr; - } - return (ISC_R_SUCCESS); - } - } +typedef struct __attribute__((__packed__)) rds_key { + dns_rdataclass_t rdclass; + dns_rdatatype_t type; + dns_rdatatype_t covers; +} rds_key_t; - return (ISC_R_NOTFOUND); +static isc_result_t +rds_hash_add(isc_ht_t *ht, dns_rdataset_t *rds, dns_rdataset_t **foundp) { + rds_key_t key = { .rdclass = rds->rdclass, + .type = rds->type, + .covers = rds->covers }; + isc_result_t result = isc_ht_find(ht, (const unsigned char *)&key, + sizeof(key), (void **)foundp); + if (result == ISC_R_SUCCESS) { + return (ISC_R_EXISTS); + } + result = isc_ht_add(ht, (const unsigned char *)&key, sizeof(key), + (void *)rds); + INSIST(result == ISC_R_SUCCESS); + return (ISC_R_SUCCESS); } isc_result_t @@ -958,6 +971,18 @@ getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, } \ } while (0) +static void +cleanup_name_hashmaps(dns_namelist_t *section) { + dns_name_t *name = NULL; + for (name = ISC_LIST_HEAD(*section); name != NULL; + name = ISC_LIST_NEXT(name, link)) + { + if (name->ht != NULL) { + isc_ht_destroy(&name->ht); + } + } +} + static isc_result_t getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, unsigned int options) { @@ -967,13 +992,19 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, dns_name_t *name2 = NULL; dns_rdataset_t *rdataset = NULL; dns_rdatalist_t *rdatalist = NULL; - isc_result_t result; + isc_result_t result = ISC_R_SUCCESS; dns_rdatatype_t rdtype; dns_rdataclass_t rdclass; dns_namelist_t *section = &msg->sections[DNS_SECTION_QUESTION]; bool best_effort = ((options & DNS_MESSAGEPARSE_BESTEFFORT) != 0); bool seen_problem = false; bool free_name = false; + bool free_ht = false; + isc_ht_t *name_map = NULL; + + if (msg->counts[DNS_SECTION_QUESTION] > 1) { + isc_ht_init(&name_map, msg->mctx, 1, ISC_HT_CASE_INSENSITIVE); + } for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) { name = NULL; @@ -994,13 +1025,19 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, goto cleanup; } + /* If there is only one QNAME, skip the duplicity checks */ + if (name_map == NULL) { + result = ISC_R_SUCCESS; + goto skip_name_check; + } + /* * Run through the section, looking to see if this name * is already there. If it is found, put back the allocated * name since we no longer need it, and set our name pointer * to point to the name we found. */ - result = findname(&name2, name, section); + result = name_hash_add(name_map, name, &name2); /* * If it is the first name in the section, accept it. @@ -1012,19 +1049,25 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, * this should be legal or not. In either case we no longer * need this name pointer. */ - if (result != ISC_R_SUCCESS) { + skip_name_check: + switch (result) { + case ISC_R_SUCCESS: if (!ISC_LIST_EMPTY(*section)) { DO_ERROR(DNS_R_FORMERR); } ISC_LIST_APPEND(*section, name, link); - free_name = false; - } else { + break; + case ISC_R_EXISTS: dns_message_puttempname(msg, &name); name = name2; name2 = NULL; - free_name = false; + break; + default: + UNREACHABLE(); } + free_name = false; + /* * Get type and class. */ @@ -1054,14 +1097,6 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, msg->tkey = 1; } - /* - * Can't ask the same question twice. - */ - result = dns_message_find(name, rdclass, rdtype, 0, NULL); - if (result == ISC_R_SUCCESS) { - DO_ERROR(DNS_R_FORMERR); - } - /* * Allocate a new rdatalist. */ @@ -1071,6 +1106,7 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, goto cleanup; } rdataset = isc_mempool_get(msg->rdspool); + dns_rdataset_init(rdataset); /* * Convert rdatalist to rdataset, and attach the latter to @@ -1078,8 +1114,6 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, */ rdatalist->type = rdtype; rdatalist->rdclass = rdclass; - - dns_rdataset_init(rdataset); result = dns_rdatalist_tordataset(rdatalist, rdataset); if (result != ISC_R_SUCCESS) { goto cleanup; @@ -1087,24 +1121,66 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, rdataset->attributes |= DNS_RDATASETATTR_QUESTION; + /* + * Skip the duplicity check for first rdataset + */ + if (ISC_LIST_EMPTY(name->list)) { + result = ISC_R_SUCCESS; + goto skip_rds_check; + } + + /* + * Can't ask the same question twice. + */ + if (name->ht == NULL) { + isc_ht_init(&name->ht, msg->mctx, 1, + ISC_HT_CASE_SENSITIVE); + free_ht = true; + + INSIST(ISC_LIST_HEAD(name->list) == + ISC_LIST_TAIL(name->list)); + + dns_rdataset_t *old_rdataset = + ISC_LIST_HEAD(name->list); + + result = rds_hash_add(name->ht, old_rdataset, NULL); + + INSIST(result == ISC_R_SUCCESS); + } + result = rds_hash_add(name->ht, rdataset, NULL); + if (result == ISC_R_EXISTS) { + DO_ERROR(DNS_R_FORMERR); + } + + skip_rds_check: ISC_LIST_APPEND(name->list, rdataset, link); + rdataset = NULL; } if (seen_problem) { - return (DNS_R_RECOVERABLE); + result = DNS_R_RECOVERABLE; } - return (ISC_R_SUCCESS); cleanup: if (rdataset != NULL) { - INSIST(!dns_rdataset_isassociated(rdataset)); + if (dns_rdataset_isassociated(rdataset)) { + dns_rdataset_disassociate(rdataset); + } isc_mempool_put(msg->rdspool, rdataset); } if (free_name) { dns_message_puttempname(msg, &name); } + if (free_ht) { + cleanup_name_hashmaps(section); + } + + if (name_map != NULL) { + isc_ht_destroy(&name_map); + } + return (result); } @@ -1184,17 +1260,24 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, dns_name_t *name = NULL; dns_name_t *name2 = NULL; dns_rdataset_t *rdataset = NULL; + dns_rdataset_t *found_rdataset = NULL; dns_rdatalist_t *rdatalist = NULL; - isc_result_t result; + isc_result_t result = ISC_R_SUCCESS; dns_rdatatype_t rdtype, covers; dns_rdataclass_t rdclass; dns_rdata_t *rdata = NULL; dns_ttl_t ttl; dns_namelist_t *section = &msg->sections[sectionid]; - bool free_name = false, free_rdataset = false, seen_problem = false; + bool free_name = false, seen_problem = false; + bool free_ht = false; bool preserve_order = ((options & DNS_MESSAGEPARSE_PRESERVEORDER) != 0); bool best_effort = ((options & DNS_MESSAGEPARSE_BESTEFFORT) != 0); bool isedns, issigzero, istsig; + isc_ht_t *name_map = NULL; + + if (msg->counts[sectionid] > 1) { + isc_ht_init(&name_map, msg->mctx, 1, ISC_HT_CASE_INSENSITIVE); + } for (count = 0; count < msg->counts[sectionid]; count++) { int recstart = source->current; @@ -1202,10 +1285,10 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, skip_name_search = false; skip_type_search = false; - free_rdataset = false; isedns = false; issigzero = false; istsig = false; + found_rdataset = NULL; name = NULL; result = dns_message_gettempname(msg, &name); @@ -1245,8 +1328,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, if (msg->rdclass_set == 0 && rdtype != dns_rdatatype_opt && /* class is UDP SIZE */ rdtype != dns_rdatatype_tsig && /* class is ANY */ - rdtype != dns_rdatatype_tkey) - { /* class is undefined */ + rdtype != dns_rdatatype_tkey) /* class is undefined */ + { msg->rdclass = rdclass; msg->rdclass_set = 1; } @@ -1353,10 +1436,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, * Then put the meta-class back into the finished rdata. */ rdata = newrdata(msg); - if (rdata == NULL) { - result = ISC_R_NOMEMORY; - goto cleanup; - } if (msg->opcode == dns_opcode_update && update(sectionid, rdclass)) { @@ -1445,34 +1524,62 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, free_name = false; } } else { + if (name_map == NULL) { + result = ISC_R_SUCCESS; + goto skip_name_check; + } + /* * Run through the section, looking to see if this name * is already there. If it is found, put back the * allocated name since we no longer need it, and set * our name pointer to point to the name we found. */ - result = findname(&name2, name, section); + result = name_hash_add(name_map, name, &name2); /* * If it is a new name, append to the section. */ - if (result == ISC_R_SUCCESS) { + skip_name_check: + switch (result) { + case ISC_R_SUCCESS: + ISC_LIST_APPEND(*section, name, link); + break; + case ISC_R_EXISTS: dns_message_puttempname(msg, &name); name = name2; - } else { - ISC_LIST_APPEND(*section, name, link); + name2 = NULL; + break; + default: + UNREACHABLE(); } free_name = false; } + rdatalist = newrdatalist(msg); + rdatalist->type = rdtype; + rdatalist->covers = covers; + rdatalist->rdclass = rdclass; + rdatalist->ttl = ttl; + + dns_message_gettemprdataset(msg, &rdataset); + RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == + ISC_R_SUCCESS); + dns_rdataset_setownercase(rdataset, name); + rdatalist = NULL; + /* * Search name for the particular type and class. * Skip this stage if in update mode or this is a meta-type. */ - if (preserve_order || msg->opcode == dns_opcode_update || - skip_type_search) + if (isedns || istsig || issigzero) { + /* Skip adding the rdataset to the tables */ + } else if (preserve_order || msg->opcode == dns_opcode_update || + skip_type_search) { - result = ISC_R_NOTFOUND; + result = ISC_R_SUCCESS; + + ISC_LIST_APPEND(name->list, rdataset, link); } else { /* * If this is a type that can only occur in @@ -1482,59 +1589,71 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, DO_ERROR(DNS_R_FORMERR); } - rdataset = NULL; - result = dns_message_find(name, rdclass, rdtype, covers, - &rdataset); - } - - /* - * If we found an rdataset that matches, we need to - * append this rdata to that set. If we did not, we need - * to create a new rdatalist, store the important bits there, - * convert it to an rdataset, and link the latter to the name. - * Yuck. When appending, make certain that the type isn't - * a singleton type, such as SOA or CNAME. - * - * Note that this check will be bypassed when preserving order, - * the opcode is an update, or the type search is skipped. - */ - if (result == ISC_R_SUCCESS) { - if (dns_rdatatype_issingleton(rdtype)) { - dns_rdata_t *first; - dns_rdatalist_fromrdataset(rdataset, - &rdatalist); - first = ISC_LIST_HEAD(rdatalist->rdata); - INSIST(first != NULL); - if (dns_rdata_compare(rdata, first) != 0) { - DO_ERROR(DNS_R_FORMERR); - } + if (ISC_LIST_EMPTY(name->list)) { + result = ISC_R_SUCCESS; + goto skip_rds_check; } - } - if (result == ISC_R_NOTFOUND) { - rdataset = isc_mempool_get(msg->rdspool); - free_rdataset = true; + if (name->ht == NULL) { + isc_ht_init(&name->ht, msg->mctx, 1, + ISC_HT_CASE_SENSITIVE); + free_ht = true; - rdatalist = newrdatalist(msg); - if (rdatalist == NULL) { - result = ISC_R_NOMEMORY; - goto cleanup; + INSIST(ISC_LIST_HEAD(name->list) == + ISC_LIST_TAIL(name->list)); + + dns_rdataset_t *old_rdataset = + ISC_LIST_HEAD(name->list); + + result = rds_hash_add(name->ht, old_rdataset, + NULL); + + INSIST(result == ISC_R_SUCCESS); } + found_rdataset = NULL; + result = rds_hash_add(name->ht, rdataset, + &found_rdataset); - rdatalist->type = rdtype; - rdatalist->covers = covers; - rdatalist->rdclass = rdclass; - rdatalist->ttl = ttl; + /* + * If we found an rdataset that matches, we need to + * append this rdata to that set. If we did not, we + * need to create a new rdatalist, store the important + * bits there, convert it to an rdataset, and link the + * latter to the name. Yuck. When appending, make + * certain that the type isn't a singleton type, such as + * SOA or CNAME. + * + * Note that this check will be bypassed when preserving + * order, the opcode is an update, or the type search is + * skipped. + */ + skip_rds_check: + switch (result) { + case ISC_R_EXISTS: + /* Free the rdataset we used as the key */ + dns_rdataset_disassociate(rdataset); + isc_mempool_put(msg->rdspool, rdataset); + result = ISC_R_SUCCESS; + rdataset = found_rdataset; - dns_rdataset_init(rdataset); - RUNTIME_CHECK( - dns_rdatalist_tordataset(rdatalist, rdataset) == - ISC_R_SUCCESS); - dns_rdataset_setownercase(rdataset, name); + if (!dns_rdatatype_issingleton(rdtype)) { + break; + } - if (!isedns && !istsig && !issigzero) { + dns_rdatalist_fromrdataset(rdataset, + &rdatalist); + dns_rdata_t *first = + ISC_LIST_HEAD(rdatalist->rdata); + INSIST(first != NULL); + if (dns_rdata_compare(rdata, first) != 0) { + DO_ERROR(DNS_R_FORMERR); + } + break; + case ISC_R_SUCCESS: ISC_LIST_APPEND(name->list, rdataset, link); - free_rdataset = false; + break; + default: + UNREACHABLE(); } } @@ -1569,8 +1688,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, dns_rcode_t ercode; msg->opt = rdataset; - rdataset = NULL; - free_rdataset = false; ercode = (dns_rcode_t)((msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK) >> 20); @@ -1581,8 +1698,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, msg->sig0 = rdataset; msg->sig0name = name; msg->sigstart = recstart; - rdataset = NULL; - free_rdataset = false; free_name = false; } else if (istsig) { msg->tsig = rdataset; @@ -1592,22 +1707,17 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, * Windows doesn't like TSIG names to be compressed. */ msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS; - rdataset = NULL; - free_rdataset = false; free_name = false; } + rdataset = NULL; if (seen_problem) { if (free_name) { dns_message_puttempname(msg, &name); } - if (free_rdataset) { - isc_mempool_put(msg->rdspool, rdataset); - } - free_name = free_rdataset = false; + free_name = false; } INSIST(!free_name); - INSIST(!free_rdataset); } /* @@ -1625,16 +1735,24 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, } if (seen_problem) { - return (DNS_R_RECOVERABLE); + result = DNS_R_RECOVERABLE; } - return (ISC_R_SUCCESS); cleanup: + if (rdataset != NULL && rdataset != found_rdataset) { + dns_rdataset_disassociate(rdataset); + isc_mempool_put(msg->rdspool, rdataset); + } if (free_name) { dns_message_puttempname(msg, &name); } - if (free_rdataset) { - isc_mempool_put(msg->rdspool, rdataset); + + if (free_ht) { + cleanup_name_hashmaps(section); + } + + if (name_map != NULL) { + isc_ht_destroy(&name_map); } return (result); @@ -1774,6 +1892,7 @@ dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx, REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(buffer != NULL); + REQUIRE(isc_buffer_length(buffer) < 65536); REQUIRE(msg->buffer == NULL); REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); @@ -2451,7 +2570,7 @@ dns_message_findname(dns_message_t *msg, dns_section_t section, const dns_name_t *target, dns_rdatatype_t type, dns_rdatatype_t covers, dns_name_t **name, dns_rdataset_t **rdataset) { - dns_name_t *foundname; + dns_name_t *foundname = NULL; isc_result_t result; /* @@ -2498,22 +2617,6 @@ dns_message_findname(dns_message_t *msg, dns_section_t section, return (result); } -void -dns_message_movename(dns_message_t *msg, dns_name_t *name, - dns_section_t fromsection, dns_section_t tosection) { - REQUIRE(msg != NULL); - REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); - REQUIRE(name != NULL); - REQUIRE(VALID_NAMED_SECTION(fromsection)); - REQUIRE(VALID_NAMED_SECTION(tosection)); - - /* - * Unlink the name from the old section - */ - ISC_LIST_UNLINK(msg->sections[fromsection], name, link); - ISC_LIST_APPEND(msg->sections[tosection], name, link); -} - void dns_message_addname(dns_message_t *msg, dns_name_t *name, dns_section_t section) { @@ -2590,6 +2693,10 @@ dns_message_puttempname(dns_message_t *msg, dns_name_t **itemp) { REQUIRE(!ISC_LINK_LINKED(item, link)); REQUIRE(ISC_LIST_HEAD(item->list) == NULL); + if (item->ht != NULL) { + isc_ht_destroy(&item->ht); + } + /* * we need to check this in case dns_name_dup() was used. */ diff --git a/lib/dns/name.c b/lib/dns/name.c index 8a258a2..90044ba 100644 --- a/lib/dns/name.c +++ b/lib/dns/name.c @@ -188,6 +188,7 @@ dns_name_invalidate(dns_name_t *name) { name->offsets = NULL; name->buffer = NULL; ISC_LINK_INIT(name, link); + INSIST(name->ht == NULL); } bool diff --git a/lib/dns/ncache.c b/lib/dns/ncache.c index 9247ac1..941574d 100644 --- a/lib/dns/ncache.c +++ b/lib/dns/ncache.c @@ -754,7 +754,7 @@ dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found, raw += 2; sigregion.base = raw; dns_rdata_reset(&rdata); - dns_rdata_fromregion(&rdata, rdataset->rdclass, rdataset->type, + dns_rdata_fromregion(&rdata, ncacherdataset->rdclass, type, &sigregion); (void)dns_rdata_tostruct(&rdata, &rrsig, NULL); rdataset->covers = rrsig.covered; diff --git a/lib/dns/nsec3.c b/lib/dns/nsec3.c index b9fc699..5785cc1 100644 --- a/lib/dns/nsec3.c +++ b/lib/dns/nsec3.c @@ -48,10 +48,10 @@ goto failure; \ } while (0) -#define OPTOUT(x) (((x)&DNS_NSEC3FLAG_OPTOUT) != 0) -#define CREATE(x) (((x)&DNS_NSEC3FLAG_CREATE) != 0) -#define INITIAL(x) (((x)&DNS_NSEC3FLAG_INITIAL) != 0) -#define REMOVE(x) (((x)&DNS_NSEC3FLAG_REMOVE) != 0) +#define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0) +#define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0) +#define INITIAL(x) (((x) & DNS_NSEC3FLAG_INITIAL) != 0) +#define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0) isc_result_t dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node, @@ -1138,12 +1138,6 @@ dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver, dns_rdata_t private = DNS_RDATA_INIT; dns_rdataset_current(&rdataset, &rdata); - - CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, origin, - rdataset.ttl, &rdata, &tuple)); - CHECK(do_one_tuple(&tuple, db, ver, diff)); - INSIST(tuple == NULL); - dns_nsec3param_toprivate(&rdata, &private, privatetype, buf, sizeof(buf)); buf[2] = DNS_NSEC3FLAG_REMOVE; diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c index dc7382c..1a0bb0f 100644 --- a/lib/dns/opensslrsa_link.c +++ b/lib/dns/opensslrsa_link.c @@ -1135,9 +1135,10 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { #if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 const BIGNUM *ex = NULL; ENGINE *ep = NULL; + const char *engine = NULL; #endif /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */ isc_mem_t *mctx = NULL; - const char *engine = NULL, *label = NULL; + const char *label = NULL; EVP_PKEY *pkey = NULL; BIGNUM *n = NULL, *e = NULL, *d = NULL; BIGNUM *p = NULL, *q = NULL; @@ -1175,9 +1176,11 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { for (i = 0; i < priv.nelements; i++) { switch (priv.elements[i].tag) { +#if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 case TAG_RSA_ENGINE: engine = (char *)priv.elements[i].data; break; +#endif case TAG_RSA_LABEL: label = (char *)priv.elements[i].data; break; @@ -1229,7 +1232,6 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { pkey = NULL; DST_RET(ISC_R_SUCCESS); #else /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */ - UNUSED(engine); DST_RET(DST_R_NOENGINE); #endif /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */ } diff --git a/lib/dns/private.c b/lib/dns/private.c index 56573b3..4157e82 100644 --- a/lib/dns/private.c +++ b/lib/dns/private.c @@ -39,10 +39,10 @@ * been requested to be built otherwise a NSEC chain needs to be built. */ -#define REMOVE(x) (((x)&DNS_NSEC3FLAG_REMOVE) != 0) -#define CREATE(x) (((x)&DNS_NSEC3FLAG_CREATE) != 0) -#define INITIAL(x) (((x)&DNS_NSEC3FLAG_INITIAL) != 0) -#define NONSEC(x) (((x)&DNS_NSEC3FLAG_NONSEC) != 0) +#define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0) +#define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0) +#define INITIAL(x) (((x) & DNS_NSEC3FLAG_INITIAL) != 0) +#define NONSEC(x) (((x) & DNS_NSEC3FLAG_NONSEC) != 0) #define CHECK(x) \ do { \ diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c index 57dcd54..29f19c8 100644 --- a/lib/dns/rbt.c +++ b/lib/dns/rbt.c @@ -302,6 +302,13 @@ dns__rbtnode_namelen(dns_rbtnode_t *node) { return (len); } +unsigned int +dns__rbtnode_getsize(dns_rbtnode_t *node) { + REQUIRE(DNS_RBTNODE_VALID(node)); + + return (NODE_SIZE(node)); +} + /* * Initialize a red/black tree of trees. */ @@ -1569,6 +1576,7 @@ create_node(isc_mem_t *mctx, const dns_name_t *name, dns_rbtnode_t **nodep) { HASHVAL(node) = 0; ISC_LINK_INIT(node, deadlink); + ISC_LINK_INIT(node, prunelink); LOCKNUM(node) = 0; WILD(node) = 0; diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 5d36466..b09d97f 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -82,7 +82,7 @@ typedef uint32_t rbtdb_serial_t; typedef uint32_t rbtdb_rdatatype_t; -#define RBTDB_RDATATYPE_BASE(type) ((dns_rdatatype_t)((type)&0xFFFF)) +#define RBTDB_RDATATYPE_BASE(type) ((dns_rdatatype_t)((type) & 0xFFFF)) #define RBTDB_RDATATYPE_EXT(type) ((dns_rdatatype_t)((type) >> 16)) #define RBTDB_RDATATYPE_VALUE(base, ext) \ ((rbtdb_rdatatype_t)(((uint32_t)ext) << 16) | \ @@ -477,12 +477,27 @@ struct dns_rbtdb { */ rdatasetheaderlist_t *rdatasets; + /* + * Start point % node_lock_count for next LRU cleanup. + */ + atomic_uint lru_sweep; + + /* + * When performing LRU cleaning limit cleaning to headers that were + * last used at or before this. + */ + atomic_uint last_used; + /*% * Temporary storage for stale cache nodes and dynamically deleted * nodes that await being cleaned up. */ rbtnodelist_t *deadnodes; + /* List of nodes from which recursive tree pruning can be started from. + * Locked by tree_lock. */ + rbtnodelist_t prunenodes; + /* * Heaps. These are used for TTL based expiry in a cache, * or for zone resigning in a zone DB. hmctx is the memory @@ -561,8 +576,7 @@ static void expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, bool tree_locked, expire_t reason); static void -overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, size_t purgesize, - bool tree_locked); +overmem_purge(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, bool tree_locked); static void resign_insert(dns_rbtdb_t *rbtdb, int idx, rdatasetheader_t *newheader); static void @@ -993,6 +1007,7 @@ free_rbtdb(dns_rbtdb_t *rbtdb, bool log, isc_event_t *event) { unsigned int i; isc_result_t result; char buf[DNS_NAME_FORMATSIZE]; + dns_rbtnode_t *node = NULL; dns_rbt_t **treep; isc_time_t start; @@ -1018,8 +1033,6 @@ free_rbtdb(dns_rbtdb_t *rbtdb, bool log, isc_event_t *event) { * the overhead of unlinking all nodes here should be negligible. */ for (i = 0; i < rbtdb->node_lock_count; i++) { - dns_rbtnode_t *node; - node = ISC_LIST_HEAD(rbtdb->deadnodes[i]); while (node != NULL) { ISC_LIST_UNLINK(rbtdb->deadnodes[i], node, deadlink); @@ -1027,6 +1040,12 @@ free_rbtdb(dns_rbtdb_t *rbtdb, bool log, isc_event_t *event) { } } + node = ISC_LIST_HEAD(rbtdb->prunenodes); + while (node != NULL) { + ISC_LIST_UNLINK(rbtdb->prunenodes, node, prunelink); + node = ISC_LIST_HEAD(rbtdb->prunenodes); + } + if (event == NULL) { rbtdb->quantum = (rbtdb->task != NULL) ? 100 : 0; } @@ -1832,19 +1851,32 @@ is_leaf(dns_rbtnode_t *node) { node->left == NULL && node->right == NULL); } +/*% + * The tree lock must be held when this function is called as it reads and + * updates rbtdb->prunenodes. + */ static void send_to_prune_tree(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, isc_rwlocktype_t locktype) { - isc_event_t *ev; - dns_db_t *db; + bool pruning_queued = (ISC_LIST_HEAD(rbtdb->prunenodes) != NULL); + + INSIST(locktype == isc_rwlocktype_write); - ev = isc_event_allocate(rbtdb->common.mctx, NULL, DNS_EVENT_RBTPRUNE, - prune_tree, node, sizeof(isc_event_t)); new_reference(rbtdb, node, locktype); - db = NULL; - attach((dns_db_t *)rbtdb, &db); - ev->ev_sender = db; - isc_task_send(rbtdb->task, &ev); + INSIST(!ISC_LINK_LINKED(node, prunelink)); + ISC_LIST_APPEND(rbtdb->prunenodes, node, prunelink); + + if (!pruning_queued) { + isc_event_t *ev = NULL; + dns_db_t *db = NULL; + + attach((dns_db_t *)rbtdb, &db); + + ev = isc_event_allocate(rbtdb->common.mctx, NULL, + DNS_EVENT_RBTPRUNE, prune_tree, db, + sizeof(isc_event_t)); + isc_task_send(rbtdb->task, &ev); + } } /*% @@ -2119,17 +2151,26 @@ restore_locks: } /* - * Prune the tree by recursively cleaning-up single leaves. In the worst - * case, the number of iteration is the number of tree levels, which is at - * most the maximum number of domain name labels, i.e, 127. In practice, this - * should be much smaller (only a few times), and even the worst case would be - * acceptable for a single event. + * Prune the tree by recursively cleaning up single leaves. Go through all + * nodes stored in the rbtdb->prunenodes list; for each of them, in the worst + * case, it will be necessary to traverse a number of tree levels equal to the + * maximum legal number of domain name labels (127); in practice, the number of + * tree levels to traverse will virtually always be much smaller (a few levels + * at most). While holding the tree lock throughout this entire operation is + * less than ideal, so is splitting the latter up by queueing a separate + * prune_tree() run for each node to start pruning from (as queueing requires + * allocating memory and can therefore potentially be exploited to exhaust + * available memory). Also note that actually freeing up the memory used by + * RBTDB nodes (which is what this function does) is essential to keeping cache + * memory use in check, so since the tree lock needs to be acquired anyway, + * freeing as many nodes as possible before the tree lock gets released is + * prudent. */ static void prune_tree(isc_task_t *task, isc_event_t *event) { - dns_rbtdb_t *rbtdb = event->ev_sender; - dns_rbtnode_t *node = event->ev_arg; - dns_rbtnode_t *parent; + dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)event->ev_arg; + dns_rbtnode_t *node = NULL; + dns_rbtnode_t *parent = NULL; unsigned int locknum; UNUSED(task); @@ -2137,44 +2178,60 @@ prune_tree(isc_task_t *task, isc_event_t *event) { isc_event_free(&event); RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); - locknum = node->locknum; - NODE_LOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write); - do { - parent = node->parent; - decrement_reference(rbtdb, node, 0, isc_rwlocktype_write, - isc_rwlocktype_write, true); - if (parent != NULL && parent->down == NULL) { - /* - * node was the only down child of the parent and has - * just been removed. We'll then need to examine the - * parent. Keep the lock if possible; otherwise, - * release the old lock and acquire one for the parent. - */ - if (parent->locknum != locknum) { - NODE_UNLOCK(&rbtdb->node_locks[locknum].lock, - isc_rwlocktype_write); - locknum = parent->locknum; - NODE_LOCK(&rbtdb->node_locks[locknum].lock, - isc_rwlocktype_write); + while ((node = ISC_LIST_HEAD(rbtdb->prunenodes)) != NULL) { + locknum = node->locknum; + NODE_LOCK(&rbtdb->node_locks[locknum].lock, + isc_rwlocktype_write); + do { + if (ISC_LINK_LINKED(node, prunelink)) { + ISC_LIST_UNLINK(rbtdb->prunenodes, node, + prunelink); } - /* - * We need to gain a reference to the node before - * decrementing it in the next iteration. - */ - if (ISC_LINK_LINKED(parent, deadlink)) { - ISC_LIST_UNLINK(rbtdb->deadnodes[locknum], + parent = node->parent; + decrement_reference(rbtdb, node, 0, + isc_rwlocktype_write, + isc_rwlocktype_write, true); + + if (parent != NULL && parent->down == NULL) { + /* + * node was the only down child of the parent + * and has just been removed. We'll then need + * to examine the parent. Keep the lock if + * possible; otherwise, release the old lock and + * acquire one for the parent. + */ + if (parent->locknum != locknum) { + NODE_UNLOCK( + &rbtdb->node_locks[locknum].lock, + isc_rwlocktype_write); + locknum = parent->locknum; + NODE_LOCK( + &rbtdb->node_locks[locknum].lock, + isc_rwlocktype_write); + } + + /* + * We need to gain a reference to the node + * before decrementing it in the next iteration. + */ + if (ISC_LINK_LINKED(parent, deadlink)) { + ISC_LIST_UNLINK( + rbtdb->deadnodes[locknum], parent, deadlink); + } + new_reference(rbtdb, parent, + isc_rwlocktype_write); + } else { + parent = NULL; } - new_reference(rbtdb, parent, isc_rwlocktype_write); - } else { - parent = NULL; - } - node = parent; - } while (node != NULL); - NODE_UNLOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write); + node = parent; + } while (node != NULL); + NODE_UNLOCK(&rbtdb->node_locks[locknum].lock, + isc_rwlocktype_write); + } RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); detach((dns_db_t **)&rbtdb); @@ -6444,6 +6501,9 @@ find_header: if (header->rdh_ttl > newheader->rdh_ttl) { set_ttl(rbtdb, header, newheader->rdh_ttl); } + if (header->last_used != now) { + update_header(rbtdb, header, now); + } if (header->noqname == NULL && newheader->noqname != NULL) { @@ -6496,6 +6556,9 @@ find_header: if (header->rdh_ttl > newheader->rdh_ttl) { set_ttl(rbtdb, header, newheader->rdh_ttl); } + if (header->last_used != now) { + update_header(rbtdb, header, now); + } if (header->noqname == NULL && newheader->noqname != NULL) { @@ -6523,6 +6586,9 @@ find_header: idx = newheader->node->locknum; if (IS_CACHE(rbtdb)) { if (ZEROTTL(newheader)) { + newheader->last_used = + atomic_load(&rbtdb->last_used) + + 1; ISC_LIST_APPEND(rbtdb->rdatasets[idx], newheader, link); } else { @@ -6564,6 +6630,9 @@ find_header: INSIST(rbtdb->heaps != NULL); isc_heap_insert(rbtdb->heaps[idx], newheader); if (ZEROTTL(newheader)) { + newheader->last_used = + atomic_load(&rbtdb->last_used) + + 1; ISC_LIST_APPEND(rbtdb->rdatasets[idx], newheader, link); } else { @@ -6969,8 +7038,7 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, } if (cache_is_overmem) { - overmem_purge(rbtdb, rbtnode->locknum, rdataset_size(newheader), - tree_locked); + overmem_purge(rbtdb, newheader, tree_locked); } NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock, @@ -8305,6 +8373,8 @@ dns_rbtdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type, ISC_LIST_INIT(rbtdb->deadnodes[i]); } + ISC_LIST_INIT(rbtdb->prunenodes); + rbtdb->active = rbtdb->node_lock_count; for (i = 0; i < (int)(rbtdb->node_lock_count); i++) { @@ -9640,7 +9710,7 @@ rehash_bits(rbtdb_version_t *version, size_t newcount) { uint32_t newbits = oldbits; while (newcount >= HASHSIZE(newbits) && - newbits <= RBTDB_GLUE_TABLE_MAX_BITS) + newbits < RBTDB_GLUE_TABLE_MAX_BITS) { newbits += 1; } @@ -10147,7 +10217,10 @@ expire_lru_headers(dns_rbtdb_t *rbtdb, unsigned int locknum, size_t purgesize, size_t purged = 0; for (header = ISC_LIST_TAIL(rbtdb->rdatasets[locknum]); - header != NULL && purged <= purgesize; header = header_prev) + header != NULL && + header->last_used <= atomic_load(&rbtdb->last_used) && + purged <= purgesize; + header = header_prev) { header_prev = ISC_LIST_PREV(header, link); /* @@ -10171,30 +10244,58 @@ expire_lru_headers(dns_rbtdb_t *rbtdb, unsigned int locknum, size_t purgesize, * entries under the overmem condition. To recover from this condition quickly, * we cleanup entries up to the size of newly added rdata (passed as purgesize). * - * This process is triggered while adding a new entry, and we specifically avoid - * purging entries in the same LRU bucket as the one to which the new entry will - * belong. Otherwise, we might purge entries of the same name of different RR - * types while adding RRsets from a single response (consider the case where - * we're adding A and AAAA glue records of the same NS name). + * The LRU lists tails are processed in LRU order to the nearest second. + * + * A write lock on the tree must be held. */ static void -overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, size_t purgesize, +overmem_purge(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader, bool tree_locked) { - unsigned int locknum; + uint32_t locknum_start = atomic_fetch_add(&rbtdb->lru_sweep, 1) % + rbtdb->node_lock_count; + uint32_t locknum = locknum_start; + /* Size of added data, possible node and possible ENT node. */ + size_t purgesize = rdataset_size(newheader) + + 2 * dns__rbtnode_getsize(newheader->node); size_t purged = 0; + isc_stdtime_t min_last_used = 0; + size_t max_passes = 8; - for (locknum = (locknum_start + 1) % rbtdb->node_lock_count; - locknum != locknum_start && purged <= purgesize; - locknum = (locknum + 1) % rbtdb->node_lock_count) - { +again: + do { NODE_LOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write); purged += expire_lru_headers(rbtdb, locknum, purgesize - purged, tree_locked); + /* + * Work out the oldest remaining last_used values of the list + * tails as we walk across the array of lru lists. + */ + rdatasetheader_t *header = + ISC_LIST_TAIL(rbtdb->rdatasets[locknum]); + if (header != NULL && + (min_last_used == 0 || header->last_used < min_last_used)) + { + min_last_used = header->last_used; + } NODE_UNLOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write); + locknum = (locknum + 1) % rbtdb->node_lock_count; + } while (locknum != locknum_start && purged <= purgesize); + + /* + * Update rbtdb->last_used if we have walked all the list tails and have + * not freed the required amount of memory. + */ + if (purged < purgesize) { + if (min_last_used != 0) { + atomic_store(&rbtdb->last_used, min_last_used); + if (max_passes-- > 0) { + goto again; + } + } } } diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index b7f9ed2..592b974 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -2059,7 +2059,7 @@ decvalue(char value) { * isascii() is valid for full range of int values, no need to * mask or cast. */ - if (!isascii(value)) { + if (!isascii((unsigned char)value)) { return (-1); } if ((s = strchr(decdigits, value)) == NULL) { diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 66bb1ac..60cac29 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -2139,10 +2139,13 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, INSIST(ISC_LIST_EMPTY(fctx->validators)); query = isc_mem_get(fctx->mctx, sizeof(*query)); - *query = (resquery_t){ .mctx = fctx->mctx, - .options = options, - .addrinfo = addrinfo, - .dispatchmgr = res->dispatchmgr }; + *query = (resquery_t){ + .mctx = fctx->mctx, + .options = options, + .addrinfo = addrinfo, + .dispatchmgr = res->dispatchmgr, + .link = ISC_LINK_INITIALIZER, + }; isc_refcount_init(&query->references, 1); @@ -2247,7 +2250,6 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, } fctx_attach(fctx, &query->fctx); - ISC_LINK_INIT(query, link); query->magic = QUERY_MAGIC; if ((query->options & DNS_FETCHOPT_TCP) == 0) { @@ -2291,6 +2293,13 @@ cleanup_udpfetch: } } + LOCK(&res->buckets[fctx->bucketnum].lock); + if (ISC_LINK_LINKED(query, link)) { + atomic_fetch_sub_release(&fctx->nqueries, 1); + ISC_LIST_UNLINK(fctx->queries, query, link); + } + UNLOCK(&res->buckets[fctx->bucketnum].lock); + cleanup_dispatch: fctx_detach(&query->fctx); @@ -2299,13 +2308,6 @@ cleanup_dispatch: } cleanup_query: - LOCK(&res->buckets[fctx->bucketnum].lock); - if (ISC_LINK_LINKED(query, link)) { - atomic_fetch_sub_release(&fctx->nqueries, 1); - ISC_LIST_UNLINK(fctx->queries, query, link); - } - UNLOCK(&res->buckets[fctx->bucketnum].lock); - query->magic = 0; dns_message_detach(&query->rmessage); isc_mem_put(fctx->mctx, query, sizeof(*query)); @@ -10406,8 +10408,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) { ntasks = i; isc_mutex_destroy(&res->buckets[i].lock); diff --git a/lib/dns/rootns.c b/lib/dns/rootns.c index 9a61587..1b8b937 100644 --- a/lib/dns/rootns.c +++ b/lib/dns/rootns.c @@ -34,6 +34,9 @@ #include #include +/* + * Also update 'upcoming' when updating 'root_ns'. + */ static char root_ns[] = ";\n" "; Internet Root Nameservers\n" @@ -54,8 +57,8 @@ static char root_ns[] = ". 518400 IN NS M.ROOT-SERVERS.NET.\n" "A.ROOT-SERVERS.NET. 3600000 IN A 198.41.0.4\n" "A.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:503:BA3E::2:30\n" - "B.ROOT-SERVERS.NET. 3600000 IN A 199.9.14.201\n" - "B.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:200::b\n" + "B.ROOT-SERVERS.NET. 3600000 IN A 170.247.170.2\n" + "B.ROOT-SERVERS.NET. 3600000 IN AAAA 2801:1b8:10::b\n" "C.ROOT-SERVERS.NET. 3600000 IN A 192.33.4.12\n" "C.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:2::c\n" "D.ROOT-SERVERS.NET. 3600000 IN A 199.7.91.13\n" @@ -79,6 +82,24 @@ static char root_ns[] = "M.ROOT-SERVERS.NET. 3600000 IN A 202.12.27.33\n" "M.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:DC3::35\n"; +static unsigned char b_data[] = "\001b\014root-servers\003net"; +static unsigned char b_offsets[] = { 0, 2, 15, 19 }; + +static struct upcoming { + const dns_name_t name; + dns_rdatatype_t type; + isc_stdtime_t time; +} upcoming[] = { { + .name = DNS_NAME_INITABSOLUTE(b_data, b_offsets), + .type = dns_rdatatype_a, + .time = 1701086400 /* November 27 2023, 12:00 UTC */ + }, + { + .name = DNS_NAME_INITABSOLUTE(b_data, b_offsets), + .type = dns_rdatatype_aaaa, + .time = 1701086400 /* November 27 2023, 12:00 UTC */ + } }; + static isc_result_t in_rootns(dns_rdataset_t *rootns, dns_name_t *name) { isc_result_t result; @@ -337,6 +358,18 @@ inrrset(dns_rdataset_t *rrset, dns_rdata_t *rdata) { return (false); } +static bool +changing(const dns_name_t *name, dns_rdatatype_t type, isc_stdtime_t now) { + for (size_t i = 0; i < ARRAY_SIZE(upcoming); i++) { + if (upcoming[i].time > now && upcoming[i].type == type && + dns_name_equal(&upcoming[i].name, name)) + { + return (true); + } + } + return (false); +} + /* * Check that the address RRsets match. * @@ -368,7 +401,9 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db, while (result == ISC_R_SUCCESS) { dns_rdata_reset(&rdata); dns_rdataset_current(&rootrrset, &rdata); - if (!inrrset(&hintrrset, &rdata)) { + if (!inrrset(&hintrrset, &rdata) && + !changing(name, dns_rdatatype_a, now)) + { report(view, name, true, &rdata); } result = dns_rdataset_next(&rootrrset); @@ -377,7 +412,9 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db, while (result == ISC_R_SUCCESS) { dns_rdata_reset(&rdata); dns_rdataset_current(&hintrrset, &rdata); - if (!inrrset(&rootrrset, &rdata)) { + if (!inrrset(&rootrrset, &rdata) && + !changing(name, dns_rdatatype_a, now)) + { report(view, name, false, &rdata); } result = dns_rdataset_next(&hintrrset); @@ -416,7 +453,9 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db, while (result == ISC_R_SUCCESS) { dns_rdata_reset(&rdata); dns_rdataset_current(&rootrrset, &rdata); - if (!inrrset(&hintrrset, &rdata)) { + if (!inrrset(&hintrrset, &rdata) && + !changing(name, dns_rdatatype_aaaa, now)) + { report(view, name, true, &rdata); } dns_rdata_reset(&rdata); @@ -426,7 +465,9 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db, while (result == ISC_R_SUCCESS) { dns_rdata_reset(&rdata); dns_rdataset_current(&hintrrset, &rdata); - if (!inrrset(&rootrrset, &rdata)) { + if (!inrrset(&rootrrset, &rdata) && + !changing(name, dns_rdatatype_aaaa, now)) + { report(view, name, false, &rdata); } dns_rdata_reset(&rdata); diff --git a/lib/dns/stats.c b/lib/dns/stats.c index 390a397..238efac 100644 --- a/lib/dns/stats.c +++ b/lib/dns/stats.c @@ -367,11 +367,12 @@ void dns_dnssecsignstats_increment(dns_stats_t *stats, dns_keytag_t id, uint8_t alg, dnssecsignstats_type_t operation) { uint32_t kval; - int num_keys = isc_stats_ncounters(stats->counters) / - dnssecsign_block_size; REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_dnssec); + int num_keys = isc_stats_ncounters(stats->counters) / + dnssecsign_block_size; + /* Shift algorithm in front of key tag, which is 16 bits */ kval = (uint32_t)(alg << 16 | id); @@ -414,11 +415,12 @@ dns_dnssecsignstats_increment(dns_stats_t *stats, dns_keytag_t id, uint8_t alg, void dns_dnssecsignstats_clear(dns_stats_t *stats, dns_keytag_t id, uint8_t alg) { uint32_t kval; - int num_keys = isc_stats_ncounters(stats->counters) / - dnssecsign_block_size; REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_dnssec); + int num_keys = isc_stats_ncounters(stats->counters) / + dnssecsign_block_size; + /* Shift algorithm in front of key tag, which is 16 bits */ kval = (uint32_t)(alg << 16 | id); diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c index 857ec4c..8f96008 100644 --- a/lib/dns/tsig.c +++ b/lib/dns/tsig.c @@ -1757,8 +1757,9 @@ isc_result_t dns_tsigkey_find(dns_tsigkey_t **tsigkey, const dns_name_t *name, const dns_name_t *algorithm, dns_tsig_keyring_t *ring) { dns_tsigkey_t *key; - isc_stdtime_t now; isc_result_t result; + isc_rwlocktype_t locktype = isc_rwlocktype_read; + isc_stdtime_t now; REQUIRE(tsigkey != NULL); REQUIRE(*tsigkey == NULL); @@ -1770,25 +1771,30 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, const dns_name_t *name, RWUNLOCK(&ring->lock, isc_rwlocktype_write); isc_stdtime_get(&now); - RWLOCK(&ring->lock, isc_rwlocktype_read); + +again: + RWLOCK(&ring->lock, locktype); key = NULL; result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key); if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) { - RWUNLOCK(&ring->lock, isc_rwlocktype_read); + RWUNLOCK(&ring->lock, locktype); return (ISC_R_NOTFOUND); } if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) { - RWUNLOCK(&ring->lock, isc_rwlocktype_read); + RWUNLOCK(&ring->lock, locktype); return (ISC_R_NOTFOUND); } if (key->inception != key->expire && isc_serial_lt(key->expire, now)) { /* * The key has expired. */ - RWUNLOCK(&ring->lock, isc_rwlocktype_read); - RWLOCK(&ring->lock, isc_rwlocktype_write); + if (locktype == isc_rwlocktype_read) { + RWUNLOCK(&ring->lock, locktype); + locktype = isc_rwlocktype_write; + goto again; + } remove_fromring(key); - RWUNLOCK(&ring->lock, isc_rwlocktype_write); + RWUNLOCK(&ring->lock, locktype); return (ISC_R_NOTFOUND); } #if 0 @@ -1803,7 +1809,7 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, const dns_name_t *name, } #endif /* if 0 */ isc_refcount_increment(&key->refs); - RWUNLOCK(&ring->lock, isc_rwlocktype_read); + RWUNLOCK(&ring->lock, locktype); adjust_lru(key); *tsigkey = key; return (ISC_R_SUCCESS); diff --git a/lib/dns/update.c b/lib/dns/update.c index 13fd05b..c3f162a 100644 --- a/lib/dns/update.c +++ b/lib/dns/update.c @@ -1089,8 +1089,8 @@ static isc_result_t add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys, - isc_stdtime_t inception, isc_stdtime_t expire, bool check_ksk, - bool keyset_kskonly) { + isc_stdtime_t now, isc_stdtime_t inception, isc_stdtime_t expire, + bool check_ksk, bool keyset_kskonly) { isc_result_t result; dns_dbnode_t *node = NULL; dns_kasp_t *kasp = dns_zone_getkasp(zone); @@ -1223,7 +1223,7 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, continue; } else if (zsk && !dst_key_is_signing(keys[i], DST_BOOL_ZSK, - inception, &when)) + now, &when)) { /* * This key is not active for zone-signing. @@ -1381,8 +1381,9 @@ static isc_result_t add_exposed_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, bool cut, dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys, - isc_stdtime_t inception, isc_stdtime_t expire, bool check_ksk, - bool keyset_kskonly, unsigned int *sigs) { + isc_stdtime_t now, isc_stdtime_t inception, + isc_stdtime_t expire, bool check_ksk, bool keyset_kskonly, + unsigned int *sigs) { isc_result_t result; dns_dbnode_t *node; dns_rdatasetiter_t *iter; @@ -1432,7 +1433,7 @@ add_exposed_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, continue; } result = add_sigs(log, zone, db, ver, name, type, diff, keys, - nkeys, inception, expire, check_ksk, + nkeys, now, inception, expire, check_ksk, keyset_kskonly); if (result != ISC_R_SUCCESS) { goto cleanup_iterator; @@ -1481,7 +1482,7 @@ struct dns_update_state { dns_diff_t work; dst_key_t *zone_keys[DNS_MAXZONEKEYS]; unsigned int nkeys; - isc_stdtime_t inception, expire, soaexpire, keyexpire; + isc_stdtime_t now, inception, expire, soaexpire, keyexpire; dns_ttl_t nsecttl; bool check_ksk, keyset_kskonly, build_nsec3; enum { @@ -1527,7 +1528,6 @@ dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, dns_difftuple_t *t, *next; bool flag, build_nsec; unsigned int i; - isc_stdtime_t now; dns_rdata_soa_t soa; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdataset_t rdataset; @@ -1564,16 +1564,17 @@ dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, goto failure; } - isc_stdtime_get(&now); - state->inception = now - 3600; /* Allow for some clock skew. */ - state->expire = now + + isc_stdtime_get(&state->now); + state->inception = state->now - 3600; /* Allow for some clock + skew. */ + state->expire = state->now + dns__jitter_expire(zone, sigvalidityinterval); - state->soaexpire = now + sigvalidityinterval; + state->soaexpire = state->now + sigvalidityinterval; state->keyexpire = dns_zone_getkeyvalidityinterval(zone); if (state->keyexpire == 0) { state->keyexpire = state->expire; } else { - state->keyexpire += now; + state->keyexpire += state->now; } /* @@ -1689,8 +1690,8 @@ next_state: log, zone, db, newver, name, type, &state->sig_diff, state->zone_keys, state->nkeys, - state->inception, exp, - state->check_ksk, + state->now, state->inception, + exp, state->check_ksk, state->keyset_kskonly)); sigs++; } @@ -1892,9 +1893,10 @@ next_state: CHECK(add_exposed_sigs( log, zone, db, newver, name, cut, &state->sig_diff, state->zone_keys, - state->nkeys, state->inception, - state->expire, state->check_ksk, - state->keyset_kskonly, &sigs)); + state->nkeys, state->now, + state->inception, state->expire, + state->check_ksk, state->keyset_kskonly, + &sigs)); } unlink: ISC_LIST_UNLINK(state->affected.tuples, t, link); @@ -1970,8 +1972,8 @@ next_state: dns_rdatatype_nsec, &state->sig_diff, state->zone_keys, state->nkeys, - state->inception, state->expire, - state->check_ksk, + state->now, state->inception, + state->expire, state->check_ksk, state->keyset_kskonly)); sigs++; } else { @@ -2099,9 +2101,10 @@ next_state: CHECK(add_exposed_sigs( log, zone, db, newver, name, cut, &state->sig_diff, state->zone_keys, - state->nkeys, state->inception, - state->expire, state->check_ksk, - state->keyset_kskonly, &sigs)); + state->nkeys, state->now, + state->inception, state->expire, + state->check_ksk, state->keyset_kskonly, + &sigs)); CHECK(dns_nsec3_addnsec3sx( db, newver, name, state->nsecttl, unsecure, privatetype, @@ -2145,8 +2148,8 @@ next_state: dns_rdatatype_nsec3, &state->sig_diff, state->zone_keys, state->nkeys, - state->inception, state->expire, - state->check_ksk, + state->now, state->inception, + state->expire, state->check_ksk, state->keyset_kskonly)); sigs++; } else { diff --git a/lib/dns/validator.c b/lib/dns/validator.c index 56a0ced..47c4813 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/dns/xfrin.c b/lib/dns/xfrin.c index 393b557..1aa982a 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -1143,7 +1143,24 @@ get_create_tlsctx(const dns_xfrin_ctx_t *xfr, isc_tlsctx_t **pctx, */ INSIST(found != NULL); isc_tlsctx_free(&tlsctx); - isc_tls_cert_store_free(&store); + /* + * The 'store' variable can be 'NULL' when remote server + * verification is not enabled (that is, when Strict or + * Mutual TLS are not used). + * + * The 'found_store' might be equal to 'store' as there + * is one-to-many relation between a store and + * per-transport TLS contexts. In that case, the call to + * 'isc_tlsctx_cache_find()' above could have returned a + * store via the 'found_store' variable, whose value we + * can assign to 'store' later. In that case, + * 'isc_tlsctx_cache_add()' will return the same value. + * When that happens, we should not free the store + * object, as it is managed by the TLS context cache. + */ + if (store != NULL && store != found_store) { + isc_tls_cert_store_free(&store); + } isc_tlsctx_client_session_cache_detach(&sess_cache); /* Let's return the data from the cache. */ *psess_cache = found_sess_cache; diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 4428e3d..729adcb 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -126,7 +126,7 @@ */ #define RANGE(a, min, max) (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max))) -#define NSEC3REMOVE(x) (((x)&DNS_NSEC3FLAG_REMOVE) != 0) +#define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0) /*% * Key flags @@ -3971,15 +3971,11 @@ set_resigntime(dns_zone_t *zone) { INSIST(LOCKED_ZONE(zone)); /* We only re-sign zones that can be dynamically updated */ - if (zone->update_disabled) { + if (!dns_zone_isdynamic(zone, false)) { return; } - if (!inline_secure(zone) && - (zone->type != dns_zone_primary || - (zone->ssutable == NULL && - (zone->update_acl == NULL || dns_acl_isnone(zone->update_acl))))) - { + if (inline_raw(zone)) { return; } @@ -5330,7 +5326,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, is_dynamic = dns_zone_isdynamic(zone, false); if (zone->type == dns_zone_primary && !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) && - is_dynamic && dns_db_issecure(db)) + is_dynamic && dns_db_issecure(db) && !inline_raw(zone)) { dns_name_t *name; dns_fixedname_t fixed; @@ -6931,8 +6927,9 @@ failure: static isc_result_t add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone, dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys, - unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception, - isc_stdtime_t expire, bool check_ksk, bool keyset_kskonly) { + unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t now, + isc_stdtime_t inception, isc_stdtime_t expire, bool check_ksk, + bool keyset_kskonly) { isc_result_t result; dns_dbnode_t *node = NULL; dns_stats_t *dnssecsignstats; @@ -7124,7 +7121,7 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone, continue; } } else if (!dst_key_is_signing(keys[i], DST_BOOL_ZSK, - inception, &when)) + now, &when)) { /* * This key is not active for zone-signing. @@ -7343,7 +7340,7 @@ zone_resigninc(dns_zone_t *zone) { */ result = add_sigs(db, version, name, zone, covers, zonediff.diff, zone_keys, nkeys, zone->mctx, - inception, + now, inception, resign > (now - 300) ? expire : fullexpire, check_ksk, keyset_kskonly); if (result != ISC_R_SUCCESS) { @@ -7406,7 +7403,7 @@ zone_resigninc(dns_zone_t *zone) { * termination is sensible. */ result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa, - zonediff.diff, zone_keys, nkeys, zone->mctx, + zonediff.diff, zone_keys, nkeys, zone->mctx, now, inception, soaexpire, check_ksk, keyset_kskonly); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, @@ -7642,10 +7639,11 @@ failure: static isc_result_t sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name, dns_dbnode_t *node, dns_dbversion_t *version, bool build_nsec3, - bool build_nsec, dst_key_t *key, isc_stdtime_t inception, - isc_stdtime_t expire, dns_ttl_t nsecttl, bool is_ksk, bool is_zsk, - bool keyset_kskonly, bool is_bottom_of_zone, dns_diff_t *diff, - int32_t *signatures, isc_mem_t *mctx) { + bool build_nsec, dst_key_t *key, isc_stdtime_t now, + isc_stdtime_t inception, isc_stdtime_t expire, dns_ttl_t nsecttl, + bool is_ksk, bool is_zsk, bool keyset_kskonly, + bool is_bottom_of_zone, dns_diff_t *diff, int32_t *signatures, + isc_mem_t *mctx) { isc_result_t result; dns_rdatasetiter_t *iterator = NULL; dns_rdataset_t rdataset; @@ -7740,8 +7738,8 @@ sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name, } } else if (!is_zsk) { goto next_rdataset; - } else if (is_zsk && !dst_key_is_signing(key, DST_BOOL_ZSK, - inception, &when)) + } else if (is_zsk && + !dst_key_is_signing(key, DST_BOOL_ZSK, now, &when)) { /* Only applies to dnssec-policy. */ if (dns_zone_getkasp(zone) != NULL) { @@ -8344,8 +8342,8 @@ dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version, } result = add_sigs(db, version, &tuple->name, zone, tuple->rdata.type, zonediff->diff, zone_keys, - nkeys, zone->mctx, inception, exp, check_ksk, - keyset_kskonly); + nkeys, zone->mctx, now, inception, exp, + check_ksk, keyset_kskonly); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, "dns__zone_updatesigs:add_sigs -> %s", @@ -9119,7 +9117,7 @@ skip_removals: } result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa, - zonediff.diff, zone_keys, nkeys, zone->mctx, + zonediff.diff, zone_keys, nkeys, zone->mctx, now, inception, soaexpire, check_ksk, keyset_kskonly); if (result != ISC_R_SUCCESS) { dnssec_log(zone, ISC_LOG_ERROR, @@ -9659,16 +9657,7 @@ zone_sign(dns_zone_t *zone) { if (ALG(zone_keys[i]) == signing->algorithm && dst_key_id(zone_keys[i]) == signing->keyid) { - bool ksk = false; - isc_result_t ret = dst_key_getbool( - zone_keys[i], DST_BOOL_KSK, - &ksk); - if (ret != ISC_R_SUCCESS) { - ksk = KSK(zone_keys[i]); - } - if (ksk) { - dst_key_free(&zone_keys[i]); - } + dst_key_free(&zone_keys[i]); continue; } zone_keys[j] = zone_keys[i]; @@ -9848,8 +9837,8 @@ zone_sign(dns_zone_t *zone) { CHECK(sign_a_node( db, zone, name, node, version, build_nsec3, - build_nsec, zone_keys[i], inception, expire, - zone_nsecttl(zone), is_ksk, is_zsk, + build_nsec, zone_keys[i], now, inception, + expire, zone_nsecttl(zone), is_ksk, is_zsk, (both && keyset_kskonly), is_bottom_of_zone, zonediff.diff, &signatures, zone->mctx)); /* @@ -9984,7 +9973,7 @@ zone_sign(dns_zone_t *zone) { * termination is sensible. */ result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa, - zonediff.diff, zone_keys, nkeys, zone->mctx, + zonediff.diff, zone_keys, nkeys, zone->mctx, now, inception, soaexpire, check_ksk, keyset_kskonly); if (result != ISC_R_SUCCESS) { dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:add_sigs -> %s", @@ -12705,14 +12694,14 @@ notify_send_toaddr(isc_task_t *task, isc_event_t *event) { result = ISC_R_NOTIMPLEMENTED; goto cleanup_key; } - timeout = 15; + timeout = 5; if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY)) { timeout = 30; } - result = dns_request_create(notify->zone->view->requestmgr, message, - &src, ¬ify->dst, options, key, - timeout * 3, timeout, 2, notify->zone->task, - notify_done, notify, ¬ify->request); + result = dns_request_create( + notify->zone->view->requestmgr, message, &src, ¬ify->dst, + options, key, timeout * 3 + 1, timeout, 2, notify->zone->task, + notify_done, notify, ¬ify->request); if (result == ISC_R_SUCCESS) { if (isc_sockaddr_pf(¬ify->dst) == AF_INET) { inc_stats(notify->zone, @@ -14672,13 +14661,13 @@ again: } zone_iattach(zone, &dummy); - timeout = 15; + timeout = 5; if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) { timeout = 30; } result = dns_request_create( zone->view->requestmgr, message, &zone->sourceaddr, - &zone->primaryaddr, options, key, timeout * 3, timeout, 2, + &zone->primaryaddr, options, key, timeout * 3 + 1, timeout, 2, zone->task, refresh_callback, zone, &zone->request); if (result != ISC_R_SUCCESS) { zone_idetach(&dummy); @@ -14928,7 +14917,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { POST(result); goto cleanup; } - timeout = 15; + timeout = 5; if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) { timeout = 30; } @@ -14946,7 +14935,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { result = dns_request_create( zone->view->requestmgr, message, &zone->sourceaddr, - &zone->primaryaddr, DNS_REQUESTOPT_TCP, key, timeout * 3, + &zone->primaryaddr, DNS_REQUESTOPT_TCP, key, timeout * 3 + 1, timeout, 2, zone->task, stub_callback, cb_args, &zone->request); if (result != ISC_R_SUCCESS) { zone_debuglog(zone, me, 1, "dns_request_create() failed: %s", @@ -17666,6 +17655,12 @@ again: DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime); } + + /* + * Set loadtime. + */ + zone->loadtime = now; + if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) { char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")]; if (zone->tsigkey != NULL) { @@ -20490,7 +20485,7 @@ tickle_apex_rrset(dns_rdatatype_t rrtype, dns_zone_t *zone, dns_db_t *db, return (result); } result = add_sigs(db, ver, &zone->origin, zone, rrtype, - zonediff->diff, keys, nkeys, zone->mctx, + zonediff->diff, keys, nkeys, zone->mctx, now, inception, keyexpire, check_ksk, keyset_kskonly); if (result != ISC_R_SUCCESS) { @@ -21252,11 +21247,11 @@ checkds_send_toaddr(isc_task_t *task, isc_event_t *event) { dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3), "checkds: create request for DS query to %s", addrbuf); - timeout = 15; + timeout = 5; options |= DNS_REQUESTOPT_TCP; result = dns_request_create( checkds->zone->view->requestmgr, message, &src, &checkds->dst, - options, key, timeout * 3, timeout, 2, checkds->zone->task, + options, key, timeout * 3 + 1, timeout, 2, checkds->zone->task, checkds_done, checkds, &checkds->request); if (result != ISC_R_SUCCESS) { dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3), -- cgit v1.2.3