summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 23:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 23:51:28 +0000
commit754c7de1e91eeb28c6d3766900ead0c3e44fdb85 (patch)
tree51433c0e38731dc9ecd342555a56f876980b1834 /lib
parentAdding debian version 1:9.16.44-1~deb11u1. (diff)
downloadbind9-754c7de1e91eeb28c6d3766900ead0c3e44fdb85.tar.xz
bind9-754c7de1e91eeb28c6d3766900ead0c3e44fdb85.zip
Merging upstream version 1:9.16.48.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/bind9/check.c4
-rw-r--r--lib/dns/adb.c10
-rw-r--r--lib/dns/catz.c8
-rw-r--r--lib/dns/dst_api.c27
-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.h6
-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/mapapi2
-rw-r--r--lib/dns/master.c2
-rw-r--r--lib/dns/message.c391
-rw-r--r--lib/dns/name.c1
-rw-r--r--lib/dns/ncache.c2
-rw-r--r--lib/dns/nsec3.c8
-rw-r--r--lib/dns/opensslrsa_link.c5
-rw-r--r--lib/dns/private.c8
-rw-r--r--lib/dns/rbt.c1
-rw-r--r--lib/dns/rbtdb.c153
-rw-r--r--lib/dns/rdata.c2
-rw-r--r--lib/dns/resolver.c4
-rw-r--r--lib/dns/result.c2
-rw-r--r--lib/dns/rootns.c53
-rw-r--r--lib/dns/rpz.c5
-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/win32/libdns.def.in3
-rw-r--r--lib/dns/zone.c46
-rw-r--r--lib/isc/ht.c556
-rw-r--r--lib/isc/include/isc/endian.h34
-rw-r--r--lib/isc/include/isc/ht.h28
-rw-r--r--lib/isc/include/isc/netmgr.h3
-rw-r--r--lib/isc/include/isc/radix.h2
-rw-r--r--lib/isc/include/isc/resultclass.h2
-rw-r--r--lib/isc/netaddr.c2
-rw-r--r--lib/isc/netmgr/netmgr-int.h1
-rw-r--r--lib/isc/netmgr/netmgr.c36
-rw-r--r--lib/isc/netmgr/tcp.c6
-rw-r--r--lib/isc/netmgr/tcpdns.c4
-rw-r--r--lib/isc/netmgr/udp.c6
-rw-r--r--lib/isc/netmgr/uv-compat.h2
-rw-r--r--lib/isc/tests/ht_test.c57
-rw-r--r--lib/isc/unix/include/isc/net.h4
-rw-r--r--lib/isc/url.c5
-rw-r--r--lib/isc/win32/file.c8
-rw-r--r--lib/isc/win32/fsaccess.c2
-rw-r--r--lib/isc/win32/include/isc/net.h4
-rw-r--r--lib/isc/win32/include/isc/stat.h4
-rw-r--r--lib/ns/query.c34
-rw-r--r--lib/ns/tests/nstest.c2
-rw-r--r--lib/ns/xfrout.c2
53 files changed, 1169 insertions, 604 deletions
diff --git a/lib/bind9/check.c b/lib/bind9/check.c
index 3a78a17..ee64543 100644
--- a/lib/bind9/check.c
+++ b/lib/bind9/check.c
@@ -1457,6 +1457,10 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx,
(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/adb.c b/lib/dns/adb.c
index 87f0f8b..6f98fec 100644
--- a/lib/dns/adb.c
+++ b/lib/dns/adb.c
@@ -442,8 +442,8 @@ log_quota(dns_adbentry_t *entry, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
* 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))
@@ -452,11 +452,11 @@ log_quota(dns_adbentry_t *entry, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
* 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 & NAME_STARTATZONE) == ((o)&DNS_ADBFIND_STARTATZONE))
+ (((nf)->flags & NAME_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 2c00d6e..0275a4f 100644
--- a/lib/dns/catz.c
+++ b/lib/dns/catz.c
@@ -423,9 +423,9 @@ dns_catz_zones_merge(dns_catz_zone_t *target, dns_catz_zone_t *newzone) {
dns_name_format(&target->name, czname, DNS_NAME_FORMATSIZE);
- isc_ht_init(&toadd, target->catzs->mctx, 16);
+ isc_ht_init(&toadd, target->catzs->mctx, 16, ISC_HT_CASE_SENSITIVE);
- isc_ht_init(&tomod, target->catzs->mctx, 16);
+ isc_ht_init(&tomod, target->catzs->mctx, 16, ISC_HT_CASE_SENSITIVE);
isc_ht_iter_create(newzone->entries, &iter1);
@@ -610,7 +610,7 @@ dns_catz_new_zones(dns_catz_zones_t **catzsp, dns_catz_zonemodmethods_t *zmm,
isc_refcount_init(&new_zones->refs, 1);
- isc_ht_init(&new_zones->zones, mctx, 4);
+ isc_ht_init(&new_zones->zones, mctx, 4, ISC_HT_CASE_SENSITIVE);
isc_mem_attach(mctx, &new_zones->mctx);
new_zones->zmm = zmm;
@@ -662,7 +662,7 @@ dns_catz_new_zone(dns_catz_zones_t *catzs, dns_catz_zone_t **zonep,
dns_name_init(&new_zone->name, NULL);
dns_name_dup(name, catzs->mctx, &new_zone->name);
- isc_ht_init(&new_zone->entries, catzs->mctx, 16);
+ isc_ht_init(&new_zone->entries, catzs->mctx, 16, ISC_HT_CASE_SENSITIVE);
new_zone->updatetimer = NULL;
result = isc_timer_create(catzs->timermgr, isc_timertype_inactive, NULL,
diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c
index d49beb2..df5a358 100644
--- a/lib/dns/dst_api.c
+++ b/lib/dns/dst_api.c
@@ -164,7 +164,8 @@ computeid(dst_key_t *key);
static isc_result_t
frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
unsigned int protocol, dns_rdataclass_t rdclass,
- isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp);
+ isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
+ dst_key_t **keyp);
static isc_result_t
algorithm_status(unsigned int alg);
@@ -780,6 +781,13 @@ dst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
isc_result_t
dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
+ return (dst_key_fromdns_ex(name, rdclass, source, mctx, false, keyp));
+}
+
+isc_result_t
+dst_key_fromdns_ex(const dns_name_t *name, dns_rdataclass_t rdclass,
+ isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
+ dst_key_t **keyp) {
uint8_t alg, proto;
uint32_t flags, extflags;
dst_key_t *key = NULL;
@@ -810,7 +818,7 @@ dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
}
result = frombuffer(name, alg, flags, proto, rdclass, source, mctx,
- &key);
+ no_rdata, &key);
if (result != ISC_R_SUCCESS) {
return (result);
}
@@ -831,7 +839,7 @@ dst_key_frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
REQUIRE(dst_initialized);
result = frombuffer(name, alg, flags, protocol, rdclass, source, mctx,
- &key);
+ false, &key);
if (result != ISC_R_SUCCESS) {
return (result);
}
@@ -2337,7 +2345,8 @@ computeid(dst_key_t *key) {
static isc_result_t
frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
unsigned int protocol, dns_rdataclass_t rdclass,
- isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
+ isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
+ dst_key_t **keyp) {
dst_key_t *key;
isc_result_t ret;
@@ -2362,10 +2371,12 @@ frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
return (DST_R_UNSUPPORTEDALG);
}
- ret = key->func->fromdns(key, source);
- if (ret != ISC_R_SUCCESS) {
- dst_key_free(&key);
- return (ret);
+ if (!no_rdata) {
+ ret = key->func->fromdns(key, source);
+ if (ret != ISC_R_SUCCESS) {
+ dst_key_free(&key);
+ return (ret);
+ }
}
}
diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h
index 8214021..ea45742 100644
--- a/lib/dns/include/dns/message.h
+++ b/lib/dns/include/dns/message.h
@@ -542,7 +542,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:
*
@@ -801,44 +801,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 683f71d..2e1c5f8 100644
--- a/lib/dns/include/dns/name.h
+++ b/lib/dns/include/dns/name.h
@@ -69,6 +69,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. */
@@ -112,6 +113,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')
@@ -167,30 +169,24 @@ LIBDNS_EXTERNAL_DATA 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 \
}
/*%
@@ -1357,6 +1353,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 4a6b078..6cfd40f 100644
--- a/lib/dns/include/dns/rbt.h
+++ b/lib/dns/include/dns/rbt.h
@@ -140,6 +140,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
diff --git a/lib/dns/include/dns/stats.h b/lib/dns/include/dns/stats.h
index fd1697e..4be0969 100644
--- a/lib/dns/include/dns/stats.h
+++ b/lib/dns/include/dns/stats.h
@@ -492,7 +492,7 @@ LIBDNS_EXTERNAL_DATA 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 b435cd6..c5d7a31 100644
--- a/lib/dns/include/dns/validator.h
+++ b/lib/dns/include/dns/validator.h
@@ -149,6 +149,7 @@ struct dns_validator {
unsigned int depth;
unsigned int authcount;
unsigned int authfail;
+ bool failed;
isc_stdtime_t start;
};
diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h
index 3185e9f..3e3cfe6 100644
--- a/lib/dns/include/dst/dst.h
+++ b/lib/dns/include/dst/dst.h
@@ -471,6 +471,10 @@ dst_key_tofile(const dst_key_t *key, int type, const char *directory);
*/
isc_result_t
+dst_key_fromdns_ex(const dns_name_t *name, dns_rdataclass_t rdclass,
+ isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
+ dst_key_t **keyp);
+isc_result_t
dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp);
/*%<
diff --git a/lib/dns/mapapi b/lib/dns/mapapi
index 1b502d3..a46e190 100644
--- a/lib/dns/mapapi
+++ b/lib/dns/mapapi
@@ -13,4 +13,4 @@
# Whenever releasing a new major release of BIND9, set this value
# back to 1.0 when releasing the first alpha. Map files are *never*
# compatible across major releases.
-MAPAPI=3.0
+MAPAPI=4.0
diff --git a/lib/dns/master.c b/lib/dns/master.c
index fc56107..024fbd5 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 09645c2..22aa552 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/string.h> /* Required for HP/UX (and others?) */
@@ -507,9 +509,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);
@@ -799,6 +803,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;
@@ -817,29 +833,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
@@ -966,6 +979,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) {
@@ -975,13 +1000,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;
@@ -1002,13 +1033,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.
@@ -1020,19 +1057,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.
*/
@@ -1063,14 +1106,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);
@@ -1083,6 +1118,7 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
result = ISC_R_NOMEMORY;
goto cleanup;
}
+ dns_rdataset_init(rdataset);
/*
* Convert rdatalist to rdataset, and attach the latter to
@@ -1091,32 +1127,71 @@ 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;
- }
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
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);
}
@@ -1196,17 +1271,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;
@@ -1214,10 +1296,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);
@@ -1257,8 +1339,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;
}
@@ -1365,10 +1447,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))
{
@@ -1456,34 +1534,71 @@ 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);
+ if (rdatalist == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ dns_message_gettemprdataset(msg, &rdataset);
+ if (rdataset == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ rdatalist->type = rdtype;
+ rdatalist->covers = covers;
+ rdatalist->rdclass = rdclass;
+ rdatalist->ttl = ttl;
+
+ 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
@@ -1493,63 +1608,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);
- if (rdataset == NULL) {
- result = ISC_R_NOMEMORY;
- goto cleanup;
- }
- 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();
}
}
@@ -1584,8 +1707,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);
@@ -1596,8 +1717,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;
@@ -1607,22 +1726,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);
}
/*
@@ -1640,16 +1754,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);
@@ -1789,6 +1911,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);
@@ -2445,7 +2568,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;
/*
@@ -2493,22 +2616,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);
@@ -2599,6 +2706,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 96f95b3..a170269 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 7f68580..b9702eb 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,
diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c
index 1f2a2e0..09412c5 100644
--- a/lib/dns/opensslrsa_link.c
+++ b/lib/dns/opensslrsa_link.c
@@ -895,9 +895,10 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
#if !defined(OPENSSL_NO_ENGINE)
ENGINE *ep = NULL;
const BIGNUM *ex = NULL;
+ const char *engine = NULL;
#endif /* if !defined(OPENSSL_NO_ENGINE) */
isc_mem_t *mctx = key->mctx;
- 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;
@@ -930,9 +931,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;
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 d5d18b8..780a950 100644
--- a/lib/dns/rbt.c
+++ b/lib/dns/rbt.c
@@ -2307,6 +2307,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 ee06c51..723d169 100644
--- a/lib/dns/rbtdb.c
+++ b/lib/dns/rbtdb.c
@@ -116,7 +116,7 @@ struct rbtdb_file_header {
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) | \
@@ -521,6 +521,10 @@ struct dns_rbtdb {
*/
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
@@ -1067,6 +1071,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;
@@ -1092,8 +1097,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);
@@ -1101,6 +1104,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;
}
@@ -1935,19 +1944,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);
+ }
}
/*%
@@ -2222,17 +2244,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);
@@ -2240,44 +2271,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);
@@ -8735,6 +8782,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++) {
@@ -10070,7 +10119,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;
}
diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c
index a283831..3b49819 100644
--- a/lib/dns/rdata.c
+++ b/lib/dns/rdata.c
@@ -2057,7 +2057,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 a97aaa8..0952624 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -10634,8 +10634,8 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr,
* Since we have a pool of tasks we bind them to task queues
* to spread the load evenly
*/
- result = isc_task_create_bound(taskmgr, 0,
- &res->buckets[i].task, i);
+ result = isc_task_create_bound(
+ taskmgr, 0, &res->buckets[i].task, ISC_NM_TASK_SLOW(i));
if (result != ISC_R_SUCCESS) {
isc_mutex_destroy(&res->buckets[i].lock);
goto cleanup_buckets;
diff --git a/lib/dns/result.c b/lib/dns/result.c
index 9921291..f07c2f1 100644
--- a/lib/dns/result.c
+++ b/lib/dns/result.c
@@ -405,7 +405,7 @@ dns_result_torcode(isc_result_t result) {
* Rcodes can't be bigger than 12 bits, which is why we
* AND with 0xFFF instead of 0xFFFF.
*/
- return ((dns_rcode_t)((result)&0xFFF));
+ return ((dns_rcode_t)((result) & 0xFFF));
}
/*
diff --git a/lib/dns/rootns.c b/lib/dns/rootns.c
index 69e2667..84f841a 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/rpz.c b/lib/dns/rpz.c
index 20db72f..fdc9759 100644
--- a/lib/dns/rpz.c
+++ b/lib/dns/rpz.c
@@ -1544,7 +1544,7 @@ dns_rpz_new_zone(dns_rpz_zones_t *rpzs, dns_rpz_zone_t **rpzp) {
* simplifies update_from_db
*/
- isc_ht_init(&zone->nodes, rpzs->mctx, 1);
+ isc_ht_init(&zone->nodes, rpzs->mctx, 1, ISC_HT_CASE_SENSITIVE);
dns_name_init(&zone->origin, NULL);
dns_name_init(&zone->client_ip, NULL);
@@ -1722,7 +1722,8 @@ setup_update(dns_rpz_zone_t *rpz) {
ISC_LOG_DEBUG(1), "rpz: %s: using hashtable size %d",
domain, hashsize);
- isc_ht_init(&rpz->newnodes, rpz->rpzs->mctx, hashsize);
+ isc_ht_init(&rpz->newnodes, rpz->rpzs->mctx, hashsize,
+ ISC_HT_CASE_SENSITIVE);
result = dns_db_createiterator(rpz->updb, DNS_DB_NONSEC3, &rpz->updbit);
if (result != ISC_R_SUCCESS) {
diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c
index e102d09..8f4c3b9 100644
--- a/lib/dns/tsig.c
+++ b/lib/dns/tsig.c
@@ -1744,8 +1744,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);
@@ -1757,25 +1758,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
@@ -1790,7 +1796,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 9d71238..5fc9605 100644
--- a/lib/dns/update.c
+++ b/lib/dns/update.c
@@ -1090,8 +1090,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);
@@ -1224,7 +1224,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.
@@ -1382,8 +1382,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;
@@ -1433,7 +1434,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;
@@ -1482,7 +1483,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 {
@@ -1528,7 +1529,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;
@@ -1565,16 +1565,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;
}
/*
@@ -1690,8 +1691,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++;
}
@@ -1893,9 +1894,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);
@@ -1971,8 +1973,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 {
@@ -2100,9 +2102,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,
@@ -2146,8 +2149,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 6cf717f..243b19f 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/win32/libdns.def.in b/lib/dns/win32/libdns.def.in
index 5c0ba7c..610d3ed 100644
--- a/lib/dns/win32/libdns.def.in
+++ b/lib/dns/win32/libdns.def.in
@@ -535,7 +535,6 @@ dns_message_clonebuffer
dns_message_create
dns_message_currentname
dns_message_detach
-dns_message_find
dns_message_findname
dns_message_findtype
dns_message_firstname
@@ -554,7 +553,6 @@ dns_message_gettsigkey
dns_message_headertotext
dns_message_logfmtpacket
dns_message_logpacket
-dns_message_movename
dns_message_nextname
dns_message_parse
dns_message_peekheader
@@ -1467,6 +1465,7 @@ dst_key_format
dst_key_free
dst_key_frombuffer
dst_key_fromdns
+dst_key_fromdns_ex
dst_key_fromfile
dst_key_fromgssapi
dst_key_fromlabel
diff --git a/lib/dns/zone.c b/lib/dns/zone.c
index 73da12e..ea02456 100644
--- a/lib/dns/zone.c
+++ b/lib/dns/zone.c
@@ -125,7 +125,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
@@ -7034,8 +7034,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;
@@ -7227,7 +7228,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.
@@ -7446,7 +7447,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) {
@@ -7509,7 +7510,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,
@@ -7745,10 +7746,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;
@@ -7843,8 +7845,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) {
@@ -8447,8 +8449,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",
@@ -9222,7 +9224,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,
@@ -9843,8 +9845,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));
/*
@@ -9979,7 +9981,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",
@@ -17612,6 +17614,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) {
@@ -20405,7 +20413,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) {
diff --git a/lib/isc/ht.c b/lib/isc/ht.c
index 07a36b4..e11050f 100644
--- a/lib/isc/ht.c
+++ b/lib/isc/ht.c
@@ -27,51 +27,274 @@ typedef struct isc_ht_node isc_ht_node_t;
#define ISC_HT_MAGIC ISC_MAGIC('H', 'T', 'a', 'b')
#define ISC_HT_VALID(ht) ISC_MAGIC_VALID(ht, ISC_HT_MAGIC)
+#define HT_NO_BITS 0
+#define HT_MIN_BITS 1
+#define HT_MAX_BITS 32
+#define HT_OVERCOMMIT 3
+
+#define HT_NEXTTABLE(idx) ((idx == 0) ? 1 : 0)
+#define TRY_NEXTTABLE(idx, ht) (idx == ht->hindex && rehashing_in_progress(ht))
+
+#define GOLDEN_RATIO_32 0x61C88647
+
+#define HASHSIZE(bits) (UINT64_C(1) << (bits))
+
struct isc_ht_node {
void *value;
isc_ht_node_t *next;
+ uint32_t hashval;
size_t keysize;
- unsigned char key[FLEXIBLE_ARRAY_MEMBER];
+ unsigned char key[];
};
struct isc_ht {
unsigned int magic;
isc_mem_t *mctx;
- size_t size;
- size_t mask;
- unsigned int count;
- isc_ht_node_t **table;
+ size_t count;
+ bool case_sensitive;
+ size_t size[2];
+ uint8_t hashbits[2];
+ isc_ht_node_t **table[2];
+ uint8_t hindex;
+ uint32_t hiter; /* rehashing iterator */
};
struct isc_ht_iter {
isc_ht_t *ht;
size_t i;
+ uint8_t hindex;
isc_ht_node_t *cur;
};
+static isc_ht_node_t *
+isc__ht_find(const isc_ht_t *ht, const unsigned char *key,
+ const uint32_t keysize, const uint32_t hashval, const uint8_t idx);
+static void
+isc__ht_add(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize,
+ const uint32_t hashval, const uint8_t idx, void *value);
+static isc_result_t
+isc__ht_delete(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize,
+ const uint32_t hashval, const uint8_t idx);
+
+static uint32_t
+rehash_bits(isc_ht_t *ht, size_t newcount);
+
+static void
+hashtable_new(isc_ht_t *ht, const uint8_t idx, const uint8_t bits);
+static void
+hashtable_free(isc_ht_t *ht, const uint8_t idx);
+static void
+hashtable_rehash(isc_ht_t *ht, uint32_t newbits);
+static void
+hashtable_rehash_one(isc_ht_t *ht);
+static void
+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, bool case_sensitive) {
+ return (node->hashval == hashval && node->keysize == keysize &&
+ (case_sensitive ? (memcmp(node->key, key, keysize) == 0)
+ : (memcasecmp(node->key, key, keysize) == 0)));
+}
+
+static uint32_t
+hash_32(uint32_t val, unsigned int bits) {
+ REQUIRE(bits <= HT_MAX_BITS);
+ /* High bits are more random. */
+ return (val * GOLDEN_RATIO_32 >> (32 - bits));
+}
+
+static bool
+rehashing_in_progress(const isc_ht_t *ht) {
+ return (ht->table[HT_NEXTTABLE(ht->hindex)] != NULL);
+}
+
+static bool
+hashtable_is_overcommited(isc_ht_t *ht) {
+ return (ht->count >= (ht->size[ht->hindex] * HT_OVERCOMMIT));
+}
+
+static uint32_t
+rehash_bits(isc_ht_t *ht, size_t newcount) {
+ uint32_t newbits = ht->hashbits[ht->hindex];
+
+ while (newcount >= HASHSIZE(newbits) && newbits <= HT_MAX_BITS) {
+ newbits += 1;
+ }
+
+ return (newbits);
+}
+
+/*
+ * Rebuild the hashtable to reduce the load factor
+ */
+static void
+hashtable_rehash(isc_ht_t *ht, uint32_t newbits) {
+ uint8_t oldindex = ht->hindex;
+ uint32_t oldbits = ht->hashbits[oldindex];
+ uint8_t newindex = HT_NEXTTABLE(oldindex);
+
+ REQUIRE(ht->hashbits[oldindex] >= HT_MIN_BITS);
+ REQUIRE(ht->hashbits[oldindex] <= HT_MAX_BITS);
+ REQUIRE(ht->table[oldindex] != NULL);
+
+ REQUIRE(newbits <= HT_MAX_BITS);
+ REQUIRE(ht->hashbits[newindex] == HT_NO_BITS);
+ REQUIRE(ht->table[newindex] == NULL);
+
+ REQUIRE(newbits > oldbits);
+
+ hashtable_new(ht, newindex, newbits);
+
+ ht->hindex = newindex;
+
+ hashtable_rehash_one(ht);
+}
+
+static void
+hashtable_rehash_one(isc_ht_t *ht) {
+ isc_ht_node_t **newtable = ht->table[ht->hindex];
+ uint32_t oldsize = ht->size[HT_NEXTTABLE(ht->hindex)];
+ isc_ht_node_t **oldtable = ht->table[HT_NEXTTABLE(ht->hindex)];
+ isc_ht_node_t *node = NULL;
+ isc_ht_node_t *nextnode;
+
+ /* Find first non-empty node */
+ while (ht->hiter < oldsize && oldtable[ht->hiter] == NULL) {
+ ht->hiter++;
+ }
+
+ /* Rehashing complete */
+ if (ht->hiter == oldsize) {
+ hashtable_free(ht, HT_NEXTTABLE(ht->hindex));
+ ht->hiter = 0;
+ return;
+ }
+
+ /* Move the first non-empty node from old hashtable to new hashtable */
+ for (node = oldtable[ht->hiter]; node != NULL; node = nextnode) {
+ uint32_t hash = hash_32(node->hashval,
+ ht->hashbits[ht->hindex]);
+ nextnode = node->next;
+ node->next = newtable[hash];
+ newtable[hash] = node;
+ }
+
+ oldtable[ht->hiter] = NULL;
+
+ ht->hiter++;
+}
+
+static void
+maybe_rehash(isc_ht_t *ht, size_t newcount) {
+ uint32_t newbits = rehash_bits(ht, newcount);
+
+ if (ht->hashbits[ht->hindex] < newbits && newbits <= HT_MAX_BITS) {
+ hashtable_rehash(ht, newbits);
+ }
+}
+
+static void
+hashtable_new(isc_ht_t *ht, const uint8_t idx, const uint8_t bits) {
+ size_t size;
+ REQUIRE(ht->hashbits[idx] == HT_NO_BITS);
+ REQUIRE(ht->table[idx] == NULL);
+ REQUIRE(bits >= HT_MIN_BITS);
+ REQUIRE(bits <= HT_MAX_BITS);
+
+ ht->hashbits[idx] = bits;
+ ht->size[idx] = HASHSIZE(ht->hashbits[idx]);
+
+ size = ht->size[idx] * sizeof(isc_ht_node_t *);
+
+ ht->table[idx] = isc_mem_get(ht->mctx, size);
+ memset(ht->table[idx], 0, size);
+}
+
+static void
+hashtable_free(isc_ht_t *ht, const uint8_t idx) {
+ size_t size = ht->size[idx] * sizeof(isc_ht_node_t *);
+
+ for (size_t i = 0; i < ht->size[idx]; i++) {
+ isc_ht_node_t *node = ht->table[idx][i];
+ while (node != NULL) {
+ isc_ht_node_t *next = node->next;
+ ht->count--;
+ isc_mem_put(ht->mctx, node,
+ sizeof(*node) + node->keysize);
+ node = next;
+ }
+ }
+
+ isc_mem_put(ht->mctx, ht->table[idx], size);
+ ht->hashbits[idx] = HT_NO_BITS;
+ ht->table[idx] = NULL;
+}
+
void
-isc_ht_init(isc_ht_t **htp, isc_mem_t *mctx, uint8_t bits) {
+isc_ht_init(isc_ht_t **htp, isc_mem_t *mctx, uint8_t bits,
+ unsigned int options) {
isc_ht_t *ht = NULL;
- size_t i;
+ bool case_sensitive = ((options & ISC_HT_CASE_INSENSITIVE) == 0);
REQUIRE(htp != NULL && *htp == NULL);
REQUIRE(mctx != NULL);
- REQUIRE(bits >= 1 && bits <= (sizeof(size_t) * 8 - 1));
+ REQUIRE(bits >= 1 && bits <= HT_MAX_BITS);
- ht = isc_mem_get(mctx, sizeof(struct isc_ht));
+ ht = isc_mem_get(mctx, sizeof(*ht));
+ *ht = (isc_ht_t){
+ .case_sensitive = case_sensitive,
+ };
- ht->mctx = NULL;
isc_mem_attach(mctx, &ht->mctx);
- ht->size = ((size_t)1 << bits);
- ht->mask = ((size_t)1 << bits) - 1;
- ht->count = 0;
-
- ht->table = isc_mem_get(ht->mctx, ht->size * sizeof(isc_ht_node_t *));
-
- for (i = 0; i < ht->size; i++) {
- ht->table[i] = NULL;
- }
+ hashtable_new(ht, 0, bits);
ht->magic = ISC_HT_MAGIC;
@@ -81,128 +304,186 @@ isc_ht_init(isc_ht_t **htp, isc_mem_t *mctx, uint8_t bits) {
void
isc_ht_destroy(isc_ht_t **htp) {
isc_ht_t *ht;
- size_t i;
REQUIRE(htp != NULL);
+ REQUIRE(ISC_HT_VALID(*htp));
ht = *htp;
*htp = NULL;
-
- REQUIRE(ISC_HT_VALID(ht));
-
ht->magic = 0;
- for (i = 0; i < ht->size; i++) {
- isc_ht_node_t *node = ht->table[i];
- while (node != NULL) {
- isc_ht_node_t *next = node->next;
- ht->count--;
- isc_mem_put(ht->mctx, node,
- offsetof(isc_ht_node_t, key) +
- node->keysize);
- node = next;
+ for (size_t i = 0; i <= 1; i++) {
+ if (ht->table[i] != NULL) {
+ hashtable_free(ht, i);
}
}
INSIST(ht->count == 0);
- isc_mem_put(ht->mctx, ht->table, ht->size * sizeof(isc_ht_node_t *));
- isc_mem_putanddetach(&ht->mctx, ht, sizeof(struct isc_ht));
+ isc_mem_putanddetach(&ht->mctx, ht, sizeof(*ht));
}
-isc_result_t
-isc_ht_add(isc_ht_t *ht, const unsigned char *key, uint32_t keysize,
- void *value) {
+static void
+isc__ht_add(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize,
+ const uint32_t hashval, const uint8_t idx, void *value) {
isc_ht_node_t *node;
uint32_t hash;
+ hash = hash_32(hashval, ht->hashbits[idx]);
+
+ node = isc_mem_get(ht->mctx, sizeof(*node) + keysize);
+ *node = (isc_ht_node_t){
+ .keysize = keysize,
+ .hashval = hashval,
+ .next = ht->table[idx][hash],
+ .value = value,
+ };
+
+ memmove(node->key, key, keysize);
+
+ ht->count++;
+ ht->table[idx][hash] = node;
+}
+
+isc_result_t
+isc_ht_add(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize,
+ void *value) {
+ uint32_t hashval;
+
REQUIRE(ISC_HT_VALID(ht));
REQUIRE(key != NULL && keysize > 0);
- hash = isc_hash_function(key, keysize, true);
- node = ht->table[hash & ht->mask];
- while (node != NULL) {
- if (keysize == node->keysize &&
- memcmp(key, node->key, keysize) == 0)
- {
- return (ISC_R_EXISTS);
- }
- node = node->next;
+ if (rehashing_in_progress(ht)) {
+ /* Rehash in progress */
+ hashtable_rehash_one(ht);
+ } else if (hashtable_is_overcommited(ht)) {
+ /* Rehash requested */
+ maybe_rehash(ht, ht->count);
}
- node = isc_mem_get(ht->mctx, offsetof(isc_ht_node_t, key) + keysize);
+ hashval = isc_hash32(key, keysize, ht->case_sensitive);
- memmove(node->key, key, keysize);
- node->keysize = keysize;
- node->next = ht->table[hash & ht->mask];
- node->value = value;
+ if (isc__ht_find(ht, key, keysize, hashval, ht->hindex) != NULL) {
+ return (ISC_R_EXISTS);
+ }
+
+ isc__ht_add(ht, key, keysize, hashval, ht->hindex, value);
- ht->count++;
- ht->table[hash & ht->mask] = node;
return (ISC_R_SUCCESS);
}
+static isc_ht_node_t *
+isc__ht_find(const isc_ht_t *ht, const unsigned char *key,
+ const uint32_t keysize, const uint32_t hashval,
+ const uint8_t idx) {
+ uint32_t hash;
+ uint8_t findex = idx;
+
+nexttable:
+ hash = hash_32(hashval, ht->hashbits[findex]);
+ for (isc_ht_node_t *node = ht->table[findex][hash]; node != NULL;
+ node = node->next)
+ {
+ if (isc__ht_node_match(node, hashval, key, keysize,
+ ht->case_sensitive))
+ {
+ return (node);
+ }
+ }
+ if (TRY_NEXTTABLE(findex, ht)) {
+ /*
+ * Rehashing in progress, check the other table
+ */
+ findex = HT_NEXTTABLE(findex);
+ goto nexttable;
+ }
+
+ return (NULL);
+}
+
isc_result_t
-isc_ht_find(const isc_ht_t *ht, const unsigned char *key, uint32_t keysize,
- void **valuep) {
+isc_ht_find(const isc_ht_t *ht, const unsigned char *key,
+ const uint32_t keysize, void **valuep) {
+ uint32_t hashval;
isc_ht_node_t *node;
- uint32_t hash;
REQUIRE(ISC_HT_VALID(ht));
REQUIRE(key != NULL && keysize > 0);
REQUIRE(valuep == NULL || *valuep == NULL);
- hash = isc_hash_function(key, keysize, true);
- node = ht->table[hash & ht->mask];
- while (node != NULL) {
- if (keysize == node->keysize &&
- memcmp(key, node->key, keysize) == 0)
- {
- if (valuep != NULL) {
- *valuep = node->value;
- }
- return (ISC_R_SUCCESS);
- }
- node = node->next;
+ hashval = isc_hash32(key, keysize, ht->case_sensitive);
+
+ node = isc__ht_find(ht, key, keysize, hashval, ht->hindex);
+ if (node == NULL) {
+ return (ISC_R_NOTFOUND);
}
- return (ISC_R_NOTFOUND);
+ if (valuep != NULL) {
+ *valuep = node->value;
+ }
+ return (ISC_R_SUCCESS);
}
-isc_result_t
-isc_ht_delete(isc_ht_t *ht, const unsigned char *key, uint32_t keysize) {
- isc_ht_node_t *node, *prev;
+static isc_result_t
+isc__ht_delete(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize,
+ const uint32_t hashval, const uint8_t idx) {
+ isc_ht_node_t *prev = NULL;
uint32_t hash;
- REQUIRE(ISC_HT_VALID(ht));
- REQUIRE(key != NULL && keysize > 0);
+ hash = hash_32(hashval, ht->hashbits[idx]);
- prev = NULL;
- hash = isc_hash_function(key, keysize, true);
- node = ht->table[hash & ht->mask];
- while (node != NULL) {
- if (keysize == node->keysize &&
- memcmp(key, node->key, keysize) == 0)
+ 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,
+ ht->case_sensitive))
{
if (prev == NULL) {
- ht->table[hash & ht->mask] = node->next;
+ ht->table[idx][hash] = node->next;
} else {
prev->next = node->next;
}
isc_mem_put(ht->mctx, node,
- offsetof(isc_ht_node_t, key) +
- node->keysize);
+ sizeof(*node) + node->keysize);
ht->count--;
return (ISC_R_SUCCESS);
}
-
- prev = node;
- node = node->next;
}
+
return (ISC_R_NOTFOUND);
}
+isc_result_t
+isc_ht_delete(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize) {
+ uint32_t hashval;
+ uint8_t hindex;
+ isc_result_t result;
+
+ REQUIRE(ISC_HT_VALID(ht));
+ REQUIRE(key != NULL && keysize > 0);
+
+ if (rehashing_in_progress(ht)) {
+ /* Rehash in progress */
+ hashtable_rehash_one(ht);
+ }
+
+ hindex = ht->hindex;
+ hashval = isc_hash32(key, keysize, ht->case_sensitive);
+nexttable:
+ result = isc__ht_delete(ht, key, keysize, hashval, hindex);
+
+ if (result == ISC_R_NOTFOUND && TRY_NEXTTABLE(hindex, ht)) {
+ /*
+ * Rehashing in progress, check the other table
+ */
+ hindex = HT_NEXTTABLE(hindex);
+ goto nexttable;
+ }
+
+ return (result);
+}
+
void
isc_ht_iter_create(isc_ht_t *ht, isc_ht_iter_t **itp) {
isc_ht_iter_t *it;
@@ -211,10 +492,10 @@ isc_ht_iter_create(isc_ht_t *ht, isc_ht_iter_t **itp) {
REQUIRE(itp != NULL && *itp == NULL);
it = isc_mem_get(ht->mctx, sizeof(isc_ht_iter_t));
-
- it->ht = ht;
- it->i = 0;
- it->cur = NULL;
+ *it = (isc_ht_iter_t){
+ .ht = ht,
+ .hindex = ht->hindex,
+ };
*itp = it;
}
@@ -229,25 +510,46 @@ isc_ht_iter_destroy(isc_ht_iter_t **itp) {
it = *itp;
*itp = NULL;
ht = it->ht;
- isc_mem_put(ht->mctx, it, sizeof(isc_ht_iter_t));
+ isc_mem_put(ht->mctx, it, sizeof(*it));
}
isc_result_t
isc_ht_iter_first(isc_ht_iter_t *it) {
+ isc_ht_t *ht;
+
REQUIRE(it != NULL);
+ ht = it->ht;
+
+ it->hindex = ht->hindex;
it->i = 0;
- while (it->i < it->ht->size && it->ht->table[it->i] == NULL) {
+
+ return (isc__ht_iter_next(it));
+}
+
+static isc_result_t
+isc__ht_iter_next(isc_ht_iter_t *it) {
+ isc_ht_t *ht = it->ht;
+
+ while (it->i < ht->size[it->hindex] &&
+ ht->table[it->hindex][it->i] == NULL)
+ {
it->i++;
}
- if (it->i == it->ht->size) {
- return (ISC_R_NOMORE);
+ if (it->i < ht->size[it->hindex]) {
+ it->cur = ht->table[it->hindex][it->i];
+
+ return (ISC_R_SUCCESS);
}
- it->cur = it->ht->table[it->i];
+ if (TRY_NEXTTABLE(it->hindex, ht)) {
+ it->hindex = HT_NEXTTABLE(it->hindex);
+ it->i = 0;
+ return (isc__ht_iter_next(it));
+ }
- return (ISC_R_SUCCESS);
+ return (ISC_R_NOMORE);
}
isc_result_t
@@ -256,60 +558,36 @@ isc_ht_iter_next(isc_ht_iter_t *it) {
REQUIRE(it->cur != NULL);
it->cur = it->cur->next;
- if (it->cur == NULL) {
- do {
- it->i++;
- } while (it->i < it->ht->size && it->ht->table[it->i] == NULL);
- if (it->i >= it->ht->size) {
- return (ISC_R_NOMORE);
- }
- it->cur = it->ht->table[it->i];
+
+ if (it->cur != NULL) {
+ return (ISC_R_SUCCESS);
}
- return (ISC_R_SUCCESS);
+ it->i++;
+
+ return (isc__ht_iter_next(it));
}
isc_result_t
isc_ht_iter_delcurrent_next(isc_ht_iter_t *it) {
isc_result_t result = ISC_R_SUCCESS;
- isc_ht_node_t *to_delete = NULL;
- isc_ht_node_t *prev = NULL;
- isc_ht_node_t *node = NULL;
- uint32_t hash;
+ isc_ht_node_t *dnode = NULL;
+ uint8_t dindex;
isc_ht_t *ht;
+ isc_result_t dresult;
+
REQUIRE(it != NULL);
REQUIRE(it->cur != NULL);
- to_delete = it->cur;
- ht = it->ht;
- it->cur = it->cur->next;
- if (it->cur == NULL) {
- do {
- it->i++;
- } while (it->i < ht->size && ht->table[it->i] == NULL);
- if (it->i >= ht->size) {
- result = ISC_R_NOMORE;
- } else {
- it->cur = ht->table[it->i];
- }
- }
+ ht = it->ht;
+ dnode = it->cur;
+ dindex = it->hindex;
- hash = isc_hash_function(to_delete->key, to_delete->keysize, true);
- node = ht->table[hash & ht->mask];
- while (node != to_delete) {
- prev = node;
- node = node->next;
- INSIST(node != NULL);
- }
+ result = isc_ht_iter_next(it);
- if (prev == NULL) {
- ht->table[hash & ht->mask] = node->next;
- } else {
- prev->next = node->next;
- }
- isc_mem_put(ht->mctx, node,
- offsetof(isc_ht_node_t, key) + node->keysize);
- ht->count--;
+ dresult = isc__ht_delete(ht, dnode->key, dnode->keysize, dnode->hashval,
+ dindex);
+ INSIST(dresult == ISC_R_SUCCESS);
return (result);
}
@@ -334,8 +612,8 @@ isc_ht_iter_currentkey(isc_ht_iter_t *it, unsigned char **key,
*keysize = it->cur->keysize;
}
-unsigned int
-isc_ht_count(isc_ht_t *ht) {
+size_t
+isc_ht_count(const isc_ht_t *ht) {
REQUIRE(ISC_HT_VALID(ht));
return (ht->count);
diff --git a/lib/isc/include/isc/endian.h b/lib/isc/include/isc/endian.h
index e598a7b..9b4f635 100644
--- a/lib/isc/include/isc/endian.h
+++ b/lib/isc/include/isc/endian.h
@@ -110,29 +110,29 @@
#include <inttypes.h>
#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/ht.h b/lib/isc/include/isc/ht.h
index f1386bb..163fbef 100644
--- a/lib/isc/include/isc/ht.h
+++ b/lib/isc/include/isc/ht.h
@@ -13,8 +13,7 @@
/* ! \file */
-#ifndef ISC_HT_H
-#define ISC_HT_H 1
+#pragma once
#include <inttypes.h>
#include <string.h>
@@ -25,9 +24,15 @@
typedef struct isc_ht isc_ht_t;
typedef struct isc_ht_iter isc_ht_iter_t;
+enum { ISC_HT_CASE_SENSITIVE = 0x00, ISC_HT_CASE_INSENSITIVE = 0x01 };
+
/*%
* Initialize hashtable at *htp, using memory context and size of (1<<bits)
*
+ * If 'options' contains ISC_HT_CASE_INSENSITIVE, then upper- and lower-case
+ * letters in key values will generate the same hash values; this can be used
+ * when the key for a hash table is a DNS name.
+ *
* Requires:
*\li 'htp' is not NULL and '*htp' is NULL.
*\li 'mctx' is a valid memory context.
@@ -35,7 +40,8 @@ typedef struct isc_ht_iter isc_ht_iter_t;
*
*/
void
-isc_ht_init(isc_ht_t **htp, isc_mem_t *mctx, uint8_t bits);
+isc_ht_init(isc_ht_t **htp, isc_mem_t *mctx, uint8_t bits,
+ unsigned int options);
/*%
* Destroy hashtable, freeing everything
@@ -52,6 +58,7 @@ isc_ht_destroy(isc_ht_t **htp);
*
* Requires:
*\li 'ht' is a valid hashtable
+ *\li write-lock
*
* Returns:
*\li #ISC_R_NOMEMORY -- not enough memory to create pool
@@ -59,7 +66,7 @@ isc_ht_destroy(isc_ht_t **htp);
*\li #ISC_R_SUCCESS -- all is well.
*/
isc_result_t
-isc_ht_add(isc_ht_t *ht, const unsigned char *key, uint32_t keysize,
+isc_ht_add(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize,
void *value);
/*%
@@ -70,27 +77,29 @@ isc_ht_add(isc_ht_t *ht, const unsigned char *key, uint32_t keysize,
*
* Requires:
* \li 'ht' is a valid hashtable
+ * \li read-lock
*
* Returns:
* \li #ISC_R_SUCCESS -- success
* \li #ISC_R_NOTFOUND -- key not found
*/
isc_result_t
-isc_ht_find(const isc_ht_t *ht, const unsigned char *key, uint32_t keysize,
- void **valuep);
+isc_ht_find(const isc_ht_t *ht, const unsigned char *key,
+ const uint32_t keysize, void **valuep);
/*%
* Delete node from hashtable
*
* Requires:
*\li ht is a valid hashtable
+ *\li write-lock
*
* Returns:
*\li #ISC_R_NOTFOUND -- key not found
*\li #ISC_R_SUCCESS -- all is well
*/
isc_result_t
-isc_ht_delete(isc_ht_t *ht, const unsigned char *key, uint32_t keysize);
+isc_ht_delete(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize);
/*%
* Create an iterator for the hashtable; point '*itp' to it.
@@ -178,6 +187,5 @@ isc_ht_iter_currentkey(isc_ht_iter_t *it, unsigned char **key, size_t *keysize);
* Requires:
*\li 'ht' is a valid hashtable
*/
-unsigned int
-isc_ht_count(isc_ht_t *ht);
-#endif /* ifndef ISC_HT_H */
+size_t
+isc_ht_count(const isc_ht_t *ht);
diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h
index f1747be..efeb5f3 100644
--- a/lib/isc/include/isc/netmgr.h
+++ b/lib/isc/include/isc/netmgr.h
@@ -479,6 +479,9 @@ isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
* 'cb'.
*/
+#define ISC_NM_TASK_SLOW_OFFSET -2
+#define ISC_NM_TASK_SLOW(i) (ISC_NM_TASK_SLOW_OFFSET - 1 - i)
+
void
isc_nm_task_enqueue(isc_nm_t *mgr, isc_task_t *task, int threadid);
/*%<
diff --git a/lib/isc/include/isc/radix.h b/lib/isc/include/isc/radix.h
index 7c004e9..93b0aae 100644
--- a/lib/isc/include/isc/radix.h
+++ b/lib/isc/include/isc/radix.h
@@ -193,7 +193,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/resultclass.h b/lib/isc/include/isc/resultclass.h
index a3a5079..61c5d7b 100644
--- a/lib/isc/include/isc/resultclass.h
+++ b/lib/isc/include/isc/resultclass.h
@@ -29,7 +29,7 @@
#define ISC_RESULTCLASS_TONUM(rclass) ((rclass) >> 16)
#define ISC_RESULTCLASS_SIZE 65536
#define ISC_RESULTCLASS_INCLASS(rclass, result) \
- ((rclass) == ((result)&0xFFFF0000))
+ ((rclass) == ((result) & 0xFFFF0000))
#define ISC_RESULTCLASS_ISC ISC_RESULTCLASS_FROMNUM(0)
#define ISC_RESULTCLASS_DNS ISC_RESULTCLASS_FROMNUM(1)
diff --git a/lib/isc/netaddr.c b/lib/isc/netaddr.c
index 39aaae6..62ce195 100644
--- a/lib/isc/netaddr.c
+++ b/lib/isc/netaddr.c
@@ -436,7 +436,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/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h
index 05fde1a..c3a1762 100644
--- a/lib/isc/netmgr/netmgr-int.h
+++ b/lib/isc/netmgr/netmgr-int.h
@@ -655,6 +655,7 @@ struct isc_nm {
isc_refcount_t references;
isc_mem_t *mctx;
int nworkers;
+ int nlisteners;
isc_mutex_t lock;
isc_condition_t wkstatecond;
isc_condition_t wkpausecond;
diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c
index 6f42ec9..7bff1cc 100644
--- a/lib/isc/netmgr/netmgr.c
+++ b/lib/isc/netmgr/netmgr.c
@@ -231,12 +231,12 @@ isc__nm_winsock_destroy(void) {
#endif /* WIN32 */
static void
-isc__nm_threadpool_initialize(uint32_t workers) {
+isc__nm_threadpool_initialize(uint32_t nworkers) {
char buf[11];
int r = uv_os_getenv("UV_THREADPOOL_SIZE", buf,
&(size_t){ sizeof(buf) });
if (r == UV_ENOENT) {
- snprintf(buf, sizeof(buf), "%" PRIu32, workers);
+ snprintf(buf, sizeof(buf), "%" PRIu32, nworkers);
uv_os_setenv("UV_THREADPOOL_SIZE", buf);
}
}
@@ -254,11 +254,11 @@ isc__nm_threadpool_initialize(uint32_t workers) {
#endif
void
-isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) {
+isc__netmgr_create(isc_mem_t *mctx, uint32_t nworkers, isc_nm_t **netmgrp) {
isc_nm_t *mgr = NULL;
char name[32];
- REQUIRE(workers > 0);
+ REQUIRE(nworkers > 0);
#ifdef MAXIMAL_UV_VERSION
if (uv_version() > MAXIMAL_UV_VERSION) {
@@ -282,10 +282,13 @@ isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) {
isc__nm_winsock_initialize();
#endif /* WIN32 */
- isc__nm_threadpool_initialize(workers);
+ isc__nm_threadpool_initialize(nworkers);
mgr = isc_mem_get(mctx, sizeof(*mgr));
- *mgr = (isc_nm_t){ .nworkers = workers };
+ *mgr = (isc_nm_t){
+ .nworkers = nworkers * 2,
+ .nlisteners = nworkers,
+ };
isc_mem_attach(mctx, &mgr->mctx);
isc_mutex_init(&mgr->lock);
@@ -316,11 +319,12 @@ isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) {
atomic_init(&mgr->keepalive, 30000);
atomic_init(&mgr->advertised, 30000);
- isc_barrier_init(&mgr->pausing, workers);
- isc_barrier_init(&mgr->resuming, workers);
+ isc_barrier_init(&mgr->pausing, mgr->nworkers);
+ isc_barrier_init(&mgr->resuming, mgr->nworkers);
- mgr->workers = isc_mem_get(mctx, workers * sizeof(isc__networker_t));
- for (size_t i = 0; i < workers; i++) {
+ mgr->workers = isc_mem_get(mctx,
+ mgr->nworkers * sizeof(isc__networker_t));
+ for (int i = 0; i < mgr->nworkers; i++) {
isc__networker_t *worker = &mgr->workers[i];
int r;
@@ -354,7 +358,7 @@ isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) {
mgr->workers_running++;
isc_thread_create(nm_thread, &mgr->workers[i], &worker->thread);
- snprintf(name, sizeof(name), "isc-net-%04zu", i);
+ snprintf(name, sizeof(name), "isc-net-%04d", i);
isc_thread_setname(worker->thread, name);
}
@@ -840,9 +844,15 @@ isc_nm_task_enqueue(isc_nm_t *nm, isc_task_t *task, int threadid) {
isc__networker_t *worker = NULL;
if (threadid == -1) {
- tid = (int)isc_random_uniform(nm->nworkers);
+ tid = (int)isc_random_uniform(nm->nlisteners);
+ } else if (threadid == ISC_NM_TASK_SLOW_OFFSET) {
+ tid = nm->nlisteners +
+ (int)isc_random_uniform(nm->nworkers - nm->nlisteners);
+ } else if (threadid < ISC_NM_TASK_SLOW_OFFSET) {
+ tid = nm->nlisteners + (ISC_NM_TASK_SLOW(threadid) %
+ (nm->nworkers - nm->nlisteners));
} else {
- tid = threadid % nm->nworkers;
+ tid = threadid % nm->nlisteners;
}
worker = &nm->workers[tid];
diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c
index 821d6c4..1666318 100644
--- a/lib/isc/netmgr/tcp.c
+++ b/lib/isc/netmgr/tcp.c
@@ -323,7 +323,7 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
isc__nm_connectcb(sock, req, result, false);
} else {
isc__nmsocket_clearcb(sock);
- sock->tid = isc_random_uniform(mgr->nworkers);
+ sock->tid = isc_random_uniform(mgr->nlisteners);
isc__nm_connectcb(sock, req, result, true);
}
atomic_store(&sock->closed, true);
@@ -341,7 +341,7 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
isc__nm_put_netievent_tcpconnect(mgr, ievent);
} else {
atomic_init(&sock->active, false);
- sock->tid = isc_random_uniform(mgr->nworkers);
+ sock->tid = isc_random_uniform(mgr->nlisteners);
isc__nm_enqueue_ievent(&mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
@@ -445,7 +445,7 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_sockaddr_t *iface,
#if defined(WIN32)
sock->nchildren = 1;
#else
- sock->nchildren = mgr->nworkers;
+ sock->nchildren = mgr->nlisteners;
#endif
children_size = sock->nchildren * sizeof(sock->children[0]);
sock->children = isc_mem_get(mgr->mctx, children_size);
diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c
index bd593eb..037d74c 100644
--- a/lib/isc/netmgr/tcpdns.c
+++ b/lib/isc/netmgr/tcpdns.c
@@ -303,7 +303,7 @@ isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
isc__nm_put_netievent_tcpdnsconnect(mgr, ievent);
} else {
atomic_init(&sock->active, false);
- sock->tid = isc_random_uniform(mgr->nworkers);
+ sock->tid = isc_random_uniform(mgr->nlisteners);
isc__nm_enqueue_ievent(&mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
@@ -410,7 +410,7 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_sockaddr_t *iface,
#if defined(WIN32)
sock->nchildren = 1;
#else
- sock->nchildren = mgr->nworkers;
+ sock->nchildren = mgr->nlisteners;
#endif
children_size = sock->nchildren * sizeof(sock->children[0]);
sock->children = isc_mem_get(mgr->mctx, children_size);
diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c
index 00f9d40..bc59fca 100644
--- a/lib/isc/netmgr/udp.c
+++ b/lib/isc/netmgr/udp.c
@@ -136,7 +136,7 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_sockaddr_t *iface, isc_nm_recv_cb_t cb,
uv_os_sock_t fd = -1;
/*
- * We are creating mgr->nworkers duplicated sockets, one
+ * We are creating mgr->nlisteners duplicated sockets, one
* socket for each worker thread.
*/
sock = isc_mem_get(mgr->mctx, sizeof(isc_nmsocket_t));
@@ -146,7 +146,7 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_sockaddr_t *iface, isc_nm_recv_cb_t cb,
#if defined(WIN32)
sock->nchildren = 1;
#else
- sock->nchildren = mgr->nworkers;
+ sock->nchildren = mgr->nlisteners;
#endif
children_size = sock->nchildren * sizeof(sock->children[0]);
@@ -847,7 +847,7 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
isc__nm_put_netievent_udpconnect(mgr, event);
} else {
atomic_init(&sock->active, false);
- sock->tid = isc_random_uniform(mgr->nworkers);
+ sock->tid = isc_random_uniform(mgr->nlisteners);
isc__nm_enqueue_ievent(&mgr->workers[sock->tid],
(isc__netievent_t *)event);
}
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/tests/ht_test.c b/lib/isc/tests/ht_test.c
index 30cc615..cc824c3 100644
--- a/lib/isc/tests/ht_test.c
+++ b/lib/isc/tests/ht_test.c
@@ -61,7 +61,7 @@ test_ht_full(int bits, uintptr_t count) {
isc_result_t result;
uintptr_t i;
- isc_ht_init(&ht, test_mctx, bits);
+ isc_ht_init(&ht, test_mctx, bits, ISC_HT_CASE_SENSITIVE);
assert_non_null(ht);
for (i = 1; i < count; i++) {
@@ -206,7 +206,7 @@ test_ht_iterator() {
unsigned char key[16];
size_t tksize;
- isc_ht_init(&ht, test_mctx, 16);
+ isc_ht_init(&ht, test_mctx, 16, ISC_HT_CASE_SENSITIVE);
assert_non_null(ht);
for (i = 1; i <= count; i++) {
/*
@@ -333,9 +333,62 @@ isc_ht_iterator_test(void **state) {
test_ht_iterator();
}
+static void
+isc_ht_case(void **state) {
+ UNUSED(state);
+
+ isc_ht_t *ht = NULL;
+ void *f = NULL;
+ isc_result_t result = ISC_R_UNSET;
+
+ unsigned char lower[16] = { "test case" };
+ unsigned char same[16] = { "test case" };
+ unsigned char upper[16] = { "TEST CASE" };
+ unsigned char mixed[16] = { "tEsT CaSe" };
+
+ isc_ht_init(&ht, test_mctx, 8, ISC_HT_CASE_SENSITIVE);
+ assert_non_null(ht);
+
+ result = isc_ht_add(ht, lower, 16, (void *)lower);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ result = isc_ht_add(ht, same, 16, (void *)same);
+ assert_int_equal(result, ISC_R_EXISTS);
+
+ result = isc_ht_add(ht, upper, 16, (void *)upper);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ result = isc_ht_find(ht, mixed, 16, &f);
+ assert_int_equal(result, ISC_R_NOTFOUND);
+ assert_null(f);
+
+ isc_ht_destroy(&ht);
+ assert_null(ht);
+
+ isc_ht_init(&ht, test_mctx, 8, ISC_HT_CASE_INSENSITIVE);
+ assert_non_null(ht);
+
+ result = isc_ht_add(ht, lower, 16, (void *)lower);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ result = isc_ht_add(ht, same, 16, (void *)same);
+ assert_int_equal(result, ISC_R_EXISTS);
+
+ result = isc_ht_add(ht, upper, 16, (void *)upper);
+ assert_int_equal(result, ISC_R_EXISTS);
+
+ result = isc_ht_find(ht, mixed, 16, &f);
+ assert_int_equal(result, ISC_R_SUCCESS);
+ assert_ptr_equal(f, &lower);
+
+ isc_ht_destroy(&ht);
+ assert_null(ht);
+}
+
int
main(void) {
const struct CMUnitTest tests[] = {
+ cmocka_unit_test(isc_ht_case),
cmocka_unit_test(isc_ht_20),
cmocka_unit_test(isc_ht_8),
cmocka_unit_test(isc_ht_1),
diff --git a/lib/isc/unix/include/isc/net.h b/lib/isc/unix/include/isc/net.h
index ead9c7f..9401ef7 100644
--- a/lib/isc/unix/include/isc/net.h
+++ b/lib/isc/unix/include/isc/net.h
@@ -194,10 +194,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/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/isc/win32/file.c b/lib/isc/win32/file.c
index 32f6a19..7da57fc 100644
--- a/lib/isc/win32/file.c
+++ b/lib/isc/win32/file.c
@@ -569,10 +569,14 @@ isc_file_isabsolute(const char *filename) {
if ((filename[0] == '\\') && (filename[1] == '\\')) {
return (true);
}
- if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '\\') {
+ if (isalpha((unsigned char)filename[0]) && filename[1] == ':' &&
+ filename[2] == '\\')
+ {
return (true);
}
- if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '/') {
+ if (isalpha((unsigned char)filename[0]) && filename[1] == ':' &&
+ filename[2] == '/')
+ {
return (true);
}
return (false);
diff --git a/lib/isc/win32/fsaccess.c b/lib/isc/win32/fsaccess.c
index 909f9e5..eb1ab54 100644
--- a/lib/isc/win32/fsaccess.c
+++ b/lib/isc/win32/fsaccess.c
@@ -70,7 +70,7 @@ is_ntfs(const char *file) {
* Look for c:\path\... style, c:/path/... or \\computer\shar\path...
* the UNC style file specs
*/
- if (isalpha(filename[0]) && filename[1] == ':' &&
+ if (isalpha((unsigned char)filename[0]) && filename[1] == ':' &&
(filename[2] == '\\' || filename[2] == '/'))
{
/* Copy 'c:\' or 'c:/' and NUL terminate. */
diff --git a/lib/isc/win32/include/isc/net.h b/lib/isc/win32/include/isc/net.h
index 391614e..3f17223 100644
--- a/lib/isc/win32/include/isc/net.h
+++ b/lib/isc/win32/include/isc/net.h
@@ -123,10 +123,10 @@ typedef uint16_t in_port_t;
#define ISC__IPADDR(x) ((uint32_t)htonl((uint32_t)(x)))
#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))
/*
* Fix the FD_SET and FD_CLR Macros to properly cast
diff --git a/lib/isc/win32/include/isc/stat.h b/lib/isc/win32/include/isc/stat.h
index 63577f9..bc0ec04 100644
--- a/lib/isc/win32/include/isc/stat.h
+++ b/lib/isc/win32/include/isc/stat.h
@@ -49,10 +49,10 @@ typedef unsigned short mode_t;
#endif /* ifndef S_IFREG */
#ifndef S_ISDIR
-#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif /* ifndef S_ISDIR */
#ifndef S_ISREG
-#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif /* ifndef S_ISREG */
#endif /* ISC_STAT_H */
diff --git a/lib/ns/query.c b/lib/ns/query.c
index 4503b8d..1290c30 100644
--- a/lib/ns/query.c
+++ b/lib/ns/query.c
@@ -196,7 +196,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
@@ -455,10 +455,10 @@ static void
query_addnxrrsetnsec(query_ctx_t *qctx);
static isc_result_t
-query_nxdomain(query_ctx_t *qctx, bool empty_wild);
+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);
@@ -6095,6 +6095,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;
@@ -7345,8 +7352,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");
@@ -7416,16 +7422,16 @@ root_key_sentinel:
return (query_nodata(qctx, DNS_R_NXRRSET));
case DNS_R_EMPTYWILD:
- return (query_nxdomain(qctx, true));
+ return (query_nxdomain(qctx, DNS_R_EMPTYWILD));
case DNS_R_NXDOMAIN:
- return (query_nxdomain(qctx, false));
+ return (query_nxdomain(qctx, DNS_R_NXDOMAIN));
case DNS_R_COVERINGNSEC:
return (query_coveringnsec(qctx));
case DNS_R_NCACHENXDOMAIN:
- result = query_redirect(qctx);
+ result = query_redirect(qctx, result);
if (result != ISC_R_COMPLETE) {
return (result);
}
@@ -9243,10 +9249,10 @@ query_addnxrrsetnsec(query_ctx_t *qctx) {
* Handle NXDOMAIN and empty wildcard responses.
*/
static isc_result_t
-query_nxdomain(query_ctx_t *qctx, bool empty_wild) {
+query_nxdomain(query_ctx_t *qctx, isc_result_t result) {
dns_section_t section;
uint32_t ttl;
- isc_result_t result;
+ bool empty_wild = (result == DNS_R_EMPTYWILD);
CCTRACE(ISC_LOG_DEBUG(3), "query_nxdomain");
@@ -9255,7 +9261,7 @@ query_nxdomain(query_ctx_t *qctx, bool empty_wild) {
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);
}
@@ -9343,7 +9349,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");
@@ -9384,7 +9390,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_copynf(qctx->fname,
qctx->client->query.redirect.fname);
qctx->client->query.redirect.authoritative =
@@ -10005,7 +10011,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/tests/nstest.c b/lib/ns/tests/nstest.c
index df15408..939803b 100644
--- a/lib/ns/tests/nstest.c
+++ b/lib/ns/tests/nstest.c
@@ -627,7 +627,7 @@ attach_query_msg_to_client(ns_client_t *client, const char *qnamestr,
dns_rdatatype_t qtype, unsigned int qflags) {
dns_rdataset_t *qrdataset = NULL;
dns_message_t *message = NULL;
- unsigned char query[65536];
+ unsigned char query[65535];
dns_name_t *qname = NULL;
isc_buffer_t querybuf;
dns_compress_t cctx;
diff --git a/lib/ns/xfrout.c b/lib/ns/xfrout.c
index f0c52f2..271b462 100644
--- a/lib/ns/xfrout.c
+++ b/lib/ns/xfrout.c
@@ -1281,7 +1281,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);