summaryrefslogtreecommitdiffstats
path: root/lib/dns
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-08 16:41:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-08 16:41:29 +0000
commite2fc8e037ea6bb5de92b25ec9c12a624737ac5ca (patch)
tree65e6bbf5e12c3fe09b43e577f8d1786d06bcd559 /lib/dns
parentReleasing progress-linux version 1:9.18.19-1~deb12u1progress7u1. (diff)
downloadbind9-e2fc8e037ea6bb5de92b25ec9c12a624737ac5ca.tar.xz
bind9-e2fc8e037ea6bb5de92b25ec9c12a624737ac5ca.zip
Merging upstream version 1:9.18.24.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib/dns')
-rw-r--r--lib/dns/Makefile.in2
-rw-r--r--lib/dns/adb.c10
-rw-r--r--lib/dns/catz.c16
-rw-r--r--lib/dns/diff.c34
-rw-r--r--lib/dns/dst_api.c29
-rw-r--r--lib/dns/include/dns/catz.h8
-rw-r--r--lib/dns/include/dns/dispatch.h2
-rw-r--r--lib/dns/include/dns/message.h40
-rw-r--r--lib/dns/include/dns/name.h37
-rw-r--r--lib/dns/include/dns/rbt.h13
-rw-r--r--lib/dns/include/dns/rpz.h5
-rw-r--r--lib/dns/include/dns/stats.h2
-rw-r--r--lib/dns/include/dns/validator.h1
-rw-r--r--lib/dns/include/dst/dst.h4
-rw-r--r--lib/dns/master.c2
-rw-r--r--lib/dns/message.c375
-rw-r--r--lib/dns/name.c1
-rw-r--r--lib/dns/ncache.c2
-rw-r--r--lib/dns/nsec3.c14
-rw-r--r--lib/dns/opensslrsa_link.c6
-rw-r--r--lib/dns/private.c8
-rw-r--r--lib/dns/rbt.c8
-rw-r--r--lib/dns/rbtdb.c237
-rw-r--r--lib/dns/rdata.c2
-rw-r--r--lib/dns/resolver.c30
-rw-r--r--lib/dns/rootns.c53
-rw-r--r--lib/dns/stats.c10
-rw-r--r--lib/dns/tsig.c22
-rw-r--r--lib/dns/update.c53
-rw-r--r--lib/dns/validator.c67
-rw-r--r--lib/dns/xfrin.c19
-rw-r--r--lib/dns/zone.c89
32 files changed, 752 insertions, 449 deletions
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 <inttypes.h>
#include <stdbool.h>
@@ -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 <dns/types.h>
-#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 <stdbool.h>
#include <stdio.h>
+#include <isc/ht.h>
#include <isc/lang.h>
#include <isc/magic.h>
#include <isc/region.h> /* 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 <inttypes.h>
#include <stdbool.h>
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 <stdbool.h>
#include <isc/buffer.h>
+#include <isc/hash.h>
+#include <isc/ht.h>
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/result.h>
@@ -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);
@@ -791,6 +795,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) {
dns_name_t *curr;
@@ -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.
*/
@@ -1055,14 +1098,6 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
}
/*
- * 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.
*/
rdatalist = newrdatalist(msg);
@@ -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;
/*
@@ -2499,22 +2618,6 @@ dns_message_findname(dns_message_t *msg, dns_section_t section,
}
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) {
REQUIRE(msg != NULL);
@@ -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 <dns/rootns.h>
#include <dns/view.h>
+/*
+ * 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, &notify->dst, options, key,
- timeout * 3, timeout, 2, notify->zone->task,
- notify_done, notify, &notify->request);
+ result = dns_request_create(
+ notify->zone->view->requestmgr, message, &src, &notify->dst,
+ options, key, timeout * 3 + 1, timeout, 2, notify->zone->task,
+ notify_done, notify, &notify->request);
if (result == ISC_R_SUCCESS) {
if (isc_sockaddr_pf(&notify->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),