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/Makefile.in | 2 - lib/bind9/Makefile.in | 2 - lib/bind9/check.c | 4 + 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 +++++----- lib/irs/Makefile.in | 2 - lib/isc/Makefile.in | 2 - lib/isc/hmac.c | 65 +++---- lib/isc/ht.c | 55 +++++- lib/isc/httpd.c | 6 +- lib/isc/include/isc/endian.h | 34 ++-- lib/isc/include/isc/net.h | 4 +- lib/isc/include/isc/netmgr.h | 3 + lib/isc/include/isc/radix.h | 2 +- lib/isc/include/isc/types.h | 10 +- lib/isc/mem.c | 11 ++ lib/isc/mem_p.h | 11 ++ lib/isc/netaddr.c | 2 +- lib/isc/netmgr/http.c | 19 +- lib/isc/netmgr/netmgr-int.h | 1 + lib/isc/netmgr/netmgr.c | 38 ++-- lib/isc/netmgr/tcp.c | 6 +- lib/isc/netmgr/tcpdns.c | 11 +- lib/isc/netmgr/tlsdns.c | 11 +- lib/isc/netmgr/tlsstream.c | 12 +- lib/isc/netmgr/udp.c | 10 +- lib/isc/netmgr/uv-compat.h | 2 +- lib/isc/stats.c | 25 ++- lib/isc/trampoline.c | 5 +- lib/isc/url.c | 5 +- lib/isccc/Makefile.in | 2 - lib/isccc/cc.c | 18 +- lib/isccfg/Makefile.in | 2 - lib/isccfg/namedconf.c | 9 +- lib/ns/Makefile.in | 2 - lib/ns/client.c | 34 +--- lib/ns/query.c | 46 +++-- lib/ns/xfrout.c | 2 +- 68 files changed, 1042 insertions(+), 634 deletions(-) (limited to 'lib') diff --git a/lib/Makefile.in b/lib/Makefile.in index 9a6f85c..9e568e5 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -102,11 +102,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/bind9/Makefile.in b/lib/bind9/Makefile.in index cf12ed5..a7bef71 100644 --- a/lib/bind9/Makefile.in +++ b/lib/bind9/Makefile.in @@ -105,11 +105,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/bind9/check.c b/lib/bind9/check.c index 695090e..1c850d8 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -1608,6 +1608,10 @@ check_options(const cfg_obj_t *options, const cfg_obj_t *config, (void)cfg_map_get(options, "cookie-algorithm", &obj); if (obj != NULL) { ccalg = cfg_obj_asstring(obj); + if (strcasecmp(ccalg, "aes") == 0) { + cfg_obj_log(obj, logctx, ISC_LOG_WARNING, + "cookie-algorithm 'aes' is deprecated"); + } } obj = NULL; 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), diff --git a/lib/irs/Makefile.in b/lib/irs/Makefile.in index 66b3575..b73a9b1 100644 --- a/lib/irs/Makefile.in +++ b/lib/irs/Makefile.in @@ -104,11 +104,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/isc/Makefile.in b/lib/isc/Makefile.in index 50ec06e..8b8d16b 100644 --- a/lib/isc/Makefile.in +++ b/lib/isc/Makefile.in @@ -132,11 +132,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/isc/hmac.c b/lib/isc/hmac.c index bc35bef..4bce2c8 100644 --- a/lib/isc/hmac.c +++ b/lib/isc/hmac.c @@ -27,26 +27,26 @@ isc_hmac_t * isc_hmac_new(void) { - EVP_MD_CTX *hmac = EVP_MD_CTX_new(); - RUNTIME_CHECK(hmac != NULL); - return ((isc_hmac_t *)hmac); + EVP_MD_CTX *hmac_st = EVP_MD_CTX_new(); + RUNTIME_CHECK(hmac_st != NULL); + return ((isc_hmac_t *)hmac_st); } void -isc_hmac_free(isc_hmac_t *hmac) { - if (hmac == NULL) { +isc_hmac_free(isc_hmac_t *hmac_st) { + if (hmac_st == NULL) { return; } - EVP_MD_CTX_free((EVP_MD_CTX *)hmac); + EVP_MD_CTX_free((EVP_MD_CTX *)hmac_st); } isc_result_t -isc_hmac_init(isc_hmac_t *hmac, const void *key, const size_t keylen, +isc_hmac_init(isc_hmac_t *hmac_st, const void *key, const size_t keylen, const isc_md_type_t *md_type) { EVP_PKEY *pkey; - REQUIRE(hmac != NULL); + REQUIRE(hmac_st != NULL); REQUIRE(key != NULL); REQUIRE(keylen <= INT_MAX); @@ -60,7 +60,7 @@ isc_hmac_init(isc_hmac_t *hmac, const void *key, const size_t keylen, return (ISC_R_CRYPTOFAILURE); } - if (EVP_DigestSignInit(hmac, NULL, md_type, NULL, pkey) != 1) { + if (EVP_DigestSignInit(hmac_st, NULL, md_type, NULL, pkey) != 1) { EVP_PKEY_free(pkey); ERR_clear_error(); return (ISC_R_CRYPTOFAILURE); @@ -72,10 +72,10 @@ isc_hmac_init(isc_hmac_t *hmac, const void *key, const size_t keylen, } isc_result_t -isc_hmac_reset(isc_hmac_t *hmac) { - REQUIRE(hmac != NULL); +isc_hmac_reset(isc_hmac_t *hmac_st) { + REQUIRE(hmac_st != NULL); - if (EVP_MD_CTX_reset(hmac) != 1) { + if (EVP_MD_CTX_reset(hmac_st) != 1) { ERR_clear_error(); return (ISC_R_CRYPTOFAILURE); } @@ -84,14 +84,15 @@ isc_hmac_reset(isc_hmac_t *hmac) { } isc_result_t -isc_hmac_update(isc_hmac_t *hmac, const unsigned char *buf, const size_t len) { - REQUIRE(hmac != NULL); +isc_hmac_update(isc_hmac_t *hmac_st, const unsigned char *buf, + const size_t len) { + REQUIRE(hmac_st != NULL); if (buf == NULL || len == 0) { return (ISC_R_SUCCESS); } - if (EVP_DigestSignUpdate(hmac, buf, len) != 1) { + if (EVP_DigestSignUpdate(hmac_st, buf, len) != 1) { ERR_clear_error(); return (ISC_R_CRYPTOFAILURE); } @@ -100,15 +101,15 @@ isc_hmac_update(isc_hmac_t *hmac, const unsigned char *buf, const size_t len) { } isc_result_t -isc_hmac_final(isc_hmac_t *hmac, unsigned char *digest, +isc_hmac_final(isc_hmac_t *hmac_st, unsigned char *digest, unsigned int *digestlen) { - REQUIRE(hmac != NULL); + REQUIRE(hmac_st != NULL); REQUIRE(digest != NULL); REQUIRE(digestlen != NULL); size_t len = *digestlen; - if (EVP_DigestSignFinal(hmac, digest, &len) != 1) { + if (EVP_DigestSignFinal(hmac_st, digest, &len) != 1) { ERR_clear_error(); return (ISC_R_CRYPTOFAILURE); } @@ -119,24 +120,24 @@ isc_hmac_final(isc_hmac_t *hmac, unsigned char *digest, } const isc_md_type_t * -isc_hmac_get_md_type(isc_hmac_t *hmac) { - REQUIRE(hmac != NULL); +isc_hmac_get_md_type(isc_hmac_t *hmac_st) { + REQUIRE(hmac_st != NULL); - return (EVP_MD_CTX_get0_md(hmac)); + return (EVP_MD_CTX_get0_md(hmac_st)); } size_t -isc_hmac_get_size(isc_hmac_t *hmac) { - REQUIRE(hmac != NULL); +isc_hmac_get_size(isc_hmac_t *hmac_st) { + REQUIRE(hmac_st != NULL); - return ((size_t)EVP_MD_CTX_size(hmac)); + return ((size_t)EVP_MD_CTX_size(hmac_st)); } int -isc_hmac_get_block_size(isc_hmac_t *hmac) { - REQUIRE(hmac != NULL); +isc_hmac_get_block_size(isc_hmac_t *hmac_st) { + REQUIRE(hmac_st != NULL); - return (EVP_MD_CTX_block_size(hmac)); + return (EVP_MD_CTX_block_size(hmac_st)); } isc_result_t @@ -144,24 +145,24 @@ isc_hmac(const isc_md_type_t *type, const void *key, const size_t keylen, const unsigned char *buf, const size_t len, unsigned char *digest, unsigned int *digestlen) { isc_result_t res; - isc_hmac_t *hmac = isc_hmac_new(); + isc_hmac_t *hmac_st = isc_hmac_new(); - res = isc_hmac_init(hmac, key, keylen, type); + res = isc_hmac_init(hmac_st, key, keylen, type); if (res != ISC_R_SUCCESS) { goto end; } - res = isc_hmac_update(hmac, buf, len); + res = isc_hmac_update(hmac_st, buf, len); if (res != ISC_R_SUCCESS) { goto end; } - res = isc_hmac_final(hmac, digest, digestlen); + res = isc_hmac_final(hmac_st, digest, digestlen); if (res != ISC_R_SUCCESS) { goto end; } end: - isc_hmac_free(hmac); + isc_hmac_free(hmac_st); return (res); } diff --git a/lib/isc/ht.c b/lib/isc/ht.c index eaf2b3c..e11050f 100644 --- a/lib/isc/ht.c +++ b/lib/isc/ht.c @@ -93,11 +93,54 @@ maybe_rehash(isc_ht_t *ht, size_t newcount); static isc_result_t isc__ht_iter_next(isc_ht_iter_t *it); +static uint8_t maptolower[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, + 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, + 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, + 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, + 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, + 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, + 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, + 0xfc, 0xfd, 0xfe, 0xff +}; + +static int +memcasecmp(const void *vs1, const void *vs2, size_t len) { + uint8_t const *s1 = vs1; + uint8_t const *s2 = vs2; + for (size_t i = 0; i < len; i++) { + uint8_t u1 = s1[i]; + uint8_t u2 = s2[i]; + int U1 = maptolower[u1]; + int U2 = maptolower[u2]; + int diff = U1 - U2; + if (diff) { + return diff; + } + } + return 0; +} + static bool isc__ht_node_match(isc_ht_node_t *node, const uint32_t hashval, - const uint8_t *key, uint32_t keysize) { + const uint8_t *key, uint32_t keysize, bool case_sensitive) { return (node->hashval == hashval && node->keysize == keysize && - memcmp(node->key, key, keysize) == 0); + (case_sensitive ? (memcmp(node->key, key, keysize) == 0) + : (memcasecmp(node->key, key, keysize) == 0))); } static uint32_t @@ -341,7 +384,9 @@ nexttable: for (isc_ht_node_t *node = ht->table[findex][hash]; node != NULL; node = node->next) { - if (isc__ht_node_match(node, hashval, key, keysize)) { + if (isc__ht_node_match(node, hashval, key, keysize, + ht->case_sensitive)) + { return (node); } } @@ -390,7 +435,9 @@ isc__ht_delete(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize, for (isc_ht_node_t *node = ht->table[idx][hash]; node != NULL; prev = node, node = node->next) { - if (isc__ht_node_match(node, hashval, key, keysize)) { + if (isc__ht_node_match(node, hashval, key, keysize, + ht->case_sensitive)) + { if (prev == NULL) { ht->table[idx][hash] = node->next; } else { diff --git a/lib/isc/httpd.c b/lib/isc/httpd.c index b15cc45..a93f9e1 100644 --- a/lib/isc/httpd.c +++ b/lib/isc/httpd.c @@ -340,8 +340,10 @@ value_match(const struct phr_header *header, const char *match) { limit = header->value_len - match_len + 1; for (size_t i = 0; i < limit; i++) { - if (isspace(header->value[i])) { - while (i < limit && isspace(header->value[i])) { + if (isspace((unsigned char)header->value[i])) { + while (i < limit && + isspace((unsigned char)header->value[i])) + { i++; } continue; diff --git a/lib/isc/include/isc/endian.h b/lib/isc/include/isc/endian.h index be91b1d..2590415 100644 --- a/lib/isc/include/isc/endian.h +++ b/lib/isc/include/isc/endian.h @@ -86,29 +86,29 @@ #include #ifndef bswap_16 -#define bswap_16(x) \ - ((uint16_t)((((uint16_t)(x)&0xff00) >> 8) | \ - (((uint16_t)(x)&0x00ff) << 8))) +#define bswap_16(x) \ + ((uint16_t)((((uint16_t)(x) & 0xff00) >> 8) | \ + (((uint16_t)(x) & 0x00ff) << 8))) #endif /* !bswap_16 */ #ifndef bswap_32 -#define bswap_32(x) \ - ((uint32_t)((((uint32_t)(x)&0xff000000) >> 24) | \ - (((uint32_t)(x)&0x00ff0000) >> 8) | \ - (((uint32_t)(x)&0x0000ff00) << 8) | \ - (((uint32_t)(x)&0x000000ff) << 24))) +#define bswap_32(x) \ + ((uint32_t)((((uint32_t)(x) & 0xff000000) >> 24) | \ + (((uint32_t)(x) & 0x00ff0000) >> 8) | \ + (((uint32_t)(x) & 0x0000ff00) << 8) | \ + (((uint32_t)(x) & 0x000000ff) << 24))) #endif /* !bswap_32 */ #ifndef bswap_64 -#define bswap_64(x) \ - ((uint64_t)((((uint64_t)(x)&0xff00000000000000ULL) >> 56) | \ - (((uint64_t)(x)&0x00ff000000000000ULL) >> 40) | \ - (((uint64_t)(x)&0x0000ff0000000000ULL) >> 24) | \ - (((uint64_t)(x)&0x000000ff00000000ULL) >> 8) | \ - (((uint64_t)(x)&0x00000000ff000000ULL) << 8) | \ - (((uint64_t)(x)&0x0000000000ff0000ULL) << 24) | \ - (((uint64_t)(x)&0x000000000000ff00ULL) << 40) | \ - (((uint64_t)(x)&0x00000000000000ffULL) << 56))) +#define bswap_64(x) \ + ((uint64_t)((((uint64_t)(x) & 0xff00000000000000ULL) >> 56) | \ + (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \ + (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \ + (((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \ + (((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \ + (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \ + (((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \ + (((uint64_t)(x) & 0x00000000000000ffULL) << 56))) #endif /* !bswap_64 */ #ifndef htobe16 diff --git a/lib/isc/include/isc/net.h b/lib/isc/include/isc/net.h index 1a3ce63..077f66e 100644 --- a/lib/isc/include/isc/net.h +++ b/lib/isc/include/isc/net.h @@ -192,10 +192,10 @@ /*% Is IP address multicast? */ #define ISC_IPADDR_ISMULTICAST(i) \ - (((uint32_t)(i)&ISC__IPADDR(0xf0000000)) == ISC__IPADDR(0xe0000000)) + (((uint32_t)(i) & ISC__IPADDR(0xf0000000)) == ISC__IPADDR(0xe0000000)) #define ISC_IPADDR_ISEXPERIMENTAL(i) \ - (((uint32_t)(i)&ISC__IPADDR(0xf0000000)) == ISC__IPADDR(0xf0000000)) + (((uint32_t)(i) & ISC__IPADDR(0xf0000000)) == ISC__IPADDR(0xf0000000)) /*** *** Functions. diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h index eff33f6..d42cfe9 100644 --- a/lib/isc/include/isc/netmgr.h +++ b/lib/isc/include/isc/netmgr.h @@ -750,6 +750,9 @@ isc_nm_verify_tls_peer_result_string(const isc_nmhandle_t *handle); * \li 'handle' is a valid netmgr handle object. */ +#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/include/isc/radix.h b/lib/isc/include/isc/radix.h index 9a91118..b385e12 100644 --- a/lib/isc/include/isc/radix.h +++ b/lib/isc/include/isc/radix.h @@ -192,7 +192,7 @@ isc_radix_process(isc_radix_tree_t *radix, isc_radix_processfunc_t func); */ #define RADIX_MAXBITS 128 -#define RADIX_NBIT(x) (0x80 >> ((x)&0x7f)) +#define RADIX_NBIT(x) (0x80 >> ((x) & 0x7f)) #define RADIX_NBYTE(x) ((x) >> 3) #define RADIX_WALK(Xhead, Xnode) \ diff --git a/lib/isc/include/isc/types.h b/lib/isc/include/isc/types.h index 7e0fc02..dc76a87 100644 --- a/lib/isc/include/isc/types.h +++ b/lib/isc/include/isc/types.h @@ -13,6 +13,7 @@ #pragma once +#include #include /*! \file isc/types.h @@ -74,10 +75,11 @@ typedef struct isc_rwlock isc_rwlock_t; /*%< Read Write Lock */ typedef struct isc_sockaddr isc_sockaddr_t; /*%< Socket Address */ typedef ISC_LIST(isc_sockaddr_t) isc_sockaddrlist_t; /*%< Socket Address List * */ -typedef struct isc_stats isc_stats_t; /*%< Statistics */ -typedef int_fast64_t isc_statscounter_t; -typedef struct isc_symtab isc_symtab_t; /*%< Symbol Table */ -typedef struct isc_task isc_task_t; /*%< Task */ +typedef struct isc_stats isc_stats_t; /*%< Statistics */ +typedef int_fast64_t isc_statscounter_t; +typedef atomic_int_fast64_t isc_atomic_statscounter_t; +typedef struct isc_symtab isc_symtab_t; /*%< Symbol Table */ +typedef struct isc_task isc_task_t; /*%< Task */ typedef ISC_LIST(isc_task_t) isc_tasklist_t; /*%< Task List */ typedef struct isc_taskmgr isc_taskmgr_t; /*%< Task Manager */ typedef struct isc_textregion isc_textregion_t; /*%< Text Region */ diff --git a/lib/isc/mem.c b/lib/isc/mem.c index 61a66f6..6560833 100644 --- a/lib/isc/mem.c +++ b/lib/isc/mem.c @@ -1906,3 +1906,14 @@ isc__mem_printactive(isc_mem_t *ctx, FILE *file) { UNUSED(file); #endif /* if ISC_MEM_TRACKLINES */ } + +void * +isc__mem_alloc_noctx(size_t size) { + return mallocx(size, 0); +} + +void +isc__mem_free_noctx(void *ptr, size_t size) { + ADJUST_ZERO_ALLOCATION_SIZE(size); + sdallocx(ptr, size, 0); +} diff --git a/lib/isc/mem_p.h b/lib/isc/mem_p.h index 611a025..d95bfc3 100644 --- a/lib/isc/mem_p.h +++ b/lib/isc/mem_p.h @@ -26,6 +26,17 @@ isc__mem_printactive(isc_mem_t *mctx, FILE *file); * a single memory context. */ +void * +isc__mem_alloc_noctx(size_t size); +void +isc__mem_free_noctx(void *ptr, size_t size); +/*%< + * Allocate memory that is not associated with an isc_mem memory context. + * + * For use purely in the isc_trampoline unit, to avoid the need of copying + * multiple #ifdef lines from lib/isc/mem.c to lib/isc/trampoline.c. + */ + void isc__mem_checkdestroyed(void); diff --git a/lib/isc/netaddr.c b/lib/isc/netaddr.c index c674d83..a170d2f 100644 --- a/lib/isc/netaddr.c +++ b/lib/isc/netaddr.c @@ -424,7 +424,7 @@ isc_netaddr_issitelocal(const isc_netaddr_t *na) { } #define ISC_IPADDR_ISNETZERO(i) \ - (((uint32_t)(i)&ISC__IPADDR(0xff000000)) == ISC__IPADDR(0x00000000)) + (((uint32_t)(i) & ISC__IPADDR(0xff000000)) == ISC__IPADDR(0x00000000)) bool isc_netaddr_isnetzero(const isc_netaddr_t *na) { diff --git a/lib/isc/netmgr/http.c b/lib/isc/netmgr/http.c index f2d3e2d..2220edf 100644 --- a/lib/isc/netmgr/http.c +++ b/lib/isc/netmgr/http.c @@ -2493,6 +2493,7 @@ isc_nm_listenhttp(isc_nm_t *mgr, isc_sockaddr_t *iface, int backlog, isc_nmsocket_t *sock = NULL; isc_result_t result; + REQUIRE(VALID_NM(mgr)); REQUIRE(!ISC_LIST_EMPTY(eps->handlers)); REQUIRE(!ISC_LIST_EMPTY(eps->handler_cbargs)); REQUIRE(atomic_load(&eps->in_use) == false); @@ -2968,7 +2969,7 @@ isc__nm_http_set_max_streams(isc_nmsocket_t *listener, void isc_nm_http_set_endpoints(isc_nmsocket_t *listener, isc_nm_http_endpoints_t *eps) { - size_t nworkers; + size_t nlisteners; REQUIRE(VALID_NMSOCK(listener)); REQUIRE(listener->type == isc_nm_httplistener); @@ -2976,8 +2977,8 @@ isc_nm_http_set_endpoints(isc_nmsocket_t *listener, atomic_store(&eps->in_use, true); - nworkers = (size_t)listener->mgr->nworkers; - for (size_t i = 0; i < nworkers; i++) { + nlisteners = (size_t)listener->mgr->nlisteners; + for (size_t i = 0; i < nlisteners; i++) { isc__netievent__http_eps_t *ievent = isc__nm_get_netievent_httpendpoints(listener->mgr, listener, eps); @@ -3002,20 +3003,20 @@ isc__nm_async_httpendpoints(isc__networker_t *worker, isc__netievent_t *ev0) { static void http_init_listener_endpoints(isc_nmsocket_t *listener, isc_nm_http_endpoints_t *epset) { - size_t nworkers; + size_t nlisteners; REQUIRE(VALID_NMSOCK(listener)); REQUIRE(VALID_NM(listener->mgr)); REQUIRE(VALID_HTTP_ENDPOINTS(epset)); - nworkers = (size_t)listener->mgr->nworkers; - INSIST(nworkers > 0); + nlisteners = (size_t)listener->mgr->nlisteners; + INSIST(nlisteners > 0); listener->h2.listener_endpoints = isc_mem_get(listener->mgr->mctx, - sizeof(isc_nm_http_endpoints_t *) * nworkers); - listener->h2.n_listener_endpoints = nworkers; - for (size_t i = 0; i < nworkers; i++) { + sizeof(isc_nm_http_endpoints_t *) * nlisteners); + listener->h2.n_listener_endpoints = nlisteners; + for (size_t i = 0; i < nlisteners; i++) { listener->h2.listener_endpoints[i] = NULL; isc_nm_http_endpoints_attach( epset, &listener->h2.listener_endpoints[i]); diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index 364a933..6aca9ab 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -776,6 +776,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 b19d468..2310b4b 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -189,12 +189,12 @@ isc__nm_force_tid(int tid) { } 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); } } @@ -212,11 +212,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) { @@ -234,10 +234,13 @@ isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) { uv_version_string(), UV_VERSION_STRING); } - 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); @@ -272,11 +275,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; @@ -310,7 +314,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); } @@ -817,9 +821,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]; @@ -3778,7 +3788,7 @@ isc__nm_async_settlsctx(isc__networker_t *worker, isc__netievent_t *ev0) { static void set_tlsctx_workers(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx) { /* Update the TLS context reference for every worker thread. */ - for (size_t i = 0; i < (size_t)listener->mgr->nworkers; i++) { + for (size_t i = 0; i < (size_t)listener->mgr->nlisteners; i++) { isc__netievent__tlsctx_t *ievent = isc__nm_get_netievent_settlsctx(listener->mgr, listener, tlsctx); diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c index 2a644fe..16b53cc 100644 --- a/lib/isc/netmgr/tcp.c +++ b/lib/isc/netmgr/tcp.c @@ -341,7 +341,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); @@ -362,7 +362,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); } @@ -457,7 +457,7 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_sockaddr_t *iface, isc__nmsocket_init(sock, mgr, isc_nm_tcplistener, iface); atomic_init(&sock->rchildren, 0); - sock->nchildren = mgr->nworkers; + sock->nchildren = mgr->nlisteners; children_size = sock->nchildren * sizeof(sock->children[0]); sock->children = isc_mem_get(mgr->mctx, children_size); memset(sock->children, 0, children_size); diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c index eda6aa6..b2a0b10 100644 --- a/lib/isc/netmgr/tcpdns.c +++ b/lib/isc/netmgr/tcpdns.c @@ -324,7 +324,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); } @@ -422,7 +422,7 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_sockaddr_t *iface, isc__nmsocket_init(sock, mgr, isc_nm_tcpdnslistener, iface); atomic_init(&sock->rchildren, 0); - sock->nchildren = mgr->nworkers; + sock->nchildren = mgr->nlisteners; children_size = sock->nchildren * sizeof(sock->children[0]); sock->children = isc_mem_get(mgr->mctx, children_size); memset(sock->children, 0, children_size); @@ -808,6 +808,13 @@ isc__nm_tcpdns_processbuffer(isc_nmsocket_t *sock) { return (ISC_R_CANCELED); } + if (sock->client && !sock->recv_read) { + /* + * We are not reading data - stop here. + */ + return (ISC_R_CANCELED); + } + req = isc__nm_get_read_req(sock, NULL); REQUIRE(VALID_UVREQ(req)); diff --git a/lib/isc/netmgr/tlsdns.c b/lib/isc/netmgr/tlsdns.c index d30e33f..feeb1a8 100644 --- a/lib/isc/netmgr/tlsdns.c +++ b/lib/isc/netmgr/tlsdns.c @@ -419,7 +419,7 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, isc__nm_put_netievent_tlsdnsconnect(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); } @@ -532,7 +532,7 @@ isc_nm_listentlsdns(isc_nm_t *mgr, isc_sockaddr_t *iface, isc__nmsocket_init(sock, mgr, isc_nm_tlsdnslistener, iface); atomic_init(&sock->rchildren, 0); - sock->nchildren = mgr->nworkers; + sock->nchildren = mgr->nlisteners; children_size = sock->nchildren * sizeof(sock->children[0]); sock->children = isc_mem_get(mgr->mctx, children_size); memset(sock->children, 0, children_size); @@ -1016,6 +1016,13 @@ isc__nm_tlsdns_processbuffer(isc_nmsocket_t *sock) { return (ISC_R_CANCELED); } + if (sock->client && !sock->recv_read) { + /* + * We are not reading data - stop here. + */ + return (ISC_R_CANCELED); + } + req = isc__nm_get_read_req(sock, NULL); REQUIRE(VALID_UVREQ(req)); diff --git a/lib/isc/netmgr/tlsstream.c b/lib/isc/netmgr/tlsstream.c index 7b49071..a3fc6d2 100644 --- a/lib/isc/netmgr/tlsstream.c +++ b/lib/isc/netmgr/tlsstream.c @@ -1264,18 +1264,18 @@ isc__nm_tls_verify_tls_peer_result_string(const isc_nmhandle_t *handle) { static void tls_init_listener_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *ctx) { - size_t nworkers; + size_t nlisteners; REQUIRE(VALID_NM(listener->mgr)); REQUIRE(ctx != NULL); - nworkers = (size_t)listener->mgr->nworkers; - INSIST(nworkers > 0); + nlisteners = (size_t)listener->mgr->nlisteners; + INSIST(nlisteners > 0); listener->tlsstream.listener_tls_ctx = isc_mem_get( - listener->mgr->mctx, sizeof(isc_tlsctx_t *) * nworkers); - listener->tlsstream.n_listener_tls_ctx = nworkers; - for (size_t i = 0; i < nworkers; i++) { + listener->mgr->mctx, sizeof(isc_tlsctx_t *) * nlisteners); + listener->tlsstream.n_listener_tls_ctx = nlisteners; + for (size_t i = 0; i < nlisteners; i++) { listener->tlsstream.listener_tls_ctx[i] = NULL; isc_tlsctx_attach(ctx, &listener->tlsstream.listener_tls_ctx[i]); diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c index 1a0ee16..661de96 100644 --- a/lib/isc/netmgr/udp.c +++ b/lib/isc/netmgr/udp.c @@ -152,18 +152,19 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_sockaddr_t *iface, isc_nm_recv_cb_t cb, isc_result_t result = ISC_R_SUCCESS; isc_nmsocket_t *sock = NULL; size_t children_size = 0; - REQUIRE(VALID_NM(mgr)); uv_os_sock_t fd = -1; + REQUIRE(VALID_NM(mgr)); + /* - * 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)); isc__nmsocket_init(sock, mgr, isc_nm_udplistener, iface); atomic_init(&sock->rchildren, 0); - sock->nchildren = mgr->nworkers; + sock->nchildren = mgr->nlisteners; children_size = sock->nchildren * sizeof(sock->children[0]); sock->children = isc_mem_get(mgr->mctx, children_size); memset(sock->children, 0, children_size); @@ -693,6 +694,7 @@ isc__nm_udp_send(isc_nmhandle_t *handle, const isc_region_t *region, uint32_t maxudp = atomic_load(&sock->mgr->maxudp); int ntid; + REQUIRE(VALID_NMSOCK(sock)); INSIST(sock->type == isc_nm_udpsocket); /* @@ -1035,7 +1037,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); } diff --git a/lib/isc/netmgr/uv-compat.h b/lib/isc/netmgr/uv-compat.h index 3a10387..eea8744 100644 --- a/lib/isc/netmgr/uv-compat.h +++ b/lib/isc/netmgr/uv-compat.h @@ -72,7 +72,7 @@ uv_tcp_close_reset(uv_tcp_t *handle, uv_close_cb close_cb); #endif #if UV_VERSION_HEX < UV_VERSION(1, 34, 0) -#define uv_sleep(msec) usleep(msec * 1000) +#define uv_sleep(msec) usleep((msec) * 1000) #endif /* UV_VERSION_HEX < UV_VERSION(1, 34, 0) */ #if UV_VERSION_HEX < UV_VERSION(1, 27, 0) diff --git a/lib/isc/stats.c b/lib/isc/stats.c index 3e4676c..183030e 100644 --- a/lib/isc/stats.c +++ b/lib/isc/stats.c @@ -28,14 +28,22 @@ #define ISC_STATS_MAGIC ISC_MAGIC('S', 't', 'a', 't') #define ISC_STATS_VALID(x) ISC_MAGIC_VALID(x, ISC_STATS_MAGIC) -typedef atomic_int_fast64_t isc__atomic_statcounter_t; +/* + * Statistics are counted with an atomic int_fast64_t but exported to functions + * taking uint64_t (isc_stats_dumper_t). A 128-bit native and fast architecture + * doesn't exist in reality so these two are the same thing in practise. + * However, a silent truncation happening silently in the future is still not + * acceptable. + */ +STATIC_ASSERT(sizeof(isc_statscounter_t) <= sizeof(uint64_t), + "Exported statistics must fit into the statistic counter size"); struct isc_stats { unsigned int magic; isc_mem_t *mctx; isc_refcount_t references; int ncounters; - isc__atomic_statcounter_t *counters; + isc_atomic_statscounter_t *counters; }; static isc_result_t @@ -46,7 +54,7 @@ create_stats(isc_mem_t *mctx, int ncounters, isc_stats_t **statsp) { REQUIRE(statsp != NULL && *statsp == NULL); stats = isc_mem_get(mctx, sizeof(*stats)); - counters_alloc_size = sizeof(isc__atomic_statcounter_t) * ncounters; + counters_alloc_size = sizeof(isc_atomic_statscounter_t) * ncounters; stats->counters = isc_mem_get(mctx, counters_alloc_size); isc_refcount_init(&stats->references, 1); for (int i = 0; i < ncounters; i++) { @@ -82,7 +90,7 @@ isc_stats_detach(isc_stats_t **statsp) { if (isc_refcount_decrement(&stats->references) == 1) { isc_refcount_destroy(&stats->references); isc_mem_put(stats->mctx, stats->counters, - sizeof(isc__atomic_statcounter_t) * + sizeof(isc_atomic_statscounter_t) * stats->ncounters); isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats)); } @@ -125,7 +133,8 @@ isc_stats_dump(isc_stats_t *stats, isc_stats_dumper_t dump_fn, void *arg, REQUIRE(ISC_STATS_VALID(stats)); for (i = 0; i < stats->ncounters; i++) { - uint32_t counter = atomic_load_acquire(&stats->counters[i]); + isc_statscounter_t counter = + atomic_load_acquire(&stats->counters[i]); if ((options & ISC_STATSDUMP_VERBOSE) == 0 && counter == 0) { continue; } @@ -169,7 +178,7 @@ void isc_stats_resize(isc_stats_t **statsp, int ncounters) { isc_stats_t *stats; size_t counters_alloc_size; - isc__atomic_statcounter_t *newcounters; + isc_atomic_statscounter_t *newcounters; REQUIRE(statsp != NULL && *statsp != NULL); REQUIRE(ISC_STATS_VALID(*statsp)); @@ -182,7 +191,7 @@ isc_stats_resize(isc_stats_t **statsp, int ncounters) { } /* Grow number of counters. */ - counters_alloc_size = sizeof(isc__atomic_statcounter_t) * ncounters; + counters_alloc_size = sizeof(isc_atomic_statscounter_t) * ncounters; newcounters = isc_mem_get(stats->mctx, counters_alloc_size); for (int i = 0; i < ncounters; i++) { atomic_init(&newcounters[i], 0); @@ -192,7 +201,7 @@ isc_stats_resize(isc_stats_t **statsp, int ncounters) { atomic_store_release(&newcounters[i], counter); } isc_mem_put(stats->mctx, stats->counters, - sizeof(isc__atomic_statcounter_t) * stats->ncounters); + sizeof(isc_atomic_statscounter_t) * stats->ncounters); stats->counters = newcounters; stats->ncounters = ncounters; } diff --git a/lib/isc/trampoline.c b/lib/isc/trampoline.c index 58171d9..3e58fa7 100644 --- a/lib/isc/trampoline.c +++ b/lib/isc/trampoline.c @@ -22,6 +22,7 @@ #include #include +#include "mem_p.h" #include "trampoline_p.h" #define ISC__TRAMPOLINE_UNUSED 0 @@ -148,7 +149,7 @@ isc__trampoline_detach(isc__trampoline_t *trampoline) { isc__trampoline_min = trampoline->tid; } - free(trampoline->jemalloc_enforce_init); + isc__mem_free_noctx(trampoline->jemalloc_enforce_init, 8); free(trampoline); uv_mutex_unlock(&isc__trampoline_lock); @@ -174,7 +175,7 @@ isc__trampoline_attach(isc__trampoline_t *trampoline) { * so that an optimizing compiler does not strip away such a pair of * malloc() + free() calls altogether, as it would foil the fix. */ - trampoline->jemalloc_enforce_init = malloc(8); + trampoline->jemalloc_enforce_init = isc__mem_alloc_noctx(8); uv_mutex_unlock(&isc__trampoline_lock); } diff --git a/lib/isc/url.c b/lib/isc/url.c index cccb712..320a863 100644 --- a/lib/isc/url.c +++ b/lib/isc/url.c @@ -44,7 +44,7 @@ #ifndef BIT_AT #define BIT_AT(a, i) \ (!!((unsigned int)(a)[(unsigned int)(i) >> 3] & \ - (1 << ((unsigned int)(i)&7)))) + (1 << ((unsigned int)(i) & 7)))) #endif #if HTTP_PARSER_STRICT @@ -201,7 +201,8 @@ typedef enum { #define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c)) #define IS_HOST_CHAR(c) (isalnum((unsigned char)c) || (c) == '.' || (c) == '-') #else -#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c) || ((c)&0x80)) +#define IS_URL_CHAR(c) \ + (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80)) #define IS_HOST_CHAR(c) \ (isalnum((unsigned char)c) || (c) == '.' || (c) == '-' || (c) == '_') #endif diff --git a/lib/isccc/Makefile.in b/lib/isccc/Makefile.in index 3fee7ca..2a8d865 100644 --- a/lib/isccc/Makefile.in +++ b/lib/isccc/Makefile.in @@ -104,11 +104,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/isccc/cc.c b/lib/isccc/cc.c index cbd9bad..71e5b14 100644 --- a/lib/isccc/cc.c +++ b/lib/isccc/cc.c @@ -255,7 +255,7 @@ list_towire(isccc_sexpr_t *list, isc_buffer_t **buffer) { } static isc_result_t -sign(unsigned char *data, unsigned int length, unsigned char *hmac, +sign(unsigned char *data, unsigned int length, unsigned char *out, uint32_t algorithm, isccc_region_t *secret) { const isc_md_type_t *md_type; isc_result_t result; @@ -304,9 +304,9 @@ sign(unsigned char *data, unsigned int length, unsigned char *hmac, return (result); } if (algorithm == ISCCC_ALG_HMACMD5) { - PUT_MEM(digestb64, HMD5_LENGTH, hmac); + PUT_MEM(digestb64, HMD5_LENGTH, out); } else { - PUT_MEM(digestb64, HSHA_LENGTH, hmac); + PUT_MEM(digestb64, HSHA_LENGTH, out); } return (ISC_R_SUCCESS); } @@ -382,7 +382,7 @@ verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length, isccc_region_t source; isccc_region_t target; isc_result_t result; - isccc_sexpr_t *_auth, *hmac; + isccc_sexpr_t *_auth, *hmacvalue; unsigned char digest[ISC_MAX_MD_SIZE]; unsigned int digestlen = sizeof(digest); unsigned char digestb64[HSHA_LENGTH * 4]; @@ -395,11 +395,11 @@ verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length, return (ISC_R_FAILURE); } if (algorithm == ISCCC_ALG_HMACMD5) { - hmac = isccc_alist_lookup(_auth, "hmd5"); + hmacvalue = isccc_alist_lookup(_auth, "hmd5"); } else { - hmac = isccc_alist_lookup(_auth, "hsha"); + hmacvalue = isccc_alist_lookup(_auth, "hsha"); } - if (!isccc_sexpr_binaryp(hmac)) { + if (!isccc_sexpr_binaryp(hmacvalue)) { return (ISC_R_FAILURE); } /* @@ -452,7 +452,7 @@ verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length, isccc_region_t *region; unsigned char *value; - region = isccc_sexpr_tobinary(hmac); + region = isccc_sexpr_tobinary(hmacvalue); if ((region->rend - region->rstart) != HMD5_LENGTH) { return (ISCCC_R_BADAUTH); } @@ -465,7 +465,7 @@ verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length, unsigned char *value; uint32_t valalg; - region = isccc_sexpr_tobinary(hmac); + region = isccc_sexpr_tobinary(hmacvalue); /* * Note: with non-MD5 algorithms, there's an extra octet diff --git a/lib/isccfg/Makefile.in b/lib/isccfg/Makefile.in index 38f6b93..5fe9255 100644 --- a/lib/isccfg/Makefile.in +++ b/lib/isccfg/Makefile.in @@ -104,11 +104,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/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 4e4c098..d5b28ba 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -2137,9 +2137,11 @@ static cfg_clausedef_t view_clauses[] = { { "request-nsid", &cfg_type_boolean, 0 }, { "request-sit", NULL, CFG_CLAUSEFLAG_ANCIENT }, { "require-server-cookie", &cfg_type_boolean, 0 }, - { "resolver-nonbackoff-tries", &cfg_type_uint32, 0 }, + { "resolver-nonbackoff-tries", &cfg_type_uint32, + CFG_CLAUSEFLAG_DEPRECATED }, { "resolver-query-timeout", &cfg_type_uint32, 0 }, - { "resolver-retry-interval", &cfg_type_uint32, 0 }, + { "resolver-retry-interval", &cfg_type_uint32, + CFG_CLAUSEFLAG_DEPRECATED }, { "response-padding", &cfg_type_resppadding, 0 }, { "response-policy", &cfg_type_rpz, 0 }, { "rfc2308-type1", NULL, CFG_CLAUSEFLAG_ANCIENT }, @@ -2161,8 +2163,7 @@ static cfg_clausedef_t view_clauses[] = { { "synth-from-dnssec", &cfg_type_boolean, 0 }, { "topology", NULL, CFG_CLAUSEFLAG_ANCIENT }, { "transfer-format", &cfg_type_transferformat, 0 }, - { "trust-anchor-telemetry", &cfg_type_boolean, - CFG_CLAUSEFLAG_EXPERIMENTAL }, + { "trust-anchor-telemetry", &cfg_type_boolean, 0 }, { "use-queryport-pool", NULL, CFG_CLAUSEFLAG_ANCIENT }, { "validate-except", &cfg_type_namelist, 0 }, { "v6-bias", &cfg_type_uint32, 0 }, diff --git a/lib/ns/Makefile.in b/lib/ns/Makefile.in index ba30d74..5737778 100644 --- a/lib/ns/Makefile.in +++ b/lib/ns/Makefile.in @@ -104,11 +104,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/ns/client.c b/lib/ns/client.c index 5ed64fd..a62343b 100644 --- a/lib/ns/client.c +++ b/lib/ns/client.c @@ -1672,9 +1672,7 @@ ns__client_put_cb(void *client0) { dns_message_detach(&client->message); - if (client->manager != NULL) { - ns_clientmgr_detach(&client->manager); - } + ns_clientmgr_detach(&client->manager); /* * Detaching the task must be done after unlinking from @@ -2322,11 +2320,8 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) { isc_result_t result; /* - * Caller must be holding the manager lock. - * * Note: creating a client does not add the client to the - * manager's client list or set the client's manager pointer. - * The caller is responsible for that. + * manager's client list, the caller is responsible for that. */ if (new) { @@ -2402,26 +2397,13 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) { return (ISC_R_SUCCESS); cleanup: - if (client->sendbuf != NULL) { - isc_mem_put(client->manager->send_mctx, client->sendbuf, - NS_CLIENT_SEND_BUFFER_SIZE); - } - - if (client->message != NULL) { - dns_message_detach(&client->message); - } - - if (client->task != NULL) { - isc_task_detach(&client->task); - } - - if (client->manager != NULL) { - ns_clientmgr_detach(&client->manager); - } + isc_mem_put(client->manager->send_mctx, client->sendbuf, + NS_CLIENT_SEND_BUFFER_SIZE); + dns_message_detach(&client->message); + isc_task_detach(&client->task); + ns_clientmgr_detach(&client->manager); isc_mem_detach(&client->mctx); - if (client->sctx != NULL) { - ns_server_detach(&client->sctx); - } + ns_server_detach(&client->sctx); return (result); } diff --git a/lib/ns/query.c b/lib/ns/query.c index 00ef955..40e1232 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -199,7 +199,7 @@ client_trace(ns_client_t *client, int level, const char *message) { #define DNS_GETDB_IGNOREACL 0x08U #define DNS_GETDB_STALEFIRST 0X0CU -#define PENDINGOK(x) (((x)&DNS_DBFIND_PENDINGOK) != 0) +#define PENDINGOK(x) (((x) & DNS_DBFIND_PENDINGOK) != 0) #define SFCACHE_CDFLAG 0x1 @@ -465,10 +465,10 @@ static void query_addnxrrsetnsec(query_ctx_t *qctx); static isc_result_t -query_nxdomain(query_ctx_t *qctx, isc_result_t res); +query_nxdomain(query_ctx_t *qctx, isc_result_t result); static isc_result_t -query_redirect(query_ctx_t *qctx); +query_redirect(query_ctx_t *qctx, isc_result_t result); static isc_result_t query_ncache(query_ctx_t *qctx, isc_result_t result); @@ -6228,6 +6228,13 @@ query_lookup_stale(ns_client_t *client) { query_ctx_t qctx; qctx_init(client, NULL, client->query.qtype, &qctx); + if (DNS64(client)) { + qctx.qtype = qctx.type = dns_rdatatype_a; + qctx.dns64 = true; + } + if (DNS64EXCLUDE(client)) { + qctx.dns64_exclude = true; + } dns_db_attach(client->view->cachedb, &qctx.db); client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK; client->query.dboptions |= DNS_DBFIND_STALETIMEOUT; @@ -7681,8 +7688,19 @@ query_usestale(query_ctx_t *qctx, isc_result_t result) { qctx_freedata(qctx); if (dns_view_staleanswerenabled(qctx->client->view)) { - dns_db_attach(qctx->client->view->cachedb, &qctx->db); - qctx->version = NULL; + isc_result_t ret; + ret = query_getdb(qctx->client, qctx->client->query.qname, + qctx->client->query.qtype, qctx->options, + &qctx->zone, &qctx->db, &qctx->version, + &qctx->is_zone); + if (ret != ISC_R_SUCCESS) { + /* + * Failed to get the database, unexpected, but let us + * at least abandon serve-stale. + */ + return (false); + } + qctx->client->query.dboptions |= DNS_DBFIND_STALEOK; if (qctx->client->query.fetch != NULL) { dns_resolver_destroyfetch(&qctx->client->query.fetch); @@ -7707,8 +7725,7 @@ query_usestale(query_ctx_t *qctx, isc_result_t result) { * result from the search. */ static isc_result_t -query_gotanswer(query_ctx_t *qctx, isc_result_t res) { - isc_result_t result = res; +query_gotanswer(query_ctx_t *qctx, isc_result_t result) { char errmsg[256]; CCTRACE(ISC_LOG_DEBUG(3), "query_gotanswer"); @@ -7784,7 +7801,7 @@ root_key_sentinel: return (query_coveringnsec(qctx)); case DNS_R_NCACHENXDOMAIN: - result = query_redirect(qctx); + result = query_redirect(qctx, result); if (result != ISC_R_COMPLETE) { return (result); } @@ -9601,11 +9618,10 @@ query_addnxrrsetnsec(query_ctx_t *qctx) { * Handle NXDOMAIN and empty wildcard responses. */ static isc_result_t -query_nxdomain(query_ctx_t *qctx, isc_result_t res) { +query_nxdomain(query_ctx_t *qctx, isc_result_t result) { dns_section_t section; uint32_t ttl; - isc_result_t result = res; - bool empty_wild = (res == DNS_R_EMPTYWILD); + bool empty_wild = (result == DNS_R_EMPTYWILD); CCTRACE(ISC_LOG_DEBUG(3), "query_nxdomain"); @@ -9614,7 +9630,7 @@ query_nxdomain(query_ctx_t *qctx, isc_result_t res) { INSIST(qctx->is_zone || REDIRECT(qctx->client)); if (!empty_wild) { - result = query_redirect(qctx); + result = query_redirect(qctx, result); if (result != ISC_R_COMPLETE) { return (result); } @@ -9702,7 +9718,7 @@ cleanup: * redirecting, so query processing should continue past it. */ static isc_result_t -query_redirect(query_ctx_t *qctx) { +query_redirect(query_ctx_t *qctx, isc_result_t saved_result) { isc_result_t result; CCTRACE(ISC_LOG_DEBUG(3), "query_redirect"); @@ -9743,7 +9759,7 @@ query_redirect(query_ctx_t *qctx) { SAVE(qctx->client->query.redirect.rdataset, qctx->rdataset); SAVE(qctx->client->query.redirect.sigrdataset, qctx->sigrdataset); - qctx->client->query.redirect.result = DNS_R_NCACHENXDOMAIN; + qctx->client->query.redirect.result = saved_result; dns_name_copy(qctx->fname, qctx->client->query.redirect.fname); qctx->client->query.redirect.authoritative = qctx->authoritative; @@ -10404,7 +10420,7 @@ query_coveringnsec(query_ctx_t *qctx) { * We now have the proof that we have an NXDOMAIN. Apply * NXDOMAIN redirection if configured. */ - result = query_redirect(qctx); + result = query_redirect(qctx, DNS_R_COVERINGNSEC); if (result != ISC_R_COMPLETE) { redirected = true; goto cleanup; diff --git a/lib/ns/xfrout.c b/lib/ns/xfrout.c index 9380924..1429d3b 100644 --- a/lib/ns/xfrout.c +++ b/lib/ns/xfrout.c @@ -1264,7 +1264,7 @@ xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id, * Note that although 65535-byte RRs are allowed in principle, they * cannot be zone-transferred (at least not if uncompressible), * because the message and RR headers would push the size of the - * TCP message over the 65536 byte limit. + * TCP message over the 65535 byte limit. */ mem = isc_mem_get(mctx, len); isc_buffer_init(&xfr->buf, mem, len); -- cgit v1.2.3