xref: /netbsd-src/external/mpl/bind/dist/lib/dns/qpzone.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1 /*	$NetBSD: qpzone.c,v 1.2 2025/01/26 16:25:24 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * SPDX-License-Identifier: MPL-2.0
7  *
8  * This Source Code Form is subject to the terms of the Mozilla Public
9  * License, v. 2.0. If a copy of the MPL was not distributed with this
10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11  *
12  * See the COPYRIGHT file distributed with this work for additional
13  * information regarding copyright ownership.
14  */
15 
16 /*! \file */
17 
18 #include <inttypes.h>
19 #include <stdbool.h>
20 #include <sys/mman.h>
21 
22 #include <isc/ascii.h>
23 #include <isc/async.h>
24 #include <isc/atomic.h>
25 #include <isc/crc64.h>
26 #include <isc/file.h>
27 #include <isc/heap.h>
28 #include <isc/hex.h>
29 #include <isc/loop.h>
30 #include <isc/mem.h>
31 #include <isc/mutex.h>
32 #include <isc/once.h>
33 #include <isc/random.h>
34 #include <isc/refcount.h>
35 #include <isc/result.h>
36 #include <isc/rwlock.h>
37 #include <isc/serial.h>
38 #include <isc/stdio.h>
39 #include <isc/string.h>
40 #include <isc/time.h>
41 #include <isc/urcu.h>
42 #include <isc/util.h>
43 
44 #include <dns/callbacks.h>
45 #include <dns/db.h>
46 #include <dns/dbiterator.h>
47 #include <dns/fixedname.h>
48 #include <dns/log.h>
49 #include <dns/masterdump.h>
50 #include <dns/name.h>
51 #include <dns/nsec.h>
52 #include <dns/nsec3.h>
53 #include <dns/qp.h>
54 #include <dns/rdata.h>
55 #include <dns/rdataset.h>
56 #include <dns/rdatasetiter.h>
57 #include <dns/rdataslab.h>
58 #include <dns/rdatastruct.h>
59 #include <dns/stats.h>
60 #include <dns/time.h>
61 #include <dns/view.h>
62 #include <dns/zone.h>
63 #include <dns/zonekey.h>
64 
65 #include "db_p.h"
66 #include "qpzone_p.h"
67 
68 #define CHECK(op)                            \
69 	do {                                 \
70 		result = (op);               \
71 		if (result != ISC_R_SUCCESS) \
72 			goto failure;        \
73 	} while (0)
74 
75 #define NONEXISTENT(header)                            \
76 	((atomic_load_acquire(&(header)->attributes) & \
77 	  DNS_SLABHEADERATTR_NONEXISTENT) != 0)
78 #define IGNORE(header)                                 \
79 	((atomic_load_acquire(&(header)->attributes) & \
80 	  DNS_SLABHEADERATTR_IGNORE) != 0)
81 #define RESIGN(header)                                 \
82 	((atomic_load_acquire(&(header)->attributes) & \
83 	  DNS_SLABHEADERATTR_RESIGN) != 0)
84 #define OPTOUT(header)                                 \
85 	((atomic_load_acquire(&(header)->attributes) & \
86 	  DNS_SLABHEADERATTR_OPTOUT) != 0)
87 #define STATCOUNT(header)                              \
88 	((atomic_load_acquire(&(header)->attributes) & \
89 	  DNS_SLABHEADERATTR_STATCOUNT) != 0)
90 
91 #define HEADERNODE(h) ((qpznode_t *)((h)->node))
92 
93 #define QPDB_ATTR_LOADED  0x01
94 #define QPDB_ATTR_LOADING 0x02
95 
96 #define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */
97 
98 #define QPDBITER_NSEC3_ORIGIN_NODE(qpdb, iterator)        \
99 	((iterator)->current == &(iterator)->nsec3iter && \
100 	 (iterator)->node == (qpdb)->nsec3_origin)
101 
102 /*%
103  * Note that "impmagic" is not the first four bytes of the struct, so
104  * ISC_MAGIC_VALID cannot be used.
105  */
106 #define QPZONE_DB_MAGIC ISC_MAGIC('Q', 'Z', 'D', 'B')
107 #define VALID_QPZONE(qpdb) \
108 	((qpdb) != NULL && (qpdb)->common.impmagic == QPZONE_DB_MAGIC)
109 
110 typedef struct qpzonedb qpzonedb_t;
111 typedef struct qpznode qpznode_t;
112 
113 typedef struct qpz_changed {
114 	qpznode_t *node;
115 	bool dirty;
116 	ISC_LINK(struct qpz_changed) link;
117 } qpz_changed_t;
118 
119 typedef ISC_LIST(qpz_changed_t) qpz_changedlist_t;
120 
121 typedef struct qpz_version qpz_version_t;
122 struct qpz_version {
123 	/* Not locked */
124 	uint32_t serial;
125 	qpzonedb_t *qpdb;
126 	isc_refcount_t references;
127 	/* Locked by database lock. */
128 	bool writer;
129 	qpz_changedlist_t changed_list;
130 	dns_slabheaderlist_t resigned_list;
131 	ISC_LINK(qpz_version_t) link;
132 	bool secure;
133 	bool havensec3;
134 	/* NSEC3 parameters */
135 	dns_hash_t hash;
136 	uint8_t flags;
137 	uint16_t iterations;
138 	uint8_t salt_length;
139 	unsigned char salt[DNS_NSEC3_SALTSIZE];
140 
141 	/*
142 	 * records and xfrsize are covered by rwlock.
143 	 */
144 	isc_rwlock_t rwlock;
145 	uint64_t records;
146 	uint64_t xfrsize;
147 
148 	struct cds_lfht *glue_table;
149 };
150 
151 typedef ISC_LIST(qpz_version_t) qpz_versionlist_t;
152 
153 struct qpznode {
154 	dns_name_t name;
155 	isc_mem_t *mctx;
156 	isc_refcount_t references;
157 	isc_refcount_t erefs;
158 	uint16_t locknum;
159 	void *data;
160 	atomic_uint_fast8_t nsec;
161 	atomic_bool wild;
162 	atomic_bool delegating;
163 	atomic_bool dirty;
164 };
165 
166 struct qpzonedb {
167 	/* Unlocked. */
168 	dns_db_t common;
169 	/* Locks the data in this struct */
170 	isc_rwlock_t lock;
171 	/* Locks for tree nodes */
172 	int node_lock_count;
173 	db_nodelock_t *node_locks;
174 	qpznode_t *origin;
175 	qpznode_t *nsec3_origin;
176 	isc_stats_t *gluecachestats;
177 	/* Locked by lock. */
178 	unsigned int active;
179 	unsigned int attributes;
180 	uint32_t current_serial;
181 	uint32_t least_serial;
182 	uint32_t next_serial;
183 	uint32_t maxrrperset;	 /* Maximum RRs per RRset */
184 	uint32_t maxtypepername; /* Maximum number of RR types per owner */
185 	qpz_version_t *current_version;
186 	qpz_version_t *future_version;
187 	qpz_versionlist_t open_versions;
188 	isc_loop_t *loop;
189 	struct rcu_head rcu_head;
190 
191 	isc_heap_t *heap; /* Resigning heap */
192 
193 	dns_qpmulti_t *tree;  /* Main QP trie for data storage */
194 	dns_qpmulti_t *nsec;  /* NSEC nodes only */
195 	dns_qpmulti_t *nsec3; /* NSEC3 nodes only */
196 };
197 
198 /*%
199  * Search Context
200  */
201 typedef struct {
202 	qpzonedb_t *qpdb;
203 	qpz_version_t *version;
204 	dns_qpread_t qpr;
205 	uint32_t serial;
206 	unsigned int options;
207 	dns_qpchain_t chain;
208 	dns_qpiter_t iter;
209 	bool copy_name;
210 	bool need_cleanup;
211 	bool wild;
212 	qpznode_t *zonecut;
213 	dns_slabheader_t *zonecut_header;
214 	dns_slabheader_t *zonecut_sigheader;
215 	dns_fixedname_t zonecut_name;
216 	isc_stdtime_t now;
217 } qpz_search_t;
218 
219 typedef struct dns_gluenode_t {
220 	isc_mem_t *mctx;
221 
222 	struct dns_glue *glue;
223 
224 	qpznode_t *node;
225 
226 	struct cds_lfht_node ht_node;
227 	struct rcu_head rcu_head;
228 } dns_gluenode_t;
229 
230 /*%
231  * Load Context
232  */
233 typedef struct {
234 	dns_db_t *db;
235 	isc_stdtime_t now;
236 	dns_qp_t *tree;
237 	dns_qp_t *nsec;
238 	dns_qp_t *nsec3;
239 } qpz_load_t;
240 
241 static dns_dbmethods_t qpdb_zonemethods;
242 
243 #if DNS_DB_NODETRACE
244 #define qpznode_ref(ptr)   qpznode__ref(ptr, __func__, __FILE__, __LINE__)
245 #define qpznode_unref(ptr) qpznode__unref(ptr, __func__, __FILE__, __LINE__)
246 #define qpznode_attach(ptr, ptrp) \
247 	qpznode__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
248 #define qpznode_detach(ptrp) qpznode__detach(ptrp, __func__, __FILE__, __LINE__)
249 ISC_REFCOUNT_STATIC_TRACE_DECL(qpznode);
250 #else
251 ISC_REFCOUNT_STATIC_DECL(qpznode);
252 #endif
253 
254 /* QP trie methods */
255 static void
256 qp_attach(void *uctx, void *pval, uint32_t ival);
257 static void
258 qp_detach(void *uctx, void *pval, uint32_t ival);
259 static size_t
260 qp_makekey(dns_qpkey_t key, void *uctx, void *pval, uint32_t ival);
261 static void
262 qp_triename(void *uctx, char *buf, size_t size);
263 
264 static dns_qpmethods_t qpmethods = {
265 	qp_attach,
266 	qp_detach,
267 	qp_makekey,
268 	qp_triename,
269 };
270 
271 static void
272 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp DNS__DB_FLARG);
273 static isc_result_t
274 rdatasetiter_first(dns_rdatasetiter_t *iterator DNS__DB_FLARG);
275 static isc_result_t
276 rdatasetiter_next(dns_rdatasetiter_t *iterator DNS__DB_FLARG);
277 static void
278 rdatasetiter_current(dns_rdatasetiter_t *iterator,
279 		     dns_rdataset_t *rdataset DNS__DB_FLARG);
280 
281 static dns_rdatasetitermethods_t rdatasetiter_methods = {
282 	rdatasetiter_destroy, rdatasetiter_first, rdatasetiter_next,
283 	rdatasetiter_current
284 };
285 
286 typedef struct qpdb_rdatasetiter {
287 	dns_rdatasetiter_t common;
288 	dns_slabheader_t *current;
289 } qpdb_rdatasetiter_t;
290 
291 /*
292  * Note that these iterators, unless created with either DNS_DB_NSEC3ONLY
293  * or DNS_DB_NONSEC3, will transparently move between the last node of the
294  * "regular" QP trie and the root node of the NSEC3 QP trie of the database
295  * in question, as if the latter was a successor to the former in lexical
296  * order.  The "current" field always holds the address of either
297  * "mainiter" or "nsec3iter", depending on which trie is being traversed
298  * at given time.
299  */
300 static void
301 dbiterator_destroy(dns_dbiterator_t **iteratorp DNS__DB_FLARG);
302 static isc_result_t
303 dbiterator_first(dns_dbiterator_t *iterator DNS__DB_FLARG);
304 static isc_result_t
305 dbiterator_last(dns_dbiterator_t *iterator DNS__DB_FLARG);
306 static isc_result_t
307 dbiterator_seek(dns_dbiterator_t *iterator,
308 		const dns_name_t *name DNS__DB_FLARG);
309 static isc_result_t
310 dbiterator_prev(dns_dbiterator_t *iterator DNS__DB_FLARG);
311 static isc_result_t
312 dbiterator_next(dns_dbiterator_t *iterator DNS__DB_FLARG);
313 static isc_result_t
314 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
315 		   dns_name_t *name DNS__DB_FLARG);
316 static isc_result_t
317 dbiterator_pause(dns_dbiterator_t *iterator);
318 static isc_result_t
319 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name);
320 
321 static dns_dbiteratormethods_t dbiterator_methods = {
322 	dbiterator_destroy, dbiterator_first, dbiterator_last,
323 	dbiterator_seek,    dbiterator_prev,  dbiterator_next,
324 	dbiterator_current, dbiterator_pause, dbiterator_origin
325 };
326 
327 typedef struct qpdb_dbiterator {
328 	dns_dbiterator_t common;
329 	isc_result_t result;
330 	dns_qpsnap_t *tsnap;	/* main tree snapshot */
331 	dns_qpsnap_t *nsnap;	/* nsec3 tree snapshot */
332 	dns_qpiter_t *current;	/* current iterator, which is one of: */
333 	dns_qpiter_t mainiter;	/* - main tree iterator */
334 	dns_qpiter_t nsec3iter; /* - nsec3 tree iterator */
335 	qpznode_t *node;
336 	enum { full, nonsec3, nsec3only } nsec3mode;
337 } qpdb_dbiterator_t;
338 
339 /*%
340  * 'init_count' is used to initialize 'newheader->count' which inturn
341  * is used to determine where in the cycle rrset-order cyclic starts.
342  * We don't lock this as we don't care about simultaneous updates.
343  */
344 static atomic_uint_fast16_t init_count = 0;
345 
346 /*
347  * Locking
348  *
349  * If a routine is going to lock more than one lock in this module, then
350  * the locking must be done in the following order:
351  *
352  *      Node Lock       (Only one from the set may be locked at one time by
353  *                       any caller)
354  *
355  *      Database Lock
356  *
357  * Failure to follow this hierarchy can result in deadlock.
358  */
359 
360 /*%
361  * Return which RRset should be resigned sooner.  If the RRsets have the
362  * same signing time, prefer the other RRset over the SOA RRset.
363  */
364 static bool
365 resign_sooner(void *v1, void *v2) {
366 	dns_slabheader_t *h1 = v1;
367 	dns_slabheader_t *h2 = v2;
368 
369 	return h1->resign < h2->resign ||
370 	       (h1->resign == h2->resign && h1->resign_lsb < h2->resign_lsb) ||
371 	       (h1->resign == h2->resign && h1->resign_lsb == h2->resign_lsb &&
372 		h2->type == DNS_SIGTYPE(dns_rdatatype_soa));
373 }
374 
375 /*%
376  * This function sets the heap index into the header.
377  */
378 static void
379 set_index(void *what, unsigned int idx) {
380 	dns_slabheader_t *h = what;
381 
382 	h->heap_index = idx;
383 }
384 
385 static void
386 free_gluenode(dns_gluenode_t *gluenode);
387 
388 static void
389 free_gluetable(struct cds_lfht *glue_table) {
390 	struct cds_lfht_iter iter;
391 	dns_gluenode_t *gluenode = NULL;
392 
393 	rcu_read_lock();
394 	cds_lfht_for_each_entry(glue_table, &iter, gluenode, ht_node) {
395 		INSIST(!cds_lfht_del(glue_table, &gluenode->ht_node));
396 		free_gluenode(gluenode);
397 	}
398 	rcu_read_unlock();
399 
400 	cds_lfht_destroy(glue_table, NULL);
401 }
402 
403 static void
404 free_db_rcu(struct rcu_head *rcu_head) {
405 	qpzonedb_t *qpdb = caa_container_of(rcu_head, qpzonedb_t, rcu_head);
406 
407 	if (dns_name_dynamic(&qpdb->common.origin)) {
408 		dns_name_free(&qpdb->common.origin, qpdb->common.mctx);
409 	}
410 	for (int i = 0; i < qpdb->node_lock_count; i++) {
411 		isc_refcount_destroy(&qpdb->node_locks[i].references);
412 		NODE_DESTROYLOCK(&qpdb->node_locks[i].lock);
413 	}
414 
415 	isc_heap_destroy(&qpdb->heap);
416 
417 	if (qpdb->gluecachestats != NULL) {
418 		isc_stats_detach(&qpdb->gluecachestats);
419 	}
420 
421 	isc_mem_cput(qpdb->common.mctx, qpdb->node_locks, qpdb->node_lock_count,
422 		     sizeof(db_nodelock_t));
423 	isc_refcount_destroy(&qpdb->common.references);
424 	if (qpdb->loop != NULL) {
425 		isc_loop_detach(&qpdb->loop);
426 	}
427 
428 	isc_rwlock_destroy(&qpdb->lock);
429 	qpdb->common.magic = 0;
430 	qpdb->common.impmagic = 0;
431 
432 	if (qpdb->common.update_listeners != NULL) {
433 		INSIST(!cds_lfht_destroy(qpdb->common.update_listeners, NULL));
434 	}
435 
436 	isc_mem_putanddetach(&qpdb->common.mctx, qpdb, sizeof(*qpdb));
437 }
438 
439 static void
440 free_qpdb(qpzonedb_t *qpdb, bool log) {
441 	REQUIRE(qpdb->future_version == NULL);
442 
443 	isc_refcount_decrementz(&qpdb->current_version->references);
444 
445 	isc_refcount_destroy(&qpdb->current_version->references);
446 	UNLINK(qpdb->open_versions, qpdb->current_version, link);
447 	isc_rwlock_destroy(&qpdb->current_version->rwlock);
448 	isc_mem_put(qpdb->common.mctx, qpdb->current_version,
449 		    sizeof(*qpdb->current_version));
450 
451 	dns_qpmulti_destroy(&qpdb->tree);
452 	dns_qpmulti_destroy(&qpdb->nsec);
453 	dns_qpmulti_destroy(&qpdb->nsec3);
454 
455 	if (log) {
456 		char buf[DNS_NAME_FORMATSIZE];
457 		if (dns_name_dynamic(&qpdb->common.origin)) {
458 			dns_name_format(&qpdb->common.origin, buf, sizeof(buf));
459 		} else {
460 			strlcpy(buf, "<UNKNOWN>", sizeof(buf));
461 		}
462 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
463 			      DNS_LOGMODULE_DB, ISC_LOG_DEBUG(1),
464 			      "called free_qpdb(%s)", buf);
465 	}
466 
467 	call_rcu(&qpdb->rcu_head, free_db_rcu);
468 }
469 
470 static void
471 qpdb_destroy(dns_db_t *arg) {
472 	qpzonedb_t *qpdb = (qpzonedb_t *)arg;
473 	unsigned int inactive = 0;
474 
475 	if (qpdb->origin != NULL) {
476 		qpznode_detach(&qpdb->origin);
477 	}
478 	if (qpdb->nsec3_origin != NULL) {
479 		qpznode_detach(&qpdb->nsec3_origin);
480 	}
481 
482 	/*
483 	 * The current version's glue table needs to be freed early
484 	 * so the nodes are dereferenced before we check the active
485 	 * node count below.
486 	 */
487 	if (qpdb->current_version != NULL) {
488 		free_gluetable(qpdb->current_version->glue_table);
489 	}
490 
491 	/*
492 	 * Even though there are no external direct references, there still
493 	 * may be nodes in use.
494 	 */
495 	for (int i = 0; i < qpdb->node_lock_count; i++) {
496 		isc_rwlocktype_t nodelock = isc_rwlocktype_none;
497 		NODE_WRLOCK(&qpdb->node_locks[i].lock, &nodelock);
498 		qpdb->node_locks[i].exiting = true;
499 		if (isc_refcount_current(&qpdb->node_locks[i].references) == 0)
500 		{
501 			inactive++;
502 		}
503 		NODE_UNLOCK(&qpdb->node_locks[i].lock, &nodelock);
504 	}
505 
506 	if (inactive != 0) {
507 		bool want_free = false;
508 
509 		RWLOCK(&qpdb->lock, isc_rwlocktype_write);
510 		qpdb->active -= inactive;
511 		if (qpdb->active == 0) {
512 			want_free = true;
513 		}
514 		RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
515 
516 		if (want_free) {
517 			char buf[DNS_NAME_FORMATSIZE];
518 			if (dns_name_dynamic(&qpdb->common.origin)) {
519 				dns_name_format(&qpdb->common.origin, buf,
520 						sizeof(buf));
521 			} else {
522 				strlcpy(buf, "<UNKNOWN>", sizeof(buf));
523 			}
524 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
525 				      DNS_LOGMODULE_DB, ISC_LOG_DEBUG(1),
526 				      "calling free_qpdb(%s)", buf);
527 			free_qpdb(qpdb, true);
528 		}
529 	}
530 }
531 
532 static qpznode_t *
533 new_qpznode(qpzonedb_t *qpdb, const dns_name_t *name) {
534 	qpznode_t *newdata = isc_mem_get(qpdb->common.mctx, sizeof(*newdata));
535 	*newdata = (qpznode_t){
536 		.name = DNS_NAME_INITEMPTY,
537 		.references = ISC_REFCOUNT_INITIALIZER(1),
538 	};
539 	newdata->locknum = dns_name_hash(name) % qpdb->node_lock_count;
540 	dns_name_dupwithoffsets(name, qpdb->common.mctx, &newdata->name);
541 	isc_mem_attach(qpdb->common.mctx, &newdata->mctx);
542 
543 #if DNS_DB_NODETRACE
544 	fprintf(stderr, "new_qpznode:%s:%s:%d:%p->references = 1\n", __func__,
545 		__FILE__, __LINE__ + 1, name);
546 #endif
547 	return newdata;
548 }
549 
550 static qpz_version_t *
551 allocate_version(isc_mem_t *mctx, uint32_t serial, unsigned int references,
552 		 bool writer) {
553 	qpz_version_t *version = isc_mem_get(mctx, sizeof(*version));
554 	*version = (qpz_version_t){
555 		.serial = serial,
556 		.writer = writer,
557 		.changed_list = ISC_LIST_INITIALIZER,
558 		.resigned_list = ISC_LIST_INITIALIZER,
559 		.link = ISC_LINK_INITIALIZER,
560 		.glue_table = cds_lfht_new(GLUETABLE_INIT_SIZE,
561 					   GLUETABLE_MIN_SIZE, 0,
562 					   CDS_LFHT_AUTO_RESIZE, NULL),
563 	};
564 
565 	isc_rwlock_init(&version->rwlock);
566 	isc_refcount_init(&version->references, references);
567 
568 	return version;
569 }
570 
571 isc_result_t
572 dns__qpzone_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
573 		   dns_rdataclass_t rdclass, unsigned int argc ISC_ATTR_UNUSED,
574 		   char **argv ISC_ATTR_UNUSED, void *driverarg ISC_ATTR_UNUSED,
575 		   dns_db_t **dbp) {
576 	qpzonedb_t *qpdb = NULL;
577 	isc_result_t result;
578 	dns_qp_t *qp = NULL;
579 
580 	qpdb = isc_mem_get(mctx, sizeof(*qpdb));
581 	*qpdb = (qpzonedb_t){
582 		.common.origin = DNS_NAME_INITEMPTY,
583 		.common.rdclass = rdclass,
584 		.node_lock_count = DEFAULT_NODE_LOCK_COUNT,
585 		.current_serial = 1,
586 		.least_serial = 1,
587 		.next_serial = 2,
588 		.open_versions = ISC_LIST_INITIALIZER,
589 	};
590 
591 	isc_refcount_init(&qpdb->common.references, 1);
592 
593 	qpdb->common.methods = &qpdb_zonemethods;
594 	if (type == dns_dbtype_stub) {
595 		qpdb->common.attributes |= DNS_DBATTR_STUB;
596 	}
597 
598 	isc_rwlock_init(&qpdb->lock);
599 
600 	qpdb->node_locks = isc_mem_cget(mctx, qpdb->node_lock_count,
601 					sizeof(db_nodelock_t));
602 
603 	qpdb->common.update_listeners = cds_lfht_new(16, 16, 0, 0, NULL);
604 
605 	isc_heap_create(mctx, resign_sooner, set_index, 0, &qpdb->heap);
606 
607 	qpdb->active = qpdb->node_lock_count;
608 
609 	for (int i = 0; i < qpdb->node_lock_count; i++) {
610 		NODE_INITLOCK(&qpdb->node_locks[i].lock);
611 		isc_refcount_init(&qpdb->node_locks[i].references, 0);
612 		qpdb->node_locks[i].exiting = false;
613 	}
614 
615 	/*
616 	 * Attach to the mctx.  The database will persist so long as there
617 	 * are references to it, and attaching to the mctx ensures that our
618 	 * mctx won't disappear out from under us.
619 	 */
620 	isc_mem_attach(mctx, &qpdb->common.mctx);
621 
622 	/*
623 	 * Make a copy of the origin name.
624 	 */
625 	dns_name_dupwithoffsets(origin, mctx, &qpdb->common.origin);
626 
627 	dns_qpmulti_create(mctx, &qpmethods, qpdb, &qpdb->tree);
628 	dns_qpmulti_create(mctx, &qpmethods, qpdb, &qpdb->nsec);
629 	dns_qpmulti_create(mctx, &qpmethods, qpdb, &qpdb->nsec3);
630 
631 	/*
632 	 * Version initialization.
633 	 */
634 	qpdb->current_version = allocate_version(mctx, 1, 1, false);
635 	qpdb->current_version->qpdb = qpdb;
636 
637 	/*
638 	 * In order to set the node callback bit correctly in zone databases,
639 	 * we need to know if the node has the origin name of the zone.
640 	 * In loading_addrdataset() we could simply compare the new name
641 	 * to the origin name, but this is expensive.  Also, we don't know the
642 	 * node name in addrdataset(), so we need another way of knowing the
643 	 * zone's top.
644 	 *
645 	 * We now explicitly create a node for the zone's origin, and then
646 	 * we simply remember the node data's address.
647 	 */
648 
649 	dns_qpmulti_write(qpdb->tree, &qp);
650 	qpdb->origin = new_qpznode(qpdb, &qpdb->common.origin);
651 	result = dns_qp_insert(qp, qpdb->origin, 0);
652 	qpdb->origin->nsec = DNS_DB_NSEC_NORMAL;
653 	dns_qpmulti_commit(qpdb->tree, &qp);
654 
655 	if (result != ISC_R_SUCCESS) {
656 		INSIST(result != ISC_R_EXISTS);
657 		free_qpdb(qpdb, false);
658 		return result;
659 	}
660 
661 	/*
662 	 * Add an apex node to the NSEC3 tree so that NSEC3 searches
663 	 * return partial matches when there is only a single NSEC3
664 	 * record in the tree.
665 	 */
666 	dns_qpmulti_write(qpdb->nsec3, &qp);
667 	qpdb->nsec3_origin = new_qpznode(qpdb, &qpdb->common.origin);
668 	qpdb->nsec3_origin->nsec = DNS_DB_NSEC_NSEC3;
669 	result = dns_qp_insert(qp, qpdb->nsec3_origin, 0);
670 	dns_qpmulti_commit(qpdb->nsec3, &qp);
671 
672 	if (result != ISC_R_SUCCESS) {
673 		INSIST(result != ISC_R_EXISTS);
674 		free_qpdb(qpdb, false);
675 		return result;
676 	}
677 
678 	/*
679 	 * Keep the current version in the open list so that list operation
680 	 * won't happen in normal lookup operations.
681 	 */
682 	PREPEND(qpdb->open_versions, qpdb->current_version, link);
683 
684 	qpdb->common.magic = DNS_DB_MAGIC;
685 	qpdb->common.impmagic = QPZONE_DB_MAGIC;
686 
687 	*dbp = (dns_db_t *)qpdb;
688 
689 	return ISC_R_SUCCESS;
690 }
691 
692 static void
693 newref(qpzonedb_t *qpdb, qpznode_t *node DNS__DB_FLARG) {
694 	uint_fast32_t refs;
695 
696 	qpznode_ref(node);
697 	refs = isc_refcount_increment0(&node->erefs);
698 #if DNS_DB_NODETRACE
699 	fprintf(stderr, "incr:node:%s:%s:%u:%p->erefs = %" PRIuFAST32 "\n",
700 		func, file, line, node, refs + 1);
701 #else
702 	UNUSED(refs);
703 #endif
704 
705 	if (refs == 0) {
706 		/* this is the first reference to the node */
707 		refs = isc_refcount_increment0(
708 			&qpdb->node_locks[node->locknum].references);
709 #if DNS_DB_NODETRACE
710 		fprintf(stderr,
711 			"incr:nodelock:%s:%s:%u:%p:%p->references = "
712 			"%" PRIuFAST32 "\n",
713 			func, file, line, node,
714 			&qpdb->node_locks[node->locknum], refs + 1);
715 #else
716 		UNUSED(refs);
717 #endif
718 	}
719 }
720 
721 static void
722 clean_zone_node(qpznode_t *node, uint32_t least_serial) {
723 	dns_slabheader_t *current = NULL, *dcurrent = NULL;
724 	dns_slabheader_t *down_next = NULL, *dparent = NULL;
725 	dns_slabheader_t *top_prev = NULL, *top_next = NULL;
726 	bool still_dirty = false;
727 
728 	/*
729 	 * Caller must be holding the node lock.
730 	 */
731 	REQUIRE(least_serial != 0);
732 
733 	for (current = node->data; current != NULL; current = top_next) {
734 		top_next = current->next;
735 
736 		/*
737 		 * First, we clean up any instances of multiple rdatasets
738 		 * with the same serial number, or that have the IGNORE
739 		 * attribute.
740 		 */
741 		dparent = current;
742 		for (dcurrent = current->down; dcurrent != NULL;
743 		     dcurrent = down_next)
744 		{
745 			down_next = dcurrent->down;
746 			INSIST(dcurrent->serial <= dparent->serial);
747 			if (dcurrent->serial == dparent->serial ||
748 			    IGNORE(dcurrent))
749 			{
750 				if (down_next != NULL) {
751 					down_next->next = dparent;
752 				}
753 				dparent->down = down_next;
754 				dns_slabheader_destroy(&dcurrent);
755 			} else {
756 				dparent = dcurrent;
757 			}
758 		}
759 
760 		/*
761 		 * We've now eliminated all IGNORE datasets with the possible
762 		 * exception of current, which we now check.
763 		 */
764 		if (IGNORE(current)) {
765 			down_next = current->down;
766 			if (down_next == NULL) {
767 				if (top_prev != NULL) {
768 					top_prev->next = current->next;
769 				} else {
770 					node->data = current->next;
771 				}
772 				dns_slabheader_destroy(&current);
773 				/*
774 				 * current no longer exists, so we can
775 				 * just continue with the loop.
776 				 */
777 				continue;
778 			} else {
779 				/*
780 				 * Pull up current->down, making it the new
781 				 * current.
782 				 */
783 				if (top_prev != NULL) {
784 					top_prev->next = down_next;
785 				} else {
786 					node->data = down_next;
787 				}
788 				down_next->next = top_next;
789 				dns_slabheader_destroy(&current);
790 				current = down_next;
791 			}
792 		}
793 
794 		/*
795 		 * We now try to find the first down node less than the
796 		 * least serial.
797 		 */
798 		dparent = current;
799 		for (dcurrent = current->down; dcurrent != NULL;
800 		     dcurrent = down_next)
801 		{
802 			down_next = dcurrent->down;
803 			if (dcurrent->serial < least_serial) {
804 				break;
805 			}
806 			dparent = dcurrent;
807 		}
808 
809 		/*
810 		 * If there is a such an rdataset, delete it and any older
811 		 * versions.
812 		 */
813 		if (dcurrent != NULL) {
814 			do {
815 				down_next = dcurrent->down;
816 				INSIST(dcurrent->serial <= least_serial);
817 				dns_slabheader_destroy(&dcurrent);
818 				dcurrent = down_next;
819 			} while (dcurrent != NULL);
820 			dparent->down = NULL;
821 		}
822 
823 		/*
824 		 * Note.  The serial number of 'current' might be less than
825 		 * least_serial too, but we cannot delete it because it is
826 		 * the most recent version.
827 		 */
828 		if (current->down != NULL) {
829 			still_dirty = true;
830 		}
831 		top_prev = current;
832 	}
833 	if (!still_dirty) {
834 		node->dirty = false;
835 	}
836 }
837 
838 /*
839  * Caller must be holding the node lock; either the read or write lock.
840  * Note that the lock must be held even when node references are
841  * atomically modified; in that case the decrement operation itself does not
842  * have to be protected, but we must avoid a race condition where multiple
843  * threads are decreasing the reference to zero simultaneously and at least
844  * one of them is going to free the node.
845  *
846  * This decrements both the internal and external node reference counters.
847  * If the external reference count drops to zero, then the node lock
848  * reference count is also decremented.
849  *
850  * (NOTE: Decrementing the reference count of a node to zero does
851  * not mean it will be immediately freed.)
852  */
853 static void
854 decref(qpzonedb_t *qpdb, qpznode_t *node, uint32_t least_serial,
855        isc_rwlocktype_t *nlocktypep DNS__DB_FLARG) {
856 	db_nodelock_t *nodelock = NULL;
857 	int bucket = node->locknum;
858 	uint_fast32_t refs;
859 
860 	REQUIRE(*nlocktypep != isc_rwlocktype_none);
861 
862 	nodelock = &qpdb->node_locks[bucket];
863 
864 	/* Handle easy and typical case first. */
865 	if (!node->dirty && (node->data != NULL || node == qpdb->origin ||
866 			     node == qpdb->nsec3_origin))
867 	{
868 		refs = isc_refcount_decrement(&node->erefs);
869 #if DNS_DB_NODETRACE
870 		fprintf(stderr,
871 			"decr:node:%s:%s:%u:%p->erefs = %" PRIuFAST32 "\n",
872 			func, file, line, node, refs - 1);
873 #else
874 		UNUSED(refs);
875 #endif
876 		if (refs == 1) {
877 			refs = isc_refcount_decrement(&nodelock->references);
878 #if DNS_DB_NODETRACE
879 			fprintf(stderr,
880 				"decr:nodelock:%s:%s:%u:%p:%p->references = "
881 				"%" PRIuFAST32 "\n",
882 				func, file, line, node, nodelock, refs - 1);
883 #else
884 			UNUSED(refs);
885 #endif
886 		}
887 		goto done;
888 	}
889 
890 	/* Upgrade the lock? */
891 	if (*nlocktypep == isc_rwlocktype_read) {
892 		NODE_FORCEUPGRADE(&nodelock->lock, nlocktypep);
893 	}
894 
895 	refs = isc_refcount_decrement(&node->erefs);
896 #if DNS_DB_NODETRACE
897 	fprintf(stderr, "decr:node:%s:%s:%u:%p->erefs = %" PRIuFAST32 "\n",
898 		func, file, line, node, refs - 1);
899 #endif
900 	if (refs == 1) {
901 		if (node->dirty) {
902 			if (least_serial == 0) {
903 				/*
904 				 * Caller doesn't know the least serial.
905 				 * Get it.
906 				 */
907 				RWLOCK(&qpdb->lock, isc_rwlocktype_read);
908 				least_serial = qpdb->least_serial;
909 				RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
910 			}
911 			clean_zone_node(node, least_serial);
912 		}
913 
914 		refs = isc_refcount_decrement(&nodelock->references);
915 #if DNS_DB_NODETRACE
916 		fprintf(stderr,
917 			"decr:nodelock:%s:%s:%u:%p:%p->references = "
918 			"%" PRIuFAST32 "\n",
919 			func, file, line, node, nodelock, refs - 1);
920 #else
921 		UNUSED(refs);
922 #endif
923 	}
924 
925 done:
926 	qpznode_unref(node);
927 }
928 
929 static void
930 bindrdataset(qpzonedb_t *qpdb, qpznode_t *node, dns_slabheader_t *header,
931 	     isc_stdtime_t now, dns_rdataset_t *rdataset DNS__DB_FLARG) {
932 	if (rdataset == NULL) {
933 		return;
934 	}
935 
936 	newref(qpdb, node DNS__DB_FLARG_PASS);
937 
938 	INSIST(rdataset->methods == NULL); /* We must be disassociated. */
939 
940 	rdataset->methods = &dns_rdataslab_rdatasetmethods;
941 	rdataset->rdclass = qpdb->common.rdclass;
942 	rdataset->type = DNS_TYPEPAIR_TYPE(header->type);
943 	rdataset->covers = DNS_TYPEPAIR_COVERS(header->type);
944 	rdataset->ttl = header->ttl - now;
945 	rdataset->trust = header->trust;
946 
947 	if (OPTOUT(header)) {
948 		rdataset->attributes |= DNS_RDATASETATTR_OPTOUT;
949 	}
950 
951 	rdataset->count = atomic_fetch_add_relaxed(&header->count, 1);
952 
953 	rdataset->slab.db = (dns_db_t *)qpdb;
954 	rdataset->slab.node = (dns_dbnode_t *)node;
955 	rdataset->slab.raw = dns_slabheader_raw(header);
956 	rdataset->slab.iter_pos = NULL;
957 	rdataset->slab.iter_count = 0;
958 
959 	/*
960 	 * Add noqname proof.
961 	 */
962 	rdataset->slab.noqname = header->noqname;
963 	if (header->noqname != NULL) {
964 		rdataset->attributes |= DNS_RDATASETATTR_NOQNAME;
965 	}
966 	rdataset->slab.closest = header->closest;
967 	if (header->closest != NULL) {
968 		rdataset->attributes |= DNS_RDATASETATTR_CLOSEST;
969 	}
970 
971 	/*
972 	 * Copy out re-signing information.
973 	 */
974 	if (RESIGN(header)) {
975 		rdataset->attributes |= DNS_RDATASETATTR_RESIGN;
976 		rdataset->resign = (header->resign << 1) | header->resign_lsb;
977 	} else {
978 		rdataset->resign = 0;
979 	}
980 }
981 
982 static void
983 setnsec3parameters(dns_db_t *db, qpz_version_t *version) {
984 	qpznode_t *node = NULL;
985 	dns_rdata_nsec3param_t nsec3param;
986 	dns_rdata_t rdata = DNS_RDATA_INIT;
987 	isc_region_t region;
988 	isc_result_t result;
989 	dns_slabheader_t *header = NULL, *header_next = NULL;
990 	unsigned char *raw; /* RDATASLAB */
991 	unsigned int count, length;
992 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
993 	isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
994 
995 	version->havensec3 = false;
996 	node = qpdb->origin;
997 	NODE_RDLOCK(&(qpdb->node_locks[node->locknum].lock), &nlocktype);
998 	for (header = node->data; header != NULL; header = header_next) {
999 		header_next = header->next;
1000 		do {
1001 			if (header->serial <= version->serial &&
1002 			    !IGNORE(header))
1003 			{
1004 				if (NONEXISTENT(header)) {
1005 					header = NULL;
1006 				}
1007 				break;
1008 			} else {
1009 				header = header->down;
1010 			}
1011 		} while (header != NULL);
1012 
1013 		if (header != NULL &&
1014 		    (header->type == dns_rdatatype_nsec3param))
1015 		{
1016 			/*
1017 			 * Find an NSEC3PARAM with a supported algorithm.
1018 			 */
1019 			raw = dns_slabheader_raw(header);
1020 			count = raw[0] * 256 + raw[1]; /* count */
1021 			raw += DNS_RDATASET_COUNT + DNS_RDATASET_LENGTH;
1022 			while (count-- > 0U) {
1023 				length = raw[0] * 256 + raw[1];
1024 				raw += DNS_RDATASET_ORDER + DNS_RDATASET_LENGTH;
1025 				region.base = raw;
1026 				region.length = length;
1027 				raw += length;
1028 				dns_rdata_fromregion(
1029 					&rdata, qpdb->common.rdclass,
1030 					dns_rdatatype_nsec3param, &region);
1031 				result = dns_rdata_tostruct(&rdata, &nsec3param,
1032 							    NULL);
1033 				INSIST(result == ISC_R_SUCCESS);
1034 				dns_rdata_reset(&rdata);
1035 
1036 				if (nsec3param.hash != DNS_NSEC3_UNKNOWNALG &&
1037 				    !dns_nsec3_supportedhash(nsec3param.hash))
1038 				{
1039 					continue;
1040 				}
1041 
1042 				if (nsec3param.flags != 0) {
1043 					continue;
1044 				}
1045 
1046 				memmove(version->salt, nsec3param.salt,
1047 					nsec3param.salt_length);
1048 				version->hash = nsec3param.hash;
1049 				version->salt_length = nsec3param.salt_length;
1050 				version->iterations = nsec3param.iterations;
1051 				version->flags = nsec3param.flags;
1052 				version->havensec3 = true;
1053 				/*
1054 				 * Look for a better algorithm than the
1055 				 * unknown test algorithm.
1056 				 */
1057 				if (nsec3param.hash != DNS_NSEC3_UNKNOWNALG) {
1058 					goto unlock;
1059 				}
1060 			}
1061 		}
1062 	}
1063 unlock:
1064 	NODE_UNLOCK(&(qpdb->node_locks[node->locknum].lock), &nlocktype);
1065 }
1066 
1067 static void
1068 cleanup_nondirty(qpz_version_t *version, qpz_changedlist_t *cleanup_list) {
1069 	qpz_changed_t *changed = NULL, *next_changed = NULL;
1070 
1071 	/*
1072 	 * If the changed record is dirty, then an update created multiple
1073 	 * versions of a given rdataset.  We keep this list until we're the
1074 	 * least open version, at which point it's safe to get rid of any
1075 	 * older versions.
1076 	 *
1077 	 * If the changed record isn't dirty, then we don't need it anymore
1078 	 * since we're committing and not rolling back.
1079 	 *
1080 	 * The caller must be holding the database lock.
1081 	 */
1082 	for (changed = HEAD(version->changed_list); changed != NULL;
1083 	     changed = next_changed)
1084 	{
1085 		next_changed = NEXT(changed, link);
1086 		if (!changed->dirty) {
1087 			UNLINK(version->changed_list, changed, link);
1088 			APPEND(*cleanup_list, changed, link);
1089 		}
1090 	}
1091 }
1092 
1093 static void
1094 setsecure(dns_db_t *db, qpz_version_t *version, dns_dbnode_t *origin) {
1095 	dns_rdataset_t keyset;
1096 	dns_rdataset_t nsecset, signsecset;
1097 	bool haszonekey = false;
1098 	bool hasnsec = false;
1099 	isc_result_t result;
1100 
1101 	dns_rdataset_init(&keyset);
1102 	result = dns_db_findrdataset(db, origin, version, dns_rdatatype_dnskey,
1103 				     0, 0, &keyset, NULL);
1104 	if (result == ISC_R_SUCCESS) {
1105 		result = dns_rdataset_first(&keyset);
1106 		while (result == ISC_R_SUCCESS) {
1107 			dns_rdata_t keyrdata = DNS_RDATA_INIT;
1108 			dns_rdataset_current(&keyset, &keyrdata);
1109 			if (dns_zonekey_iszonekey(&keyrdata)) {
1110 				haszonekey = true;
1111 				break;
1112 			}
1113 			result = dns_rdataset_next(&keyset);
1114 		}
1115 		dns_rdataset_disassociate(&keyset);
1116 	}
1117 	if (!haszonekey) {
1118 		version->secure = false;
1119 		version->havensec3 = false;
1120 		return;
1121 	}
1122 
1123 	dns_rdataset_init(&nsecset);
1124 	dns_rdataset_init(&signsecset);
1125 	result = dns_db_findrdataset(db, origin, version, dns_rdatatype_nsec, 0,
1126 				     0, &nsecset, &signsecset);
1127 	if (result == ISC_R_SUCCESS) {
1128 		if (dns_rdataset_isassociated(&signsecset)) {
1129 			hasnsec = true;
1130 			dns_rdataset_disassociate(&signsecset);
1131 		}
1132 		dns_rdataset_disassociate(&nsecset);
1133 	}
1134 
1135 	setnsec3parameters(db, version);
1136 
1137 	/*
1138 	 * Do we have a valid NSEC/NSEC3 chain?
1139 	 */
1140 	if (version->havensec3 || hasnsec) {
1141 		version->secure = true;
1142 	} else {
1143 		version->secure = false;
1144 	}
1145 }
1146 
1147 static void
1148 currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
1149 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
1150 	qpz_version_t *version = NULL;
1151 
1152 	REQUIRE(VALID_QPZONE(qpdb));
1153 
1154 	RWLOCK(&qpdb->lock, isc_rwlocktype_read);
1155 	version = qpdb->current_version;
1156 	isc_refcount_increment(&version->references);
1157 	RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
1158 
1159 	*versionp = (dns_dbversion_t *)version;
1160 }
1161 
1162 static void
1163 attachversion(dns_db_t *db, dns_dbversion_t *source,
1164 	      dns_dbversion_t **targetp) {
1165 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
1166 	qpz_version_t *version = source;
1167 
1168 	REQUIRE(VALID_QPZONE(qpdb));
1169 	INSIST(version != NULL && version->qpdb == qpdb);
1170 
1171 	isc_refcount_increment(&version->references);
1172 
1173 	*targetp = version;
1174 }
1175 
1176 static isc_result_t
1177 newversion(dns_db_t *db, dns_dbversion_t **versionp) {
1178 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
1179 	qpz_version_t *version = NULL;
1180 
1181 	REQUIRE(VALID_QPZONE(qpdb));
1182 	REQUIRE(versionp != NULL && *versionp == NULL);
1183 	REQUIRE(qpdb->future_version == NULL);
1184 
1185 	RWLOCK(&qpdb->lock, isc_rwlocktype_write);
1186 	INSIST(qpdb->next_serial != 0);
1187 	version = allocate_version(qpdb->common.mctx, qpdb->next_serial, 1,
1188 				   true);
1189 	version->qpdb = qpdb;
1190 	version->secure = qpdb->current_version->secure;
1191 	version->havensec3 = qpdb->current_version->havensec3;
1192 	if (version->havensec3) {
1193 		version->flags = qpdb->current_version->flags;
1194 		version->iterations = qpdb->current_version->iterations;
1195 		version->hash = qpdb->current_version->hash;
1196 		version->salt_length = qpdb->current_version->salt_length;
1197 		memmove(version->salt, qpdb->current_version->salt,
1198 			version->salt_length);
1199 	}
1200 
1201 	version->records = qpdb->current_version->records;
1202 	version->xfrsize = qpdb->current_version->xfrsize;
1203 
1204 	qpdb->next_serial++;
1205 	qpdb->future_version = version;
1206 	RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
1207 
1208 	*versionp = version;
1209 
1210 	return ISC_R_SUCCESS;
1211 }
1212 
1213 static void
1214 resigninsert(qpzonedb_t *qpdb, dns_slabheader_t *newheader) {
1215 	REQUIRE(newheader->heap_index == 0);
1216 	REQUIRE(!ISC_LINK_LINKED(newheader, link));
1217 
1218 	RWLOCK(&qpdb->lock, isc_rwlocktype_write);
1219 	isc_heap_insert(qpdb->heap, newheader);
1220 	RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
1221 
1222 	newheader->heap = qpdb->heap;
1223 }
1224 
1225 static void
1226 resigndelete(qpzonedb_t *qpdb, qpz_version_t *version,
1227 	     dns_slabheader_t *header DNS__DB_FLARG) {
1228 	if (header == NULL || header->heap_index == 0) {
1229 		return;
1230 	}
1231 
1232 	RWLOCK(&qpdb->lock, isc_rwlocktype_write);
1233 	isc_heap_delete(qpdb->heap, header->heap_index);
1234 	RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
1235 
1236 	header->heap_index = 0;
1237 	newref(qpdb, HEADERNODE(header) DNS__DB_FLARG_PASS);
1238 	ISC_LIST_APPEND(version->resigned_list, header, link);
1239 }
1240 
1241 static void
1242 make_least_version(qpzonedb_t *qpdb, qpz_version_t *version,
1243 		   qpz_changedlist_t *cleanup_list) {
1244 	qpdb->least_serial = version->serial;
1245 	*cleanup_list = version->changed_list;
1246 	ISC_LIST_INIT(version->changed_list);
1247 }
1248 
1249 static void
1250 rollback_node(qpznode_t *node, uint32_t serial) {
1251 	dns_slabheader_t *header = NULL, *dcurrent = NULL;
1252 	bool make_dirty = false;
1253 
1254 	/*
1255 	 * We set the IGNORE attribute on rdatasets with serial number
1256 	 * 'serial'.  When the reference count goes to zero, these rdatasets
1257 	 * will be cleaned up; until that time, they will be ignored.
1258 	 */
1259 	for (header = node->data; header != NULL; header = header->next) {
1260 		if (header->serial == serial) {
1261 			DNS_SLABHEADER_SETATTR(header,
1262 					       DNS_SLABHEADERATTR_IGNORE);
1263 			make_dirty = true;
1264 		}
1265 		for (dcurrent = header->down; dcurrent != NULL;
1266 		     dcurrent = dcurrent->down)
1267 		{
1268 			if (dcurrent->serial == serial) {
1269 				DNS_SLABHEADER_SETATTR(
1270 					dcurrent, DNS_SLABHEADERATTR_IGNORE);
1271 				make_dirty = true;
1272 			}
1273 		}
1274 	}
1275 	if (make_dirty) {
1276 		node->dirty = true;
1277 	}
1278 }
1279 
1280 static void
1281 closeversion(dns_db_t *db, dns_dbversion_t **versionp,
1282 	     bool commit DNS__DB_FLARG) {
1283 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
1284 	qpz_version_t *version = NULL, *cleanup_version = NULL;
1285 	qpz_version_t *least_greater = NULL;
1286 	qpznode_t *node = NULL;
1287 	bool rollback = false;
1288 	qpz_changed_t *changed = NULL, *next_changed = NULL;
1289 	qpz_changedlist_t cleanup_list;
1290 	dns_slabheaderlist_t resigned_list;
1291 	dns_slabheader_t *header = NULL;
1292 	uint32_t serial, least_serial;
1293 
1294 	REQUIRE(VALID_QPZONE(qpdb));
1295 	version = (qpz_version_t *)*versionp;
1296 	INSIST(version->qpdb == qpdb);
1297 
1298 	if (isc_refcount_decrement(&version->references) > 1) {
1299 		*versionp = NULL;
1300 		return;
1301 	}
1302 
1303 	ISC_LIST_INIT(cleanup_list);
1304 	ISC_LIST_INIT(resigned_list);
1305 
1306 	/*
1307 	 * Update the zone's secure status in version before making
1308 	 * it the current version.
1309 	 */
1310 	if (version->writer && commit) {
1311 		setsecure(db, version, qpdb->origin);
1312 	}
1313 
1314 	RWLOCK(&qpdb->lock, isc_rwlocktype_write);
1315 	serial = version->serial;
1316 	if (version->writer) {
1317 		if (commit) {
1318 			unsigned int cur_ref;
1319 			qpz_version_t *cur_version = NULL;
1320 
1321 			INSIST(version == qpdb->future_version);
1322 			/*
1323 			 * The current version is going to be replaced.
1324 			 * Release the (likely last) reference to it from the
1325 			 * DB itself and unlink it from the open list.
1326 			 */
1327 			cur_version = qpdb->current_version;
1328 			cur_ref = isc_refcount_decrement(
1329 				&cur_version->references);
1330 			if (cur_ref == 1) {
1331 				(void)isc_refcount_current(
1332 					&cur_version->references);
1333 				if (cur_version->serial == qpdb->least_serial) {
1334 					INSIST(EMPTY(
1335 						cur_version->changed_list));
1336 				}
1337 				UNLINK(qpdb->open_versions, cur_version, link);
1338 			}
1339 			if (EMPTY(qpdb->open_versions)) {
1340 				/*
1341 				 * We're going to become the least open
1342 				 * version.
1343 				 */
1344 				make_least_version(qpdb, version,
1345 						   &cleanup_list);
1346 			} else {
1347 				/*
1348 				 * Some other open version is the
1349 				 * least version.  We can't cleanup
1350 				 * records that were changed in this
1351 				 * version because the older versions
1352 				 * may still be in use by an open
1353 				 * version.
1354 				 *
1355 				 * We can, however, discard the
1356 				 * changed records for things that
1357 				 * we've added that didn't exist in
1358 				 * prior versions.
1359 				 */
1360 				cleanup_nondirty(version, &cleanup_list);
1361 			}
1362 			/*
1363 			 * If the (soon to be former) current version
1364 			 * isn't being used by anyone, we can clean
1365 			 * it up.
1366 			 */
1367 			if (cur_ref == 1) {
1368 				cleanup_version = cur_version;
1369 				APPENDLIST(version->changed_list,
1370 					   cleanup_version->changed_list, link);
1371 			}
1372 			/*
1373 			 * Become the current version.
1374 			 */
1375 			version->writer = false;
1376 			qpdb->current_version = version;
1377 			qpdb->current_serial = version->serial;
1378 			qpdb->future_version = NULL;
1379 
1380 			/*
1381 			 * Keep the current version in the open list, and
1382 			 * gain a reference for the DB itself (see the DB
1383 			 * creation function below).  This must be the only
1384 			 * case where we need to increment the counter from
1385 			 * zero and need to use isc_refcount_increment0().
1386 			 */
1387 			INSIST(isc_refcount_increment0(&version->references) ==
1388 			       0);
1389 			PREPEND(qpdb->open_versions, qpdb->current_version,
1390 				link);
1391 			resigned_list = version->resigned_list;
1392 			ISC_LIST_INIT(version->resigned_list);
1393 		} else {
1394 			/*
1395 			 * We're rolling back this transaction.
1396 			 */
1397 			cleanup_list = version->changed_list;
1398 			ISC_LIST_INIT(version->changed_list);
1399 			resigned_list = version->resigned_list;
1400 			ISC_LIST_INIT(version->resigned_list);
1401 			rollback = true;
1402 			cleanup_version = version;
1403 			qpdb->future_version = NULL;
1404 		}
1405 	} else {
1406 		if (version != qpdb->current_version) {
1407 			/*
1408 			 * There are no external or internal references
1409 			 * to this version and it can be cleaned up.
1410 			 */
1411 			cleanup_version = version;
1412 
1413 			/*
1414 			 * Find the version with the least serial
1415 			 * number greater than ours.
1416 			 */
1417 			least_greater = PREV(version, link);
1418 			if (least_greater == NULL) {
1419 				least_greater = qpdb->current_version;
1420 			}
1421 
1422 			INSIST(version->serial < least_greater->serial);
1423 			/*
1424 			 * Is this the least open version?
1425 			 */
1426 			if (version->serial == qpdb->least_serial) {
1427 				/*
1428 				 * Yes.  Install the new least open
1429 				 * version.
1430 				 */
1431 				make_least_version(qpdb, least_greater,
1432 						   &cleanup_list);
1433 			} else {
1434 				/*
1435 				 * Add any unexecuted cleanups to
1436 				 * those of the least greater version.
1437 				 */
1438 				APPENDLIST(least_greater->changed_list,
1439 					   version->changed_list, link);
1440 			}
1441 		} else if (version->serial == qpdb->least_serial) {
1442 			INSIST(EMPTY(version->changed_list));
1443 		}
1444 		UNLINK(qpdb->open_versions, version, link);
1445 	}
1446 	least_serial = qpdb->least_serial;
1447 	RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
1448 
1449 	if (cleanup_version != NULL) {
1450 		isc_refcount_destroy(&cleanup_version->references);
1451 		INSIST(EMPTY(cleanup_version->changed_list));
1452 		free_gluetable(cleanup_version->glue_table);
1453 		isc_rwlock_destroy(&cleanup_version->rwlock);
1454 		isc_mem_put(qpdb->common.mctx, cleanup_version,
1455 			    sizeof(*cleanup_version));
1456 	}
1457 
1458 	/*
1459 	 * Commit/rollback re-signed headers.
1460 	 */
1461 	for (header = HEAD(resigned_list); header != NULL;
1462 	     header = HEAD(resigned_list))
1463 	{
1464 		isc_rwlock_t *lock = NULL;
1465 		isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
1466 
1467 		ISC_LIST_UNLINK(resigned_list, header, link);
1468 
1469 		lock = &qpdb->node_locks[HEADERNODE(header)->locknum].lock;
1470 		NODE_WRLOCK(lock, &nlocktype);
1471 		if (rollback && !IGNORE(header)) {
1472 			resigninsert(qpdb, header);
1473 		}
1474 		decref(qpdb, HEADERNODE(header), least_serial,
1475 		       &nlocktype DNS__DB_FLARG_PASS);
1476 		NODE_UNLOCK(lock, &nlocktype);
1477 	}
1478 
1479 	if (EMPTY(cleanup_list)) {
1480 		*versionp = NULL;
1481 		return;
1482 	}
1483 
1484 	for (changed = HEAD(cleanup_list); changed != NULL;
1485 	     changed = next_changed)
1486 	{
1487 		isc_rwlock_t *lock = NULL;
1488 		isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
1489 
1490 		next_changed = NEXT(changed, link);
1491 		node = changed->node;
1492 		lock = &qpdb->node_locks[node->locknum].lock;
1493 
1494 		NODE_WRLOCK(lock, &nlocktype);
1495 		if (rollback) {
1496 			rollback_node(node, serial);
1497 		}
1498 		decref(qpdb, node, least_serial, &nlocktype DNS__DB_FILELINE);
1499 
1500 		NODE_UNLOCK(lock, &nlocktype);
1501 
1502 		isc_mem_put(qpdb->common.mctx, changed, sizeof(*changed));
1503 	}
1504 
1505 	*versionp = NULL;
1506 }
1507 
1508 static isc_result_t
1509 findrdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
1510 	     dns_rdatatype_t type, dns_rdatatype_t covers,
1511 	     isc_stdtime_t now ISC_ATTR_UNUSED, dns_rdataset_t *rdataset,
1512 	     dns_rdataset_t *sigrdataset DNS__DB_FLARG) {
1513 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
1514 	qpznode_t *node = (qpznode_t *)dbnode;
1515 	dns_slabheader_t *header = NULL, *header_next = NULL;
1516 	dns_slabheader_t *found = NULL, *foundsig = NULL;
1517 	uint32_t serial;
1518 	qpz_version_t *version = dbversion;
1519 	bool close_version = false;
1520 	dns_typepair_t matchtype, sigmatchtype;
1521 	isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
1522 
1523 	REQUIRE(VALID_QPZONE(qpdb));
1524 	REQUIRE(type != dns_rdatatype_any);
1525 	INSIST(version == NULL || version->qpdb == qpdb);
1526 
1527 	if (version == NULL) {
1528 		currentversion(db, (dns_dbversion_t **)&version);
1529 		close_version = true;
1530 	}
1531 	serial = version->serial;
1532 
1533 	NODE_RDLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
1534 
1535 	matchtype = DNS_TYPEPAIR_VALUE(type, covers);
1536 	if (covers == 0) {
1537 		sigmatchtype = DNS_SIGTYPE(type);
1538 	} else {
1539 		sigmatchtype = 0;
1540 	}
1541 
1542 	for (header = node->data; header != NULL; header = header_next) {
1543 		header_next = header->next;
1544 		do {
1545 			if (header->serial <= serial && !IGNORE(header)) {
1546 				if (NONEXISTENT(header)) {
1547 					header = NULL;
1548 				}
1549 				break;
1550 			} else {
1551 				header = header->down;
1552 			}
1553 		} while (header != NULL);
1554 		if (header != NULL) {
1555 			/*
1556 			 * We have an active, extant rdataset.  If it's a
1557 			 * type we're looking for, remember it.
1558 			 */
1559 			if (header->type == matchtype) {
1560 				found = header;
1561 				if (foundsig != NULL) {
1562 					break;
1563 				}
1564 			} else if (header->type == sigmatchtype) {
1565 				foundsig = header;
1566 				if (found != NULL) {
1567 					break;
1568 				}
1569 			}
1570 		}
1571 	}
1572 	if (found != NULL) {
1573 		bindrdataset(qpdb, node, found, 0, rdataset DNS__DB_FLARG_PASS);
1574 		if (foundsig != NULL) {
1575 			bindrdataset(qpdb, node, foundsig, 0,
1576 				     sigrdataset DNS__DB_FLARG_PASS);
1577 		}
1578 	}
1579 
1580 	NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
1581 
1582 	if (close_version) {
1583 		closeversion(db, (dns_dbversion_t **)&version,
1584 			     false DNS__DB_FLARG_PASS);
1585 	}
1586 
1587 	if (found == NULL) {
1588 		return ISC_R_NOTFOUND;
1589 	}
1590 
1591 	return ISC_R_SUCCESS;
1592 }
1593 
1594 static bool
1595 delegating_type(qpzonedb_t *qpdb, qpznode_t *node, dns_typepair_t type) {
1596 	return type == dns_rdatatype_dname ||
1597 	       (type == dns_rdatatype_ns &&
1598 		(node != qpdb->origin || IS_STUB(qpdb)));
1599 }
1600 
1601 static void
1602 loading_addnode(qpz_load_t *loadctx, const dns_name_t *name,
1603 		dns_rdatatype_t type, dns_rdatatype_t covers,
1604 		qpznode_t **nodep) {
1605 	qpzonedb_t *qpdb = (qpzonedb_t *)loadctx->db;
1606 	isc_result_t result;
1607 	qpznode_t *node = NULL, *nsecnode = NULL;
1608 
1609 	if (type == dns_rdatatype_nsec3 || covers == dns_rdatatype_nsec3) {
1610 		result = dns_qp_getname(loadctx->nsec3, name, (void **)&node,
1611 					NULL);
1612 		if (result == ISC_R_SUCCESS) {
1613 			*nodep = node;
1614 		} else {
1615 			node = new_qpznode(qpdb, name);
1616 			result = dns_qp_insert(loadctx->nsec3, node, 0);
1617 			INSIST(result == ISC_R_SUCCESS);
1618 			node->nsec = DNS_DB_NSEC_NSEC3;
1619 			*nodep = node;
1620 			qpznode_detach(&node);
1621 		}
1622 		return;
1623 	}
1624 
1625 	result = dns_qp_getname(loadctx->tree, name, (void **)&node, NULL);
1626 	if (result == ISC_R_SUCCESS) {
1627 		if (type == dns_rdatatype_nsec &&
1628 		    node->nsec == DNS_DB_NSEC_HAS_NSEC)
1629 		{
1630 			goto done;
1631 		}
1632 	} else {
1633 		INSIST(node == NULL);
1634 		node = new_qpznode(qpdb, name);
1635 		result = dns_qp_insert(loadctx->tree, node, 0);
1636 		INSIST(result == ISC_R_SUCCESS);
1637 		qpznode_unref(node);
1638 	}
1639 	if (type != dns_rdatatype_nsec) {
1640 		goto done;
1641 	}
1642 
1643 	/*
1644 	 * We're adding an NSEC record, so create a node in the nsec tree
1645 	 * too. This tree speeds searches for closest NSECs that would
1646 	 * otherwise need to examine many irrelevant nodes in large TLDs.
1647 	 */
1648 	nsecnode = new_qpznode(qpdb, name);
1649 	result = dns_qp_insert(loadctx->nsec, nsecnode, 0);
1650 	node->nsec = DNS_DB_NSEC_HAS_NSEC;
1651 	if (result == ISC_R_SUCCESS) {
1652 		nsecnode->nsec = DNS_DB_NSEC_NSEC;
1653 	}
1654 	qpznode_detach(&nsecnode);
1655 
1656 done:
1657 	*nodep = node;
1658 }
1659 
1660 static bool
1661 cname_and_other(qpznode_t *node, uint32_t serial) {
1662 	dns_slabheader_t *header = NULL, *header_next = NULL;
1663 	bool cname = false, other = false;
1664 	dns_rdatatype_t rdtype;
1665 
1666 	/*
1667 	 * Look for CNAME and "other data" rdatasets active in our version.
1668 	 * ("Other data" is any rdataset whose type is not KEY, NSEC, SIG
1669 	 * or RRSIG.
1670 	 */
1671 	for (header = node->data; header != NULL; header = header_next) {
1672 		header_next = header->next;
1673 
1674 		if (!prio_type(header->type)) {
1675 			/*
1676 			 * CNAME is in the priority list, so if we are done
1677 			 * with priority types, we know there will not be a
1678 			 * CNAME, and are safe to skip the rest.
1679 			 */
1680 			return false;
1681 		}
1682 
1683 		rdtype = DNS_TYPEPAIR_TYPE(header->type);
1684 		if (rdtype == dns_rdatatype_cname) {
1685 			do {
1686 				if (header->serial <= serial && !IGNORE(header))
1687 				{
1688 					if (NONEXISTENT(header)) {
1689 						header = NULL;
1690 					}
1691 					break;
1692 				}
1693 				header = header->down;
1694 			} while (header != NULL);
1695 			if (header != NULL) {
1696 				cname = true;
1697 			}
1698 		} else if (rdtype != dns_rdatatype_key &&
1699 			   rdtype != dns_rdatatype_sig &&
1700 			   rdtype != dns_rdatatype_nsec &&
1701 			   rdtype != dns_rdatatype_rrsig)
1702 		{
1703 			do {
1704 				if (header->serial <= serial && !IGNORE(header))
1705 				{
1706 					if (NONEXISTENT(header)) {
1707 						header = NULL;
1708 					}
1709 					break;
1710 				}
1711 				header = header->down;
1712 			} while (header != NULL);
1713 			if (header != NULL) {
1714 				other = true;
1715 			}
1716 		}
1717 
1718 		if (cname && other) {
1719 			return true;
1720 		}
1721 	}
1722 
1723 	return false;
1724 }
1725 
1726 static qpz_changed_t *
1727 add_changed(dns_slabheader_t *header, qpz_version_t *version DNS__DB_FLARG) {
1728 	qpz_changed_t *changed = NULL;
1729 	qpzonedb_t *qpdb = (qpzonedb_t *)header->db;
1730 	qpznode_t *node = (qpznode_t *)header->node;
1731 
1732 	changed = isc_mem_get(qpdb->common.mctx, sizeof(*changed));
1733 
1734 	RWLOCK(&qpdb->lock, isc_rwlocktype_write);
1735 	REQUIRE(version->writer);
1736 
1737 	*changed = (qpz_changed_t){ .node = node };
1738 	ISC_LIST_INITANDAPPEND(version->changed_list, changed, link);
1739 	newref(qpdb, node DNS__DB_FLARG_PASS);
1740 	RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
1741 
1742 	return changed;
1743 }
1744 
1745 static uint64_t
1746 recordsize(dns_slabheader_t *header, unsigned int namelen) {
1747 	return dns_rdataslab_rdatasize((unsigned char *)header,
1748 				       sizeof(*header)) +
1749 	       sizeof(dns_ttl_t) + sizeof(dns_rdatatype_t) +
1750 	       sizeof(dns_rdataclass_t) + namelen;
1751 }
1752 
1753 static void
1754 maybe_update_recordsandsize(bool add, qpz_version_t *version,
1755 			    dns_slabheader_t *header, unsigned int namelen) {
1756 	unsigned char *hdr = (unsigned char *)header;
1757 	size_t hdrsize = sizeof(*header);
1758 
1759 	if (NONEXISTENT(header)) {
1760 		return;
1761 	}
1762 
1763 	RWLOCK(&version->rwlock, isc_rwlocktype_write);
1764 	if (add) {
1765 		version->records += dns_rdataslab_count(hdr, hdrsize);
1766 		version->xfrsize += recordsize(header, namelen);
1767 	} else {
1768 		version->records -= dns_rdataslab_count(hdr, hdrsize);
1769 		version->xfrsize -= recordsize(header, namelen);
1770 	}
1771 	RWUNLOCK(&version->rwlock, isc_rwlocktype_write);
1772 }
1773 
1774 static isc_result_t
1775 add(qpzonedb_t *qpdb, qpznode_t *node, const dns_name_t *nodename,
1776     qpz_version_t *version, dns_slabheader_t *newheader, unsigned int options,
1777     bool loading, dns_rdataset_t *addedrdataset,
1778     isc_stdtime_t now DNS__DB_FLARG) {
1779 	qpz_changed_t *changed = NULL;
1780 	dns_slabheader_t *topheader = NULL, *topheader_prev = NULL;
1781 	dns_slabheader_t *prioheader = NULL;
1782 	dns_slabheader_t *header = NULL;
1783 	unsigned char *merged = NULL;
1784 	isc_result_t result;
1785 	bool merge = false;
1786 	uint32_t ntypes;
1787 
1788 	if ((options & DNS_DBADD_MERGE) != 0) {
1789 		REQUIRE(version != NULL);
1790 		merge = true;
1791 	}
1792 
1793 	if (!loading) {
1794 		/*
1795 		 * We always add a changed record, even if no changes end up
1796 		 * being made to this node, because it's harmless and
1797 		 * simplifies the code.
1798 		 */
1799 		changed = add_changed(newheader, version DNS__DB_FLARG_PASS);
1800 	}
1801 
1802 	ntypes = 0;
1803 	for (topheader = node->data; topheader != NULL;
1804 	     topheader = topheader->next)
1805 	{
1806 		++ntypes;
1807 		if (prio_type(topheader->type)) {
1808 			prioheader = topheader;
1809 		}
1810 		if (topheader->type == newheader->type) {
1811 			break;
1812 		}
1813 		topheader_prev = topheader;
1814 	}
1815 
1816 	/*
1817 	 * If topheader isn't NULL, we've found the right type.  There may be
1818 	 * IGNORE rdatasets between the top of the chain and the first real
1819 	 * data.  We skip over them.
1820 	 */
1821 	header = topheader;
1822 	while (header != NULL && IGNORE(header)) {
1823 		header = header->down;
1824 	}
1825 	if (header != NULL) {
1826 		/*
1827 		 * If 'merge' is true and header isn't empty/nonexistent,
1828 		 * we'll try to create a new rdataset that is the union
1829 		 * of 'newheader' and 'header'.
1830 		 */
1831 		if (merge && !NONEXISTENT(header)) {
1832 			unsigned int flags = 0;
1833 			INSIST(version->serial >= header->serial);
1834 			merged = NULL;
1835 			result = ISC_R_SUCCESS;
1836 
1837 			if ((options & DNS_DBADD_EXACT) != 0) {
1838 				flags |= DNS_RDATASLAB_EXACT;
1839 			}
1840 			if ((options & DNS_DBADD_EXACTTTL) != 0 &&
1841 			    newheader->ttl != header->ttl)
1842 			{
1843 				result = DNS_R_NOTEXACT;
1844 			} else if (newheader->ttl != header->ttl) {
1845 				flags |= DNS_RDATASLAB_FORCE;
1846 			}
1847 			if (result == ISC_R_SUCCESS) {
1848 				result = dns_rdataslab_merge(
1849 					(unsigned char *)header,
1850 					(unsigned char *)newheader,
1851 					(unsigned int)(sizeof(*newheader)),
1852 					qpdb->common.mctx, qpdb->common.rdclass,
1853 					(dns_rdatatype_t)header->type, flags,
1854 					qpdb->maxrrperset, &merged);
1855 			}
1856 			if (result == ISC_R_SUCCESS) {
1857 				/*
1858 				 * If 'header' has the same serial number as
1859 				 * we do, we could clean it up now if we knew
1860 				 * that our caller had no references to it.
1861 				 * We don't know this, however, so we leave it
1862 				 * alone.  It will get cleaned up when
1863 				 * clean_zone_node() runs.
1864 				 */
1865 				dns_slabheader_destroy(&newheader);
1866 				newheader = (dns_slabheader_t *)merged;
1867 				dns_slabheader_reset(newheader,
1868 						     (dns_db_t *)qpdb,
1869 						     (dns_dbnode_t *)node);
1870 				dns_slabheader_copycase(newheader, header);
1871 				if (loading && RESIGN(newheader) &&
1872 				    RESIGN(header) &&
1873 				    resign_sooner(header, newheader))
1874 				{
1875 					newheader->resign = header->resign;
1876 					newheader->resign_lsb =
1877 						header->resign_lsb;
1878 				}
1879 			} else {
1880 				if (result == DNS_R_TOOMANYRECORDS) {
1881 					dns__db_logtoomanyrecords(
1882 						(dns_db_t *)qpdb, nodename,
1883 						(dns_rdatatype_t)header->type,
1884 						"updating", qpdb->maxrrperset);
1885 				}
1886 				dns_slabheader_destroy(&newheader);
1887 				return result;
1888 			}
1889 		}
1890 
1891 		INSIST(version->serial >= topheader->serial);
1892 		if (loading) {
1893 			newheader->down = NULL;
1894 			if (RESIGN(newheader)) {
1895 				resigninsert(qpdb, newheader);
1896 				/* resigndelete not needed here */
1897 			}
1898 
1899 			/*
1900 			 * There are no other references to 'header' when
1901 			 * loading, so we MAY clean up 'header' now.
1902 			 * Since we don't generate changed records when
1903 			 * loading, we MUST clean up 'header' now.
1904 			 */
1905 			if (topheader_prev != NULL) {
1906 				topheader_prev->next = newheader;
1907 			} else {
1908 				node->data = newheader;
1909 			}
1910 			newheader->next = topheader->next;
1911 			maybe_update_recordsandsize(false, version, header,
1912 						    nodename->length);
1913 			dns_slabheader_destroy(&header);
1914 		} else {
1915 			if (RESIGN(newheader)) {
1916 				resigninsert(qpdb, newheader);
1917 				resigndelete(qpdb, version,
1918 					     header DNS__DB_FLARG_PASS);
1919 			}
1920 			if (topheader_prev != NULL) {
1921 				topheader_prev->next = newheader;
1922 			} else {
1923 				node->data = newheader;
1924 			}
1925 			newheader->next = topheader->next;
1926 			newheader->down = topheader;
1927 			topheader->next = newheader;
1928 			node->dirty = true;
1929 			if (changed != NULL) {
1930 				changed->dirty = true;
1931 			}
1932 			maybe_update_recordsandsize(false, version, header,
1933 						    nodename->length);
1934 		}
1935 	} else {
1936 		/*
1937 		 * No non-IGNORED rdatasets of the given type exist at
1938 		 * this node.
1939 		 *
1940 		 * If we're trying to delete the type, don't bother.
1941 		 */
1942 		if (NONEXISTENT(newheader)) {
1943 			dns_slabheader_destroy(&newheader);
1944 			return DNS_R_UNCHANGED;
1945 		}
1946 
1947 		if (RESIGN(newheader)) {
1948 			resigninsert(qpdb, newheader);
1949 			resigndelete(qpdb, version, header DNS__DB_FLARG_PASS);
1950 		}
1951 
1952 		if (topheader != NULL) {
1953 			/*
1954 			 * We have a list of rdatasets of the given type,
1955 			 * but they're all marked IGNORE.  We simply insert
1956 			 * the new rdataset at the head of the list.
1957 			 *
1958 			 * Ignored rdatasets cannot occur during loading, so
1959 			 * we INSIST on it.
1960 			 */
1961 			INSIST(!loading);
1962 			INSIST(version->serial >= topheader->serial);
1963 			if (topheader_prev != NULL) {
1964 				topheader_prev->next = newheader;
1965 			} else {
1966 				node->data = newheader;
1967 			}
1968 			newheader->next = topheader->next;
1969 			newheader->down = topheader;
1970 			topheader->next = newheader;
1971 			if (changed != NULL) {
1972 				changed->dirty = true;
1973 			}
1974 			node->dirty = true;
1975 		} else {
1976 			/*
1977 			 * No rdatasets of the given type exist at the node.
1978 			 */
1979 
1980 			if (qpdb->maxtypepername > 0 &&
1981 			    ntypes >= qpdb->maxtypepername)
1982 			{
1983 				dns_slabheader_destroy(&newheader);
1984 				return DNS_R_TOOMANYRECORDS;
1985 			}
1986 
1987 			INSIST(newheader->down == NULL);
1988 
1989 			if (prio_type(newheader->type)) {
1990 				/* This is a priority type, prepend it */
1991 				newheader->next = node->data;
1992 				node->data = newheader;
1993 			} else if (prioheader != NULL) {
1994 				/* Append after the priority headers */
1995 				newheader->next = prioheader->next;
1996 				prioheader->next = newheader;
1997 			} else {
1998 				/* There were no priority headers */
1999 				newheader->next = node->data;
2000 				node->data = newheader;
2001 			}
2002 		}
2003 	}
2004 
2005 	maybe_update_recordsandsize(true, version, newheader, nodename->length);
2006 
2007 	/*
2008 	 * Check if the node now contains CNAME and other data.
2009 	 */
2010 	if (cname_and_other(node, version->serial)) {
2011 		return DNS_R_CNAMEANDOTHER;
2012 	}
2013 
2014 	if (addedrdataset != NULL) {
2015 		bindrdataset(qpdb, node, newheader, now,
2016 			     addedrdataset DNS__DB_FLARG_PASS);
2017 	}
2018 
2019 	return ISC_R_SUCCESS;
2020 }
2021 
2022 static void
2023 wildcardmagic(qpzonedb_t *qpdb, dns_qp_t *qp, const dns_name_t *name) {
2024 	isc_result_t result;
2025 	dns_name_t foundname;
2026 	dns_offsets_t offsets;
2027 	unsigned int n;
2028 	qpznode_t *node = NULL;
2029 
2030 	dns_name_init(&foundname, offsets);
2031 	n = dns_name_countlabels(name);
2032 	INSIST(n >= 2);
2033 	n--;
2034 	dns_name_getlabelsequence(name, 1, n, &foundname);
2035 
2036 	/* insert an empty node, if needed, to hold the wildcard bit */
2037 	result = dns_qp_getname(qp, &foundname, (void **)&node, NULL);
2038 	if (result != ISC_R_SUCCESS) {
2039 		INSIST(node == NULL);
2040 		node = new_qpznode(qpdb, &foundname);
2041 		result = dns_qp_insert(qp, node, 0);
2042 		INSIST(result == ISC_R_SUCCESS);
2043 		qpznode_unref(node);
2044 	}
2045 
2046 	node->wild = true;
2047 }
2048 
2049 static void
2050 addwildcards(qpzonedb_t *qpdb, dns_qp_t *qp, const dns_name_t *name) {
2051 	dns_name_t foundname;
2052 	dns_offsets_t offsets;
2053 	unsigned int n, l, i;
2054 
2055 	dns_name_init(&foundname, offsets);
2056 	n = dns_name_countlabels(name);
2057 	l = dns_name_countlabels(&qpdb->common.origin);
2058 	i = l + 1;
2059 	while (i < n) {
2060 		dns_name_getlabelsequence(name, n - i, i, &foundname);
2061 		if (dns_name_iswildcard(&foundname)) {
2062 			wildcardmagic(qpdb, qp, &foundname);
2063 		}
2064 
2065 		i++;
2066 	}
2067 }
2068 
2069 static isc_result_t
2070 loading_addrdataset(void *arg, const dns_name_t *name,
2071 		    dns_rdataset_t *rdataset DNS__DB_FLARG) {
2072 	qpz_load_t *loadctx = arg;
2073 	qpzonedb_t *qpdb = (qpzonedb_t *)loadctx->db;
2074 	qpznode_t *node = NULL;
2075 	isc_result_t result = ISC_R_SUCCESS;
2076 	isc_region_t region;
2077 	dns_slabheader_t *newheader = NULL;
2078 	isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
2079 
2080 	REQUIRE(rdataset->rdclass == qpdb->common.rdclass);
2081 
2082 	/*
2083 	 * SOA records are only allowed at top of zone.
2084 	 */
2085 	if (rdataset->type == dns_rdatatype_soa &&
2086 	    !dns_name_equal(name, &qpdb->common.origin))
2087 	{
2088 		return DNS_R_NOTZONETOP;
2089 	}
2090 
2091 	if (rdataset->type != dns_rdatatype_nsec3 &&
2092 	    rdataset->covers != dns_rdatatype_nsec3)
2093 	{
2094 		addwildcards(qpdb, loadctx->tree, name);
2095 	}
2096 
2097 	if (dns_name_iswildcard(name)) {
2098 		if (rdataset->type == dns_rdatatype_ns) {
2099 			/*
2100 			 * NS owners cannot legally be wild cards.
2101 			 */
2102 			return DNS_R_INVALIDNS;
2103 		}
2104 
2105 		if (rdataset->type == dns_rdatatype_nsec3) {
2106 			/*
2107 			 * NSEC3 owners cannot legally be wild cards.
2108 			 */
2109 			return DNS_R_INVALIDNSEC3;
2110 		}
2111 
2112 		wildcardmagic(qpdb, loadctx->tree, name);
2113 	}
2114 
2115 	loading_addnode(loadctx, name, rdataset->type, rdataset->covers, &node);
2116 	result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx,
2117 					    &region, sizeof(dns_slabheader_t),
2118 					    qpdb->maxrrperset);
2119 	if (result != ISC_R_SUCCESS) {
2120 		if (result == DNS_R_TOOMANYRECORDS) {
2121 			dns__db_logtoomanyrecords((dns_db_t *)qpdb, name,
2122 						  rdataset->type, "adding",
2123 						  qpdb->maxrrperset);
2124 		}
2125 		return result;
2126 	}
2127 
2128 	newheader = (dns_slabheader_t *)region.base;
2129 	*newheader = (dns_slabheader_t){
2130 		.type = DNS_TYPEPAIR_VALUE(rdataset->type, rdataset->covers),
2131 		.ttl = rdataset->ttl + loadctx->now,
2132 		.trust = rdataset->trust,
2133 		.node = node,
2134 		.serial = 1,
2135 		.count = 1,
2136 	};
2137 
2138 	dns_slabheader_reset(newheader, (dns_db_t *)qpdb, node);
2139 	dns_slabheader_setownercase(newheader, name);
2140 
2141 	if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
2142 		DNS_SLABHEADER_SETATTR(newheader, DNS_SLABHEADERATTR_RESIGN);
2143 		newheader->resign =
2144 			(isc_stdtime_t)(dns_time64_from32(rdataset->resign) >>
2145 					1);
2146 		newheader->resign_lsb = rdataset->resign & 0x1;
2147 	}
2148 
2149 	NODE_WRLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
2150 	result = add(qpdb, node, name, qpdb->current_version, newheader,
2151 		     DNS_DBADD_MERGE, true, NULL, 0 DNS__DB_FLARG_PASS);
2152 	NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
2153 
2154 	if (result == ISC_R_SUCCESS &&
2155 	    delegating_type(qpdb, node, rdataset->type))
2156 	{
2157 		node->delegating = true;
2158 	} else if (result == DNS_R_UNCHANGED) {
2159 		result = ISC_R_SUCCESS;
2160 	}
2161 
2162 	return result;
2163 }
2164 
2165 static void
2166 loading_setup(void *arg) {
2167 	qpz_load_t *loadctx = arg;
2168 	qpzonedb_t *qpdb = (qpzonedb_t *)loadctx->db;
2169 
2170 	dns_qpmulti_write(qpdb->tree, &loadctx->tree);
2171 	dns_qpmulti_write(qpdb->nsec, &loadctx->nsec);
2172 	dns_qpmulti_write(qpdb->nsec3, &loadctx->nsec3);
2173 }
2174 
2175 static void
2176 loading_commit(void *arg) {
2177 	qpz_load_t *loadctx = arg;
2178 	qpzonedb_t *qpdb = (qpzonedb_t *)loadctx->db;
2179 
2180 	if (loadctx->tree != NULL) {
2181 		dns_qp_compact(loadctx->tree, DNS_QPGC_MAYBE);
2182 		dns_qpmulti_commit(qpdb->tree, &loadctx->tree);
2183 	}
2184 	if (loadctx->nsec != NULL) {
2185 		dns_qp_compact(loadctx->nsec, DNS_QPGC_MAYBE);
2186 		dns_qpmulti_commit(qpdb->nsec, &loadctx->nsec);
2187 	}
2188 	if (loadctx->nsec3 != NULL) {
2189 		dns_qp_compact(loadctx->nsec3, DNS_QPGC_MAYBE);
2190 		dns_qpmulti_commit(qpdb->nsec3, &loadctx->nsec3);
2191 	}
2192 }
2193 
2194 static isc_result_t
2195 beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
2196 	qpz_load_t *loadctx = NULL;
2197 	qpzonedb_t *qpdb = NULL;
2198 	qpdb = (qpzonedb_t *)db;
2199 
2200 	REQUIRE(DNS_CALLBACK_VALID(callbacks));
2201 	REQUIRE(VALID_QPZONE(qpdb));
2202 
2203 	loadctx = isc_mem_get(qpdb->common.mctx, sizeof(*loadctx));
2204 	*loadctx = (qpz_load_t){ .db = db };
2205 
2206 	RWLOCK(&qpdb->lock, isc_rwlocktype_write);
2207 
2208 	REQUIRE((qpdb->attributes & (QPDB_ATTR_LOADED | QPDB_ATTR_LOADING)) ==
2209 		0);
2210 	qpdb->attributes |= QPDB_ATTR_LOADING;
2211 
2212 	RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
2213 
2214 	callbacks->add = loading_addrdataset;
2215 	callbacks->setup = loading_setup;
2216 	callbacks->commit = loading_commit;
2217 	callbacks->add_private = loadctx;
2218 
2219 	return ISC_R_SUCCESS;
2220 }
2221 
2222 static isc_result_t
2223 endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
2224 	qpz_load_t *loadctx = NULL;
2225 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
2226 
2227 	REQUIRE(VALID_QPZONE(qpdb));
2228 	REQUIRE(DNS_CALLBACK_VALID(callbacks));
2229 	loadctx = callbacks->add_private;
2230 	REQUIRE(loadctx != NULL);
2231 	REQUIRE(loadctx->db == db);
2232 
2233 	RWLOCK(&qpdb->lock, isc_rwlocktype_write);
2234 
2235 	REQUIRE((qpdb->attributes & QPDB_ATTR_LOADING) != 0);
2236 	REQUIRE((qpdb->attributes & QPDB_ATTR_LOADED) == 0);
2237 
2238 	qpdb->attributes &= ~QPDB_ATTR_LOADING;
2239 	qpdb->attributes |= QPDB_ATTR_LOADED;
2240 
2241 	if (qpdb->origin != NULL) {
2242 		dns_dbversion_t *version = qpdb->current_version;
2243 		RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
2244 		setsecure(db, version, qpdb->origin);
2245 	} else {
2246 		RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
2247 	}
2248 
2249 	callbacks->add = NULL;
2250 	callbacks->setup = NULL;
2251 	callbacks->commit = NULL;
2252 	callbacks->add_private = NULL;
2253 
2254 	isc_mem_put(qpdb->common.mctx, loadctx, sizeof(*loadctx));
2255 
2256 	return ISC_R_SUCCESS;
2257 }
2258 
2259 static bool
2260 issecure(dns_db_t *db) {
2261 	qpzonedb_t *qpdb = NULL;
2262 	bool secure;
2263 
2264 	qpdb = (qpzonedb_t *)db;
2265 
2266 	REQUIRE(VALID_QPZONE(qpdb));
2267 
2268 	RWLOCK(&qpdb->lock, isc_rwlocktype_read);
2269 	secure = qpdb->current_version->secure;
2270 	RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
2271 
2272 	return secure;
2273 }
2274 
2275 static isc_result_t
2276 getnsec3parameters(dns_db_t *db, dns_dbversion_t *dbversion, dns_hash_t *hash,
2277 		   uint8_t *flags, uint16_t *iterations, unsigned char *salt,
2278 		   size_t *salt_length) {
2279 	qpzonedb_t *qpdb = NULL;
2280 	isc_result_t result = ISC_R_NOTFOUND;
2281 	qpz_version_t *version = dbversion;
2282 
2283 	qpdb = (qpzonedb_t *)db;
2284 
2285 	REQUIRE(VALID_QPZONE(qpdb));
2286 	INSIST(version == NULL || version->qpdb == qpdb);
2287 
2288 	RWLOCK(&qpdb->lock, isc_rwlocktype_read);
2289 	if (version == NULL) {
2290 		version = qpdb->current_version;
2291 	}
2292 
2293 	if (version->havensec3) {
2294 		if (hash != NULL) {
2295 			*hash = version->hash;
2296 		}
2297 		if (salt != NULL && salt_length != NULL) {
2298 			REQUIRE(*salt_length >= version->salt_length);
2299 			memmove(salt, version->salt, version->salt_length);
2300 		}
2301 		if (salt_length != NULL) {
2302 			*salt_length = version->salt_length;
2303 		}
2304 		if (iterations != NULL) {
2305 			*iterations = version->iterations;
2306 		}
2307 		if (flags != NULL) {
2308 			*flags = version->flags;
2309 		}
2310 		result = ISC_R_SUCCESS;
2311 	}
2312 	RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
2313 
2314 	return result;
2315 }
2316 
2317 static isc_result_t
2318 getsize(dns_db_t *db, dns_dbversion_t *dbversion, uint64_t *records,
2319 	uint64_t *xfrsize) {
2320 	qpzonedb_t *qpdb = NULL;
2321 	qpz_version_t *version = dbversion;
2322 	isc_result_t result = ISC_R_SUCCESS;
2323 
2324 	qpdb = (qpzonedb_t *)db;
2325 
2326 	REQUIRE(VALID_QPZONE(qpdb));
2327 	INSIST(version == NULL || version->qpdb == qpdb);
2328 
2329 	RWLOCK(&qpdb->lock, isc_rwlocktype_read);
2330 	if (version == NULL) {
2331 		version = qpdb->current_version;
2332 	}
2333 
2334 	RWLOCK(&version->rwlock, isc_rwlocktype_read);
2335 	SET_IF_NOT_NULL(records, version->records);
2336 
2337 	SET_IF_NOT_NULL(xfrsize, version->xfrsize);
2338 	RWUNLOCK(&version->rwlock, isc_rwlocktype_read);
2339 	RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
2340 
2341 	return result;
2342 }
2343 
2344 static isc_result_t
2345 setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) {
2346 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
2347 	dns_slabheader_t *header = NULL, oldheader;
2348 	isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
2349 
2350 	REQUIRE(VALID_QPZONE(qpdb));
2351 	REQUIRE(rdataset != NULL);
2352 	REQUIRE(rdataset->methods == &dns_rdataslab_rdatasetmethods);
2353 
2354 	header = dns_slabheader_fromrdataset(rdataset);
2355 
2356 	NODE_WRLOCK(&qpdb->node_locks[HEADERNODE(header)->locknum].lock,
2357 		    &nlocktype);
2358 
2359 	oldheader = *header;
2360 
2361 	/*
2362 	 * Only break the heap invariant (by adjusting resign and resign_lsb)
2363 	 * if we are going to be restoring it by calling isc_heap_increased
2364 	 * or isc_heap_decreased.
2365 	 */
2366 	if (resign != 0) {
2367 		header->resign = (isc_stdtime_t)(dns_time64_from32(resign) >>
2368 						 1);
2369 		header->resign_lsb = resign & 0x1;
2370 	}
2371 	if (header->heap_index != 0) {
2372 		INSIST(RESIGN(header));
2373 		RWLOCK(&qpdb->lock, isc_rwlocktype_write);
2374 		if (resign == 0) {
2375 			isc_heap_delete(qpdb->heap, header->heap_index);
2376 			header->heap_index = 0;
2377 			header->heap = NULL;
2378 		} else if (resign_sooner(header, &oldheader)) {
2379 			isc_heap_increased(qpdb->heap, header->heap_index);
2380 		} else if (resign_sooner(&oldheader, header)) {
2381 			isc_heap_decreased(qpdb->heap, header->heap_index);
2382 		}
2383 		RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
2384 	} else if (resign != 0) {
2385 		DNS_SLABHEADER_SETATTR(header, DNS_SLABHEADERATTR_RESIGN);
2386 		resigninsert(qpdb, header);
2387 	}
2388 	NODE_UNLOCK(&qpdb->node_locks[HEADERNODE(header)->locknum].lock,
2389 		    &nlocktype);
2390 	return ISC_R_SUCCESS;
2391 }
2392 
2393 static isc_result_t
2394 getsigningtime(dns_db_t *db, isc_stdtime_t *resign, dns_name_t *foundname,
2395 	       dns_typepair_t *typepair) {
2396 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
2397 	dns_slabheader_t *header = NULL;
2398 	isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
2399 	uint16_t locknum;
2400 	isc_result_t result = ISC_R_NOTFOUND;
2401 
2402 	REQUIRE(VALID_QPZONE(qpdb));
2403 	REQUIRE(resign != NULL);
2404 	REQUIRE(foundname != NULL);
2405 	REQUIRE(typepair != NULL);
2406 
2407 	RWLOCK(&qpdb->lock, isc_rwlocktype_read);
2408 	header = isc_heap_element(qpdb->heap, 1);
2409 	if (header == NULL) {
2410 		RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
2411 		return ISC_R_NOTFOUND;
2412 	}
2413 	locknum = HEADERNODE(header)->locknum;
2414 	RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
2415 
2416 again:
2417 	NODE_RDLOCK(&qpdb->node_locks[locknum].lock, &nlocktype);
2418 
2419 	RWLOCK(&qpdb->lock, isc_rwlocktype_read);
2420 	header = isc_heap_element(qpdb->heap, 1);
2421 	if (header != NULL && HEADERNODE(header)->locknum != locknum) {
2422 		RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
2423 		NODE_UNLOCK(&qpdb->node_locks[locknum].lock, &nlocktype);
2424 		locknum = HEADERNODE(header)->locknum;
2425 		goto again;
2426 	}
2427 
2428 	if (header != NULL) {
2429 		*resign = RESIGN(header)
2430 				  ? (header->resign << 1) | header->resign_lsb
2431 				  : 0;
2432 		dns_name_copy(&HEADERNODE(header)->name, foundname);
2433 		*typepair = header->type;
2434 		result = ISC_R_SUCCESS;
2435 	}
2436 	RWUNLOCK(&qpdb->lock, isc_rwlocktype_read);
2437 	NODE_UNLOCK(&qpdb->node_locks[locknum].lock, &nlocktype);
2438 
2439 	return result;
2440 }
2441 
2442 static isc_result_t
2443 setgluecachestats(dns_db_t *db, isc_stats_t *stats) {
2444 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
2445 
2446 	REQUIRE(VALID_QPZONE(qpdb));
2447 	REQUIRE(!IS_STUB(qpdb));
2448 	REQUIRE(stats != NULL);
2449 
2450 	isc_stats_attach(stats, &qpdb->gluecachestats);
2451 	return ISC_R_SUCCESS;
2452 }
2453 
2454 static isc_result_t
2455 findnodeintree(qpzonedb_t *qpdb, const dns_name_t *name, bool create,
2456 	       bool nsec3, dns_dbnode_t **nodep DNS__DB_FLARG) {
2457 	isc_result_t result;
2458 	qpznode_t *node = NULL;
2459 	dns_qpmulti_t *dbtree = nsec3 ? qpdb->nsec3 : qpdb->tree;
2460 	dns_qpread_t qpr = { 0 };
2461 	dns_qp_t *qp = NULL;
2462 
2463 	if (create) {
2464 		dns_qpmulti_write(dbtree, &qp);
2465 	} else {
2466 		dns_qpmulti_query(dbtree, &qpr);
2467 		qp = (dns_qp_t *)&qpr;
2468 	}
2469 
2470 	result = dns_qp_getname(qp, name, (void **)&node, NULL);
2471 	if (result != ISC_R_SUCCESS) {
2472 		if (!create) {
2473 			dns_qpread_destroy(dbtree, &qpr);
2474 			return result;
2475 		}
2476 
2477 		node = new_qpznode(qpdb, name);
2478 		result = dns_qp_insert(qp, node, 0);
2479 		qpznode_unref(node);
2480 
2481 		if (result == ISC_R_SUCCESS) {
2482 			if (nsec3) {
2483 				node->nsec = DNS_DB_NSEC_NSEC3;
2484 			} else {
2485 				addwildcards(qpdb, qp, name);
2486 				if (dns_name_iswildcard(name)) {
2487 					wildcardmagic(qpdb, qp, name);
2488 				}
2489 			}
2490 		}
2491 
2492 		INSIST(node->nsec == DNS_DB_NSEC_NSEC3 || !nsec3);
2493 	}
2494 
2495 	newref(qpdb, node DNS__DB_FLARG_PASS);
2496 
2497 	if (create) {
2498 		dns_qp_compact(qp, DNS_QPGC_MAYBE);
2499 		dns_qpmulti_commit(dbtree, &qp);
2500 	} else {
2501 		dns_qpread_destroy(dbtree, &qpr);
2502 	}
2503 
2504 	*nodep = (dns_dbnode_t *)node;
2505 
2506 	return ISC_R_SUCCESS;
2507 }
2508 
2509 static isc_result_t
2510 findnode(dns_db_t *db, const dns_name_t *name, bool create,
2511 	 dns_dbnode_t **nodep DNS__DB_FLARG) {
2512 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
2513 
2514 	REQUIRE(VALID_QPZONE(qpdb));
2515 
2516 	return findnodeintree(qpdb, name, create, false,
2517 			      nodep DNS__DB_FLARG_PASS);
2518 }
2519 
2520 static isc_result_t
2521 findnsec3node(dns_db_t *db, const dns_name_t *name, bool create,
2522 	      dns_dbnode_t **nodep DNS__DB_FLARG) {
2523 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
2524 
2525 	REQUIRE(VALID_QPZONE(qpdb));
2526 
2527 	return findnodeintree(qpdb, name, create, true,
2528 			      nodep DNS__DB_FLARG_PASS);
2529 }
2530 
2531 static bool
2532 matchparams(dns_slabheader_t *header, qpz_search_t *search) {
2533 	dns_rdata_t rdata = DNS_RDATA_INIT;
2534 	dns_rdata_nsec3_t nsec3;
2535 	unsigned char *raw = NULL;
2536 	unsigned int rdlen, count;
2537 	isc_region_t region;
2538 	isc_result_t result;
2539 
2540 	REQUIRE(header->type == dns_rdatatype_nsec3);
2541 
2542 	raw = (unsigned char *)header + sizeof(*header);
2543 	count = raw[0] * 256 + raw[1]; /* count */
2544 	raw += DNS_RDATASET_COUNT + DNS_RDATASET_LENGTH;
2545 
2546 	while (count-- > 0) {
2547 		rdlen = raw[0] * 256 + raw[1];
2548 		raw += DNS_RDATASET_ORDER + DNS_RDATASET_LENGTH;
2549 		region.base = raw;
2550 		region.length = rdlen;
2551 		dns_rdata_fromregion(&rdata, search->qpdb->common.rdclass,
2552 				     dns_rdatatype_nsec3, &region);
2553 		raw += rdlen;
2554 		result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
2555 		INSIST(result == ISC_R_SUCCESS);
2556 		if (nsec3.hash == search->version->hash &&
2557 		    nsec3.iterations == search->version->iterations &&
2558 		    nsec3.salt_length == search->version->salt_length &&
2559 		    memcmp(nsec3.salt, search->version->salt,
2560 			   nsec3.salt_length) == 0)
2561 		{
2562 			return true;
2563 		}
2564 		dns_rdata_reset(&rdata);
2565 	}
2566 	return false;
2567 }
2568 
2569 static isc_result_t
2570 setup_delegation(qpz_search_t *search, dns_dbnode_t **nodep,
2571 		 dns_name_t *foundname, dns_rdataset_t *rdataset,
2572 		 dns_rdataset_t *sigrdataset DNS__DB_FLARG) {
2573 	dns_name_t *zcname = NULL;
2574 	dns_typepair_t type;
2575 	qpznode_t *node = NULL;
2576 
2577 	REQUIRE(search != NULL);
2578 	REQUIRE(search->zonecut != NULL);
2579 	REQUIRE(search->zonecut_header != NULL);
2580 
2581 	/*
2582 	 * The caller MUST NOT be holding any node locks.
2583 	 */
2584 
2585 	node = search->zonecut;
2586 	type = search->zonecut_header->type;
2587 
2588 	/*
2589 	 * If we have to set foundname, we do it before anything else.
2590 	 * If we were to set foundname after we had set nodep or bound the
2591 	 * rdataset, then we'd have to undo that work if dns_name_copy()
2592 	 * failed.  By setting foundname first, there's nothing to undo if
2593 	 * we have trouble.
2594 	 */
2595 	if (foundname != NULL && search->copy_name) {
2596 		zcname = dns_fixedname_name(&search->zonecut_name);
2597 		dns_name_copy(zcname, foundname);
2598 	}
2599 	if (nodep != NULL) {
2600 		/*
2601 		 * Note that we don't have to increment the node's reference
2602 		 * count here because we're going to use the reference we
2603 		 * already have in the search block.
2604 		 */
2605 		*nodep = node;
2606 		search->need_cleanup = false;
2607 	}
2608 	if (rdataset != NULL) {
2609 		isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
2610 		NODE_RDLOCK(&(search->qpdb->node_locks[node->locknum].lock),
2611 			    &nlocktype);
2612 		bindrdataset(search->qpdb, node, search->zonecut_header,
2613 			     search->now, rdataset DNS__DB_FLARG_PASS);
2614 		if (sigrdataset != NULL && search->zonecut_sigheader != NULL) {
2615 			bindrdataset(search->qpdb, node,
2616 				     search->zonecut_sigheader, search->now,
2617 				     sigrdataset DNS__DB_FLARG_PASS);
2618 		}
2619 		NODE_UNLOCK(&(search->qpdb->node_locks[node->locknum].lock),
2620 			    &nlocktype);
2621 	}
2622 
2623 	if (type == dns_rdatatype_dname) {
2624 		return DNS_R_DNAME;
2625 	}
2626 	return DNS_R_DELEGATION;
2627 }
2628 
2629 typedef enum { FORWARD, BACK } direction_t;
2630 
2631 /*
2632  * Step backwards or forwards through the database until we find a
2633  * node with data in it for the desired version. If 'nextname' is not NULL,
2634  * and we found a predecessor or successor, save the name we found in it.
2635  * Return true if we found a predecessor or successor.
2636  */
2637 static bool
2638 step(qpz_search_t *search, dns_qpiter_t *it, direction_t direction,
2639      dns_name_t *nextname) {
2640 	dns_fixedname_t fnodename;
2641 	dns_name_t *nodename = dns_fixedname_initname(&fnodename);
2642 	qpzonedb_t *qpdb = NULL;
2643 	qpznode_t *node = NULL;
2644 	isc_result_t result = ISC_R_SUCCESS;
2645 	dns_slabheader_t *header = NULL;
2646 
2647 	qpdb = search->qpdb;
2648 
2649 	result = dns_qpiter_current(it, nodename, (void **)&node, NULL);
2650 	while (result == ISC_R_SUCCESS) {
2651 		isc_rwlock_t *nodelock = &qpdb->node_locks[node->locknum].lock;
2652 		isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
2653 
2654 		NODE_RDLOCK(nodelock, &nlocktype);
2655 		for (header = node->data; header != NULL; header = header->next)
2656 		{
2657 			if (header->serial <= search->serial &&
2658 			    !IGNORE(header) && !NONEXISTENT(header))
2659 			{
2660 				break;
2661 			}
2662 		}
2663 		NODE_UNLOCK(nodelock, &nlocktype);
2664 		if (header != NULL) {
2665 			break;
2666 		}
2667 
2668 		if (direction == FORWARD) {
2669 			result = dns_qpiter_next(it, nodename, (void **)&node,
2670 						 NULL);
2671 		} else {
2672 			result = dns_qpiter_prev(it, nodename, (void **)&node,
2673 						 NULL);
2674 		}
2675 	};
2676 	if (result == ISC_R_SUCCESS) {
2677 		if (nextname != NULL) {
2678 			dns_name_copy(nodename, nextname);
2679 		}
2680 		return true;
2681 	}
2682 
2683 	return false;
2684 }
2685 
2686 static bool
2687 activeempty(qpz_search_t *search, dns_qpiter_t *it, const dns_name_t *current) {
2688 	dns_fixedname_t fnext;
2689 	dns_name_t *next = dns_fixedname_initname(&fnext);
2690 
2691 	/*
2692 	 * The iterator is currently pointed at the predecessor
2693 	 * of the name we were searching for. Step the iterator
2694 	 * forward, then step() will continue forward until it
2695 	 * finds a node with active data. If that node is a
2696 	 * subdomain of the one we were looking for, then we're
2697 	 * at an active empty nonterminal node.
2698 	 */
2699 	isc_result_t result = dns_qpiter_next(it, NULL, NULL, NULL);
2700 	if (result != ISC_R_SUCCESS) {
2701 		/* An ENT at the end of the zone is impossible */
2702 		return false;
2703 	}
2704 	return step(search, it, FORWARD, next) &&
2705 	       dns_name_issubdomain(next, current);
2706 }
2707 
2708 static bool
2709 wildcard_blocked(qpz_search_t *search, const dns_name_t *qname,
2710 		 dns_name_t *wname) {
2711 	isc_result_t result;
2712 	dns_fixedname_t fnext;
2713 	dns_fixedname_t fprev;
2714 	dns_name_t *next = NULL, *prev = NULL;
2715 	dns_name_t name;
2716 	dns_name_t rname;
2717 	dns_name_t tname;
2718 	dns_qpiter_t it;
2719 	bool check_next = false;
2720 	bool check_prev = false;
2721 	unsigned int n;
2722 
2723 	dns_name_init(&name, NULL);
2724 	dns_name_init(&tname, NULL);
2725 	dns_name_init(&rname, NULL);
2726 	next = dns_fixedname_initname(&fnext);
2727 	prev = dns_fixedname_initname(&fprev);
2728 
2729 	/*
2730 	 * The qname seems to have matched a wildcard, but we
2731 	 * need to find out if there's an empty nonterminal node
2732 	 * between the wildcard level and the qname.
2733 	 *
2734 	 * search->iter should now be pointing at the predecessor
2735 	 * of the searched-for name. We are using a local copy of the
2736 	 * iterator so as not to change the state of search->iter.
2737 	 * step() will walk backward until we find a predecessor with
2738 	 * data.
2739 	 */
2740 	it = search->iter;
2741 	check_prev = step(search, &it, BACK, prev);
2742 
2743 	/* Now reset the iterator and look for a successor with data. */
2744 	it = search->iter;
2745 	result = dns_qpiter_next(&it, NULL, NULL, NULL);
2746 	if (result == ISC_R_SUCCESS) {
2747 		check_next = step(search, &it, FORWARD, next);
2748 	}
2749 
2750 	if (!check_prev && !check_next) {
2751 		/* No predecessor or successor was found at all? */
2752 		return false;
2753 	}
2754 
2755 	dns_name_clone(qname, &rname);
2756 
2757 	/*
2758 	 * Remove the wildcard label to find the terminal name.
2759 	 */
2760 	n = dns_name_countlabels(wname);
2761 	dns_name_getlabelsequence(wname, 1, n - 1, &tname);
2762 
2763 	do {
2764 		if ((check_prev && dns_name_issubdomain(prev, &rname)) ||
2765 		    (check_next && dns_name_issubdomain(next, &rname)))
2766 		{
2767 			return true;
2768 		}
2769 
2770 		/*
2771 		 * Remove the leftmost label from the qname and check again.
2772 		 */
2773 		n = dns_name_countlabels(&rname);
2774 		dns_name_getlabelsequence(&rname, 1, n - 1, &rname);
2775 	} while (!dns_name_equal(&rname, &tname));
2776 
2777 	return false;
2778 }
2779 
2780 static isc_result_t
2781 find_wildcard(qpz_search_t *search, qpznode_t **nodep,
2782 	      const dns_name_t *qname) {
2783 	dns_slabheader_t *header = NULL;
2784 	isc_result_t result = ISC_R_NOTFOUND;
2785 	qpzonedb_t *qpdb = search->qpdb;
2786 
2787 	/*
2788 	 * Examine each ancestor level.  If the level's wild bit
2789 	 * is set, then construct the corresponding wildcard name and
2790 	 * search for it.  If the wildcard node exists, and is active in
2791 	 * this version, we're done.  If not, then we next check to see
2792 	 * if the ancestor is active in this version.  If so, then there
2793 	 * can be no possible wildcard match and again we're done.  If not,
2794 	 * continue the search.
2795 	 */
2796 	for (int i = dns_qpchain_length(&search->chain) - 1; i >= 0; i--) {
2797 		qpznode_t *node = NULL;
2798 		isc_rwlock_t *lock = NULL;
2799 		isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
2800 		bool wild, active;
2801 
2802 		dns_qpchain_node(&search->chain, i, NULL, (void **)&node, NULL);
2803 
2804 		lock = &qpdb->node_locks[node->locknum].lock;
2805 		NODE_RDLOCK(lock, &nlocktype);
2806 		/*
2807 		 * First we try to figure out if this node is active in
2808 		 * the search's version.  We do this now, even though we
2809 		 * may not need the information, because it simplifies the
2810 		 * locking and code flow.
2811 		 */
2812 		for (header = node->data; header != NULL; header = header->next)
2813 		{
2814 			if (header->serial <= search->serial &&
2815 			    !IGNORE(header) && !NONEXISTENT(header))
2816 			{
2817 				break;
2818 			}
2819 		}
2820 
2821 		active = (header != NULL);
2822 		wild = node->wild;
2823 		NODE_UNLOCK(lock, &nlocktype);
2824 
2825 		if (wild) {
2826 			qpznode_t *wnode = NULL;
2827 			dns_fixedname_t fwname;
2828 			dns_name_t *wname = dns_fixedname_initname(&fwname);
2829 			dns_qpiter_t wit;
2830 
2831 			/*
2832 			 * Construct the wildcard name for this level.
2833 			 */
2834 			result = dns_name_concatenate(dns_wildcardname,
2835 						      &node->name, wname, NULL);
2836 			if (result != ISC_R_SUCCESS) {
2837 				break;
2838 			}
2839 
2840 			result = dns_qp_lookup(&search->qpr, wname, NULL, &wit,
2841 					       NULL, (void **)&wnode, NULL);
2842 			if (result == ISC_R_SUCCESS) {
2843 				/*
2844 				 * We have found the wildcard node.  If it
2845 				 * is active in the search's version, we're
2846 				 * done.
2847 				 */
2848 				lock = &qpdb->node_locks[wnode->locknum].lock;
2849 				NODE_RDLOCK(lock, &nlocktype);
2850 				for (header = wnode->data; header != NULL;
2851 				     header = header->next)
2852 				{
2853 					if (header->serial <= search->serial &&
2854 					    !IGNORE(header) &&
2855 					    !NONEXISTENT(header))
2856 					{
2857 						break;
2858 					}
2859 				}
2860 				NODE_UNLOCK(lock, &nlocktype);
2861 				if (header != NULL ||
2862 				    activeempty(search, &wit, wname))
2863 				{
2864 					if (wildcard_blocked(search, qname,
2865 							     wname))
2866 					{
2867 						return ISC_R_NOTFOUND;
2868 					}
2869 
2870 					/*
2871 					 * The wildcard node is active!
2872 					 *
2873 					 * Note: result is still ISC_R_SUCCESS
2874 					 * so we don't have to set it.
2875 					 */
2876 					*nodep = wnode;
2877 					break;
2878 				}
2879 			} else if (result != ISC_R_NOTFOUND &&
2880 				   result != DNS_R_PARTIALMATCH)
2881 			{
2882 				/*
2883 				 * An error has occurred.  Bail out.
2884 				 */
2885 				break;
2886 			}
2887 		}
2888 
2889 		if (active) {
2890 			/*
2891 			 * The level node is active.  Any wildcarding
2892 			 * present at higher levels has no
2893 			 * effect and we're done.
2894 			 */
2895 			result = ISC_R_NOTFOUND;
2896 			break;
2897 		}
2898 	}
2899 
2900 	return result;
2901 }
2902 
2903 /*
2904  * Find node of the NSEC/NSEC3 record that is 'name'.
2905  */
2906 static isc_result_t
2907 previous_closest_nsec(dns_rdatatype_t type, qpz_search_t *search,
2908 		      dns_name_t *name, qpznode_t **nodep, dns_qpiter_t *nit,
2909 		      bool *firstp) {
2910 	isc_result_t result;
2911 	dns_qpread_t qpr;
2912 
2913 	REQUIRE(nodep != NULL && *nodep == NULL);
2914 	REQUIRE(type == dns_rdatatype_nsec3 || firstp != NULL);
2915 
2916 	if (type == dns_rdatatype_nsec3) {
2917 		result = dns_qpiter_prev(&search->iter, name, (void **)nodep,
2918 					 NULL);
2919 		return result;
2920 	}
2921 
2922 	dns_qpmulti_query(search->qpdb->nsec, &qpr);
2923 
2924 	for (;;) {
2925 		if (*firstp) {
2926 			/*
2927 			 * Construct the name of the second node to check.
2928 			 * It is the first node sought in the NSEC tree.
2929 			 */
2930 			*firstp = false;
2931 			result = dns_qp_lookup(&qpr, name, NULL, nit, NULL,
2932 					       NULL, NULL);
2933 			INSIST(result != ISC_R_NOTFOUND);
2934 			if (result == ISC_R_SUCCESS) {
2935 				/*
2936 				 * Since this was the first loop, finding the
2937 				 * name in the NSEC tree implies that the first
2938 				 * node checked in the main tree had an
2939 				 * unacceptable NSEC record.
2940 				 * Try the previous node in the NSEC tree.
2941 				 */
2942 				result = dns_qpiter_prev(nit, name, NULL, NULL);
2943 			} else if (result == DNS_R_PARTIALMATCH) {
2944 				/*
2945 				 * The iterator is already where we want it.
2946 				 */
2947 				dns_qpiter_current(nit, name, NULL, NULL);
2948 				result = ISC_R_SUCCESS;
2949 			}
2950 		} else {
2951 			/*
2952 			 * This is a second or later trip through the auxiliary
2953 			 * tree for the name of a third or earlier NSEC node in
2954 			 * the main tree.  Previous trips through the NSEC tree
2955 			 * must have found nodes in the main tree with NSEC
2956 			 * records.  Perhaps they lacked signature records.
2957 			 */
2958 			result = dns_qpiter_prev(nit, name, NULL, NULL);
2959 		}
2960 		if (result != ISC_R_SUCCESS) {
2961 			break;
2962 		}
2963 
2964 		*nodep = NULL;
2965 		result = dns_qp_lookup(&search->qpr, name, NULL, &search->iter,
2966 				       &search->chain, (void **)nodep, NULL);
2967 		if (result == ISC_R_SUCCESS) {
2968 			break;
2969 		}
2970 
2971 		/*
2972 		 * There should always be a node in the main tree with the
2973 		 * same name as the node in the auxiliary NSEC tree, except for
2974 		 * nodes in the auxiliary tree that are awaiting deletion.
2975 		 */
2976 		if (result != DNS_R_PARTIALMATCH && result != ISC_R_NOTFOUND) {
2977 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
2978 				      DNS_LOGMODULE_DB, ISC_LOG_ERROR,
2979 				      "previous_closest_nsec(): %s",
2980 				      isc_result_totext(result));
2981 			result = DNS_R_BADDB;
2982 			break;
2983 		}
2984 	}
2985 
2986 	dns_qpread_destroy(search->qpdb->nsec, &qpr);
2987 	return result;
2988 }
2989 
2990 /*
2991  * Find the NSEC/NSEC3 which is or before the current point on the
2992  * search chain.  For NSEC3 records only NSEC3 records that match the
2993  * current NSEC3PARAM record are considered.
2994  */
2995 static isc_result_t
2996 find_closest_nsec(qpz_search_t *search, dns_dbnode_t **nodep,
2997 		  dns_name_t *foundname, dns_rdataset_t *rdataset,
2998 		  dns_rdataset_t *sigrdataset, bool nsec3,
2999 		  bool secure DNS__DB_FLARG) {
3000 	qpznode_t *node = NULL, *prevnode = NULL;
3001 	dns_slabheader_t *header = NULL, *header_next = NULL;
3002 	dns_qpiter_t nseciter;
3003 	bool empty_node;
3004 	isc_result_t result;
3005 	dns_fixedname_t fname;
3006 	dns_name_t *name = dns_fixedname_initname(&fname);
3007 	dns_rdatatype_t type = dns_rdatatype_nsec;
3008 	dns_typepair_t sigtype = DNS_SIGTYPE(dns_rdatatype_nsec);
3009 	bool wraps = false;
3010 	bool first = true;
3011 	bool need_sig = secure;
3012 
3013 	if (nsec3) {
3014 		type = dns_rdatatype_nsec3;
3015 		sigtype = DNS_SIGTYPE(dns_rdatatype_nsec3);
3016 		wraps = true;
3017 	}
3018 
3019 	/*
3020 	 * Use the auxiliary tree only starting with the second node in the
3021 	 * hope that the original node will be right much of the time.
3022 	 */
3023 	result = dns_qpiter_current(&search->iter, name, (void **)&node, NULL);
3024 	if (result != ISC_R_SUCCESS) {
3025 		return result;
3026 	}
3027 again:
3028 	do {
3029 		dns_slabheader_t *found = NULL, *foundsig = NULL;
3030 		isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
3031 		NODE_RDLOCK(&(search->qpdb->node_locks[node->locknum].lock),
3032 			    &nlocktype);
3033 		empty_node = true;
3034 		for (header = node->data; header != NULL; header = header_next)
3035 		{
3036 			header_next = header->next;
3037 			/*
3038 			 * Look for an active, extant NSEC or RRSIG NSEC.
3039 			 */
3040 			do {
3041 				if (header->serial <= search->serial &&
3042 				    !IGNORE(header))
3043 				{
3044 					if (NONEXISTENT(header)) {
3045 						header = NULL;
3046 					}
3047 					break;
3048 				} else {
3049 					header = header->down;
3050 				}
3051 			} while (header != NULL);
3052 			if (header != NULL) {
3053 				/*
3054 				 * We now know that there is at least one
3055 				 * active rdataset at this node.
3056 				 */
3057 				empty_node = false;
3058 				if (header->type == type) {
3059 					found = header;
3060 					if (foundsig != NULL) {
3061 						break;
3062 					}
3063 				} else if (header->type == sigtype) {
3064 					foundsig = header;
3065 					if (found != NULL) {
3066 						break;
3067 					}
3068 				}
3069 			}
3070 		}
3071 		if (!empty_node) {
3072 			if (found != NULL && search->version->havensec3 &&
3073 			    found->type == dns_rdatatype_nsec3 &&
3074 			    !matchparams(found, search))
3075 			{
3076 				empty_node = true;
3077 				found = NULL;
3078 				foundsig = NULL;
3079 				result = previous_closest_nsec(type, search,
3080 							       name, &prevnode,
3081 							       NULL, NULL);
3082 			} else if (found != NULL &&
3083 				   (foundsig != NULL || !need_sig))
3084 			{
3085 				/*
3086 				 * We've found the right NSEC/NSEC3 record.
3087 				 *
3088 				 * Note: for this to really be the right
3089 				 * NSEC record, it's essential that the NSEC
3090 				 * records of any nodes obscured by a zone
3091 				 * cut have been removed; we assume this is
3092 				 * the case.
3093 				 */
3094 				dns_name_copy(name, foundname);
3095 				if (nodep != NULL) {
3096 					newref(search->qpdb,
3097 					       node DNS__DB_FLARG_PASS);
3098 					*nodep = node;
3099 				}
3100 				bindrdataset(search->qpdb, node, found,
3101 					     search->now,
3102 					     rdataset DNS__DB_FLARG_PASS);
3103 				if (foundsig != NULL) {
3104 					bindrdataset(
3105 						search->qpdb, node, foundsig,
3106 						search->now,
3107 						sigrdataset DNS__DB_FLARG_PASS);
3108 				}
3109 			} else if (found == NULL && foundsig == NULL) {
3110 				/*
3111 				 * This node is active, but has no NSEC or
3112 				 * RRSIG NSEC.  That means it's glue or
3113 				 * other obscured zone data that isn't
3114 				 * relevant for our search.  Treat the
3115 				 * node as if it were empty and keep looking.
3116 				 */
3117 				empty_node = true;
3118 				result = previous_closest_nsec(
3119 					type, search, name, &prevnode,
3120 					&nseciter, &first);
3121 			} else {
3122 				/*
3123 				 * We found an active node, but either the
3124 				 * NSEC or the RRSIG NSEC is missing.  This
3125 				 * shouldn't happen.
3126 				 */
3127 				result = DNS_R_BADDB;
3128 			}
3129 		} else {
3130 			/*
3131 			 * This node isn't active.  We've got to keep
3132 			 * looking.
3133 			 */
3134 			result = previous_closest_nsec(type, search, name,
3135 						       &prevnode, &nseciter,
3136 						       &first);
3137 		}
3138 		NODE_UNLOCK(&(search->qpdb->node_locks[node->locknum].lock),
3139 			    &nlocktype);
3140 		node = prevnode;
3141 		prevnode = NULL;
3142 	} while (empty_node && result == ISC_R_SUCCESS);
3143 
3144 	if (result == ISC_R_NOMORE && wraps) {
3145 		result = dns_qpiter_prev(&search->iter, name, (void **)&node,
3146 					 NULL);
3147 		if (result == ISC_R_SUCCESS) {
3148 			wraps = false;
3149 			goto again;
3150 		}
3151 	}
3152 
3153 	/*
3154 	 * If the result is ISC_R_NOMORE, then we got to the beginning of
3155 	 * the database and didn't find a NSEC record.  This shouldn't
3156 	 * happen.
3157 	 */
3158 	if (result == ISC_R_NOMORE) {
3159 		result = DNS_R_BADDB;
3160 	}
3161 
3162 	return result;
3163 }
3164 
3165 static isc_result_t
3166 check_zonecut(qpznode_t *node, void *arg DNS__DB_FLARG) {
3167 	qpz_search_t *search = arg;
3168 	dns_slabheader_t *header = NULL, *header_next = NULL;
3169 	dns_slabheader_t *dname_header = NULL, *sigdname_header = NULL;
3170 	dns_slabheader_t *ns_header = NULL;
3171 	dns_slabheader_t *found = NULL;
3172 	isc_result_t result = DNS_R_CONTINUE;
3173 	isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
3174 
3175 	NODE_RDLOCK(&(search->qpdb->node_locks[node->locknum].lock),
3176 		    &nlocktype);
3177 
3178 	/*
3179 	 * Look for an NS or DNAME rdataset active in our version.
3180 	 */
3181 	for (header = node->data; header != NULL; header = header_next) {
3182 		header_next = header->next;
3183 		if (header->type == dns_rdatatype_ns ||
3184 		    header->type == dns_rdatatype_dname ||
3185 		    header->type == DNS_SIGTYPE(dns_rdatatype_dname))
3186 		{
3187 			do {
3188 				if (header->serial <= search->serial &&
3189 				    !IGNORE(header))
3190 				{
3191 					if (NONEXISTENT(header)) {
3192 						header = NULL;
3193 					}
3194 					break;
3195 				} else {
3196 					header = header->down;
3197 				}
3198 			} while (header != NULL);
3199 			if (header != NULL) {
3200 				if (header->type == dns_rdatatype_dname) {
3201 					dname_header = header;
3202 				} else if (header->type ==
3203 					   DNS_SIGTYPE(dns_rdatatype_dname))
3204 				{
3205 					sigdname_header = header;
3206 				} else if (node != search->qpdb->origin ||
3207 					   IS_STUB(search->qpdb))
3208 				{
3209 					/*
3210 					 * We've found an NS rdataset that
3211 					 * isn't at the origin node.
3212 					 */
3213 					ns_header = header;
3214 				}
3215 			}
3216 		}
3217 	}
3218 
3219 	/*
3220 	 * Did we find anything?
3221 	 */
3222 	if (!IS_STUB(search->qpdb) && ns_header != NULL) {
3223 		/*
3224 		 * Note that NS has precedence over DNAME if both exist
3225 		 * in a zone.  Otherwise DNAME take precedence over NS.
3226 		 */
3227 		found = ns_header;
3228 		search->zonecut_sigheader = NULL;
3229 	} else if (dname_header != NULL) {
3230 		found = dname_header;
3231 		search->zonecut_sigheader = sigdname_header;
3232 	} else if (ns_header != NULL) {
3233 		found = ns_header;
3234 		search->zonecut_sigheader = NULL;
3235 	}
3236 
3237 	if (found != NULL) {
3238 		/*
3239 		 * We increment the reference count on node to ensure that
3240 		 * search->zonecut_header will still be valid later.
3241 		 */
3242 		newref(search->qpdb, node DNS__DB_FLARG_PASS);
3243 		search->zonecut = node;
3244 		search->zonecut_header = found;
3245 		search->need_cleanup = true;
3246 		/*
3247 		 * Since we've found a zonecut, anything beneath it is
3248 		 * glue and is not subject to wildcard matching, so we
3249 		 * may clear search->wild.
3250 		 */
3251 		search->wild = false;
3252 		if ((search->options & DNS_DBFIND_GLUEOK) == 0) {
3253 			/*
3254 			 * If the caller does not want to find glue, then
3255 			 * this is the best answer and the search should
3256 			 * stop now.
3257 			 */
3258 			result = DNS_R_PARTIALMATCH;
3259 		} else {
3260 			dns_name_t *zcname = NULL;
3261 
3262 			/*
3263 			 * The search will continue beneath the zone cut.
3264 			 * This may or may not be the best match.  In case it
3265 			 * is, we need to remember the node name.
3266 			 */
3267 			zcname = dns_fixedname_name(&search->zonecut_name);
3268 			dns_name_copy(&node->name, zcname);
3269 			search->copy_name = true;
3270 		}
3271 	} else {
3272 		/*
3273 		 * There is no zonecut at this node which is active in this
3274 		 * version.
3275 		 *
3276 		 * If this is a "wild" node and the caller hasn't disabled
3277 		 * wildcard matching, remember that we've seen a wild node
3278 		 * in case we need to go searching for wildcard matches
3279 		 * later on.
3280 		 */
3281 		if (node->wild && (search->options & DNS_DBFIND_NOWILD) == 0) {
3282 			search->wild = true;
3283 		}
3284 	}
3285 
3286 	NODE_UNLOCK(&(search->qpdb->node_locks[node->locknum].lock),
3287 		    &nlocktype);
3288 
3289 	return result;
3290 }
3291 
3292 static isc_result_t
3293 find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
3294      dns_rdatatype_t type, unsigned int options,
3295      isc_stdtime_t now ISC_ATTR_UNUSED, dns_dbnode_t **nodep,
3296      dns_name_t *foundname, dns_rdataset_t *rdataset,
3297      dns_rdataset_t *sigrdataset DNS__DB_FLARG) {
3298 	isc_result_t result;
3299 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
3300 	qpznode_t *node = NULL;
3301 	qpz_search_t search;
3302 	bool cname_ok = true, close_version = false;
3303 	bool maybe_zonecut = false, at_zonecut = false;
3304 	bool wild = false, empty_node = false;
3305 	bool nsec3 = false;
3306 	dns_slabheader_t *header = NULL, *header_next = NULL;
3307 	dns_slabheader_t *found = NULL, *nsecheader = NULL;
3308 	dns_slabheader_t *foundsig = NULL, *cnamesig = NULL, *nsecsig = NULL;
3309 	dns_typepair_t sigtype;
3310 	bool active;
3311 	isc_rwlock_t *lock = NULL;
3312 	isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
3313 
3314 	REQUIRE(VALID_QPZONE((qpzonedb_t *)db));
3315 	INSIST(version == NULL ||
3316 	       ((qpz_version_t *)version)->qpdb == (qpzonedb_t *)db);
3317 
3318 	/*
3319 	 * If the caller didn't supply a version, attach to the current
3320 	 * version.
3321 	 */
3322 	if (version == NULL) {
3323 		currentversion(db, &version);
3324 		close_version = true;
3325 	}
3326 
3327 	search = (qpz_search_t){
3328 		.qpdb = (qpzonedb_t *)db,
3329 		.version = version,
3330 		.serial = ((qpz_version_t *)version)->serial,
3331 		.options = options,
3332 	};
3333 	dns_fixedname_init(&search.zonecut_name);
3334 
3335 	if ((options & DNS_DBFIND_FORCENSEC3) != 0) {
3336 		dns_qpmulti_query(qpdb->nsec3, &search.qpr);
3337 		nsec3 = true;
3338 	} else {
3339 		dns_qpmulti_query(qpdb->tree, &search.qpr);
3340 	}
3341 
3342 	/*
3343 	 * Search down from the root of the tree.
3344 	 */
3345 	result = dns_qp_lookup(&search.qpr, name, NULL, &search.iter,
3346 			       &search.chain, (void **)&node, NULL);
3347 	if (result != ISC_R_NOTFOUND) {
3348 		dns_name_copy(&node->name, foundname);
3349 	}
3350 
3351 	/*
3352 	 * Check the QP chain to see if there's a node above us with a
3353 	 * active DNAME or NS rdatasets.
3354 	 *
3355 	 * We're only interested in nodes above QNAME, so if the result
3356 	 * was success, then we skip the last item in the chain.
3357 	 */
3358 	unsigned int clen = dns_qpchain_length(&search.chain);
3359 	if (result == ISC_R_SUCCESS) {
3360 		clen--;
3361 	}
3362 	for (unsigned int i = 0; i < clen && search.zonecut == NULL; i++) {
3363 		qpznode_t *n = NULL;
3364 		isc_result_t tresult;
3365 
3366 		dns_qpchain_node(&search.chain, i, NULL, (void **)&n, NULL);
3367 		tresult = check_zonecut(n, &search DNS__DB_FLARG_PASS);
3368 		if (tresult != DNS_R_CONTINUE) {
3369 			result = tresult;
3370 			search.chain.len = i - 1;
3371 			node = n;
3372 			if (foundname != NULL) {
3373 				dns_name_copy(&node->name, foundname);
3374 			}
3375 		}
3376 	}
3377 
3378 	if (result == DNS_R_PARTIALMATCH) {
3379 	partial_match:
3380 		if (search.zonecut != NULL) {
3381 			result = setup_delegation(
3382 				&search, nodep, foundname, rdataset,
3383 				sigrdataset DNS__DB_FLARG_PASS);
3384 			goto tree_exit;
3385 		}
3386 
3387 		if (search.wild) {
3388 			/*
3389 			 * At least one of the levels in the search chain
3390 			 * potentially has a wildcard.  For each such level,
3391 			 * we must see if there's a matching wildcard active
3392 			 * in the current version.
3393 			 */
3394 			result = find_wildcard(&search, &node, name);
3395 			if (result == ISC_R_SUCCESS) {
3396 				dns_name_copy(name, foundname);
3397 				wild = true;
3398 				goto found;
3399 			} else if (result != ISC_R_NOTFOUND) {
3400 				goto tree_exit;
3401 			}
3402 		}
3403 
3404 		active = false;
3405 		if (!nsec3) {
3406 			/*
3407 			 * The NSEC3 tree won't have empty nodes,
3408 			 * so it isn't necessary to check for them.
3409 			 */
3410 			dns_qpiter_t iter = search.iter;
3411 			active = activeempty(&search, &iter, name);
3412 		}
3413 
3414 		/*
3415 		 * If we're here, then the name does not exist, is not
3416 		 * beneath a zonecut, and there's no matching wildcard.
3417 		 */
3418 		if ((search.version->secure && !search.version->havensec3) ||
3419 		    nsec3)
3420 		{
3421 			result = find_closest_nsec(
3422 				&search, nodep, foundname, rdataset,
3423 				sigrdataset, nsec3,
3424 				search.version->secure DNS__DB_FLARG_PASS);
3425 			if (result == ISC_R_SUCCESS) {
3426 				result = active ? DNS_R_EMPTYNAME
3427 						: DNS_R_NXDOMAIN;
3428 			}
3429 		} else {
3430 			result = active ? DNS_R_EMPTYNAME : DNS_R_NXDOMAIN;
3431 		}
3432 		goto tree_exit;
3433 	} else if (result != ISC_R_SUCCESS) {
3434 		goto tree_exit;
3435 	}
3436 
3437 found:
3438 	/*
3439 	 * We have found a node whose name is the desired name, or we
3440 	 * have matched a wildcard.
3441 	 */
3442 
3443 	lock = &search.qpdb->node_locks[node->locknum].lock;
3444 	NODE_RDLOCK(lock, &nlocktype);
3445 
3446 	if (search.zonecut != NULL) {
3447 		/*
3448 		 * If we're beneath a zone cut, we don't want to look for
3449 		 * CNAMEs because they're not legitimate zone glue.
3450 		 */
3451 		cname_ok = false;
3452 	} else {
3453 		/*
3454 		 * The node may be a zone cut itself.  If it might be one,
3455 		 * make sure we check for it later.
3456 		 *
3457 		 * DS records live above the zone cut in ordinary zone so
3458 		 * we want to ignore any referral.
3459 		 *
3460 		 * Stub zones don't have anything "above" the delegation so
3461 		 * we always return a referral.
3462 		 */
3463 		if (node->delegating && ((node != search.qpdb->origin &&
3464 					  !dns_rdatatype_atparent(type)) ||
3465 					 IS_STUB(search.qpdb)))
3466 		{
3467 			maybe_zonecut = true;
3468 		}
3469 	}
3470 
3471 	/*
3472 	 * Certain DNSSEC types are not subject to CNAME matching
3473 	 * (RFC4035, section 2.5 and RFC3007).
3474 	 *
3475 	 * We don't check for RRSIG, because we don't store RRSIG records
3476 	 * directly.
3477 	 */
3478 	if (type == dns_rdatatype_key || type == dns_rdatatype_nsec) {
3479 		cname_ok = false;
3480 	}
3481 
3482 	/*
3483 	 * We now go looking for rdata...
3484 	 */
3485 
3486 	sigtype = DNS_SIGTYPE(type);
3487 	empty_node = true;
3488 	for (header = node->data; header != NULL; header = header_next) {
3489 		header_next = header->next;
3490 		/*
3491 		 * Look for an active, extant rdataset.
3492 		 */
3493 		do {
3494 			if (header->serial <= search.serial && !IGNORE(header))
3495 			{
3496 				if (NONEXISTENT(header)) {
3497 					header = NULL;
3498 				}
3499 				break;
3500 			} else {
3501 				header = header->down;
3502 			}
3503 		} while (header != NULL);
3504 		if (header != NULL) {
3505 			/*
3506 			 * We now know that there is at least one active
3507 			 * rdataset at this node.
3508 			 */
3509 			empty_node = false;
3510 
3511 			/*
3512 			 * Do special zone cut handling, if requested.
3513 			 */
3514 			if (maybe_zonecut && header->type == dns_rdatatype_ns) {
3515 				/*
3516 				 * We increment the reference count on node to
3517 				 * ensure that search->zonecut_header will
3518 				 * still be valid later.
3519 				 */
3520 				newref(search.qpdb, node DNS__DB_FLARG_PASS);
3521 				search.zonecut = node;
3522 				search.zonecut_header = header;
3523 				search.zonecut_sigheader = NULL;
3524 				search.need_cleanup = true;
3525 				maybe_zonecut = false;
3526 				at_zonecut = true;
3527 				/*
3528 				 * It is not clear if KEY should still be
3529 				 * allowed at the parent side of the zone
3530 				 * cut or not.  It is needed for RFC3007
3531 				 * validated updates.
3532 				 */
3533 				if ((search.options & DNS_DBFIND_GLUEOK) == 0 &&
3534 				    type != dns_rdatatype_nsec &&
3535 				    type != dns_rdatatype_key)
3536 				{
3537 					/*
3538 					 * Glue is not OK, but any answer we
3539 					 * could return would be glue.  Return
3540 					 * the delegation.
3541 					 */
3542 					found = NULL;
3543 					break;
3544 				}
3545 				if (found != NULL && foundsig != NULL) {
3546 					break;
3547 				}
3548 			}
3549 
3550 			/*
3551 			 * If the NSEC3 record doesn't match the chain
3552 			 * we are using behave as if it isn't here.
3553 			 */
3554 			if (header->type == dns_rdatatype_nsec3 &&
3555 			    !matchparams(header, &search))
3556 			{
3557 				NODE_UNLOCK(lock, &nlocktype);
3558 				goto partial_match;
3559 			}
3560 			/*
3561 			 * If we found a type we were looking for,
3562 			 * remember it.
3563 			 */
3564 			if (header->type == type || type == dns_rdatatype_any ||
3565 			    (header->type == dns_rdatatype_cname && cname_ok))
3566 			{
3567 				/*
3568 				 * We've found the answer!
3569 				 */
3570 				found = header;
3571 				if (header->type == dns_rdatatype_cname &&
3572 				    cname_ok)
3573 				{
3574 					/*
3575 					 * We may be finding a CNAME instead
3576 					 * of the desired type.
3577 					 *
3578 					 * If we've already got the CNAME RRSIG,
3579 					 * use it, otherwise change sigtype
3580 					 * so that we find it.
3581 					 */
3582 					if (cnamesig != NULL) {
3583 						foundsig = cnamesig;
3584 					} else {
3585 						sigtype = DNS_SIGTYPE(
3586 							dns_rdatatype_cname);
3587 					}
3588 				}
3589 				/*
3590 				 * If we've got all we need, end the search.
3591 				 */
3592 				if (!maybe_zonecut && foundsig != NULL) {
3593 					break;
3594 				}
3595 			} else if (header->type == sigtype) {
3596 				/*
3597 				 * We've found the RRSIG rdataset for our
3598 				 * target type.  Remember it.
3599 				 */
3600 				foundsig = header;
3601 				/*
3602 				 * If we've got all we need, end the search.
3603 				 */
3604 				if (!maybe_zonecut && found != NULL) {
3605 					break;
3606 				}
3607 			} else if (header->type == dns_rdatatype_nsec &&
3608 				   !search.version->havensec3)
3609 			{
3610 				/*
3611 				 * Remember a NSEC rdataset even if we're
3612 				 * not specifically looking for it, because
3613 				 * we might need it later.
3614 				 */
3615 				nsecheader = header;
3616 			} else if (header->type ==
3617 					   DNS_SIGTYPE(dns_rdatatype_nsec) &&
3618 				   !search.version->havensec3)
3619 			{
3620 				/*
3621 				 * If we need the NSEC rdataset, we'll also
3622 				 * need its signature.
3623 				 */
3624 				nsecsig = header;
3625 			} else if (cname_ok &&
3626 				   header->type ==
3627 					   DNS_SIGTYPE(dns_rdatatype_cname))
3628 			{
3629 				/*
3630 				 * If we get a CNAME match, we'll also need
3631 				 * its signature.
3632 				 */
3633 				cnamesig = header;
3634 			}
3635 		}
3636 	}
3637 
3638 	if (empty_node) {
3639 		/*
3640 		 * We have an exact match for the name, but there are no
3641 		 * active rdatasets in the desired version.  That means that
3642 		 * this node doesn't exist in the desired version, and that
3643 		 * we really have a partial match.
3644 		 */
3645 		if (!wild) {
3646 			NODE_UNLOCK(lock, &nlocktype);
3647 			goto partial_match;
3648 		}
3649 	}
3650 
3651 	/*
3652 	 * If we didn't find what we were looking for...
3653 	 */
3654 	if (found == NULL) {
3655 		if (search.zonecut != NULL) {
3656 			/*
3657 			 * We were trying to find glue at a node beneath a
3658 			 * zone cut, but didn't.
3659 			 *
3660 			 * Return the delegation.
3661 			 */
3662 			NODE_UNLOCK(lock, &nlocktype);
3663 			result = setup_delegation(
3664 				&search, nodep, foundname, rdataset,
3665 				sigrdataset DNS__DB_FLARG_PASS);
3666 			goto tree_exit;
3667 		}
3668 		/*
3669 		 * The desired type doesn't exist.
3670 		 */
3671 		result = DNS_R_NXRRSET;
3672 		if (search.version->secure && !search.version->havensec3 &&
3673 		    (nsecheader == NULL || nsecsig == NULL))
3674 		{
3675 			/*
3676 			 * The zone is secure but there's no NSEC,
3677 			 * or the NSEC has no signature!
3678 			 */
3679 			if (!wild) {
3680 				result = DNS_R_BADDB;
3681 				goto node_exit;
3682 			}
3683 
3684 			NODE_UNLOCK(lock, &nlocktype);
3685 			result = find_closest_nsec(
3686 				&search, nodep, foundname, rdataset,
3687 				sigrdataset, false,
3688 				search.version->secure DNS__DB_FLARG_PASS);
3689 			if (result == ISC_R_SUCCESS) {
3690 				result = DNS_R_EMPTYWILD;
3691 			}
3692 			goto tree_exit;
3693 		}
3694 		if (nodep != NULL) {
3695 			newref(search.qpdb, node DNS__DB_FLARG_PASS);
3696 			*nodep = node;
3697 		}
3698 		if (search.version->secure && !search.version->havensec3) {
3699 			bindrdataset(search.qpdb, node, nsecheader, 0,
3700 				     rdataset DNS__DB_FLARG_PASS);
3701 			if (nsecsig != NULL) {
3702 				bindrdataset(search.qpdb, node, nsecsig, 0,
3703 					     sigrdataset DNS__DB_FLARG_PASS);
3704 			}
3705 		}
3706 		if (wild) {
3707 			foundname->attributes.wildcard = true;
3708 		}
3709 		goto node_exit;
3710 	}
3711 
3712 	/*
3713 	 * We found what we were looking for, or we found a CNAME.
3714 	 */
3715 	if (type != found->type && type != dns_rdatatype_any &&
3716 	    found->type == dns_rdatatype_cname)
3717 	{
3718 		/*
3719 		 * We weren't doing an ANY query and we found a CNAME instead
3720 		 * of the type we were looking for, so we need to indicate
3721 		 * that result to the caller.
3722 		 */
3723 		result = DNS_R_CNAME;
3724 	} else if (search.zonecut != NULL) {
3725 		/*
3726 		 * If we're beneath a zone cut, we must indicate that the
3727 		 * result is glue, unless we're actually at the zone cut
3728 		 * and the type is NSEC or KEY.
3729 		 */
3730 		if (search.zonecut == node) {
3731 			/*
3732 			 * It is not clear if KEY should still be
3733 			 * allowed at the parent side of the zone
3734 			 * cut or not.  It is needed for RFC3007
3735 			 * validated updates.
3736 			 */
3737 			if (type == dns_rdatatype_nsec ||
3738 			    type == dns_rdatatype_nsec3 ||
3739 			    type == dns_rdatatype_key)
3740 			{
3741 				result = ISC_R_SUCCESS;
3742 			} else if (type == dns_rdatatype_any) {
3743 				result = DNS_R_ZONECUT;
3744 			} else {
3745 				result = DNS_R_GLUE;
3746 			}
3747 		} else {
3748 			result = DNS_R_GLUE;
3749 		}
3750 	} else {
3751 		/*
3752 		 * An ordinary successful query!
3753 		 */
3754 		result = ISC_R_SUCCESS;
3755 	}
3756 
3757 	if (nodep != NULL) {
3758 		if (!at_zonecut) {
3759 			newref(search.qpdb, node DNS__DB_FLARG_PASS);
3760 		} else {
3761 			search.need_cleanup = false;
3762 		}
3763 		*nodep = node;
3764 	}
3765 
3766 	if (type != dns_rdatatype_any) {
3767 		bindrdataset(search.qpdb, node, found, 0,
3768 			     rdataset DNS__DB_FLARG_PASS);
3769 		if (foundsig != NULL) {
3770 			bindrdataset(search.qpdb, node, foundsig, 0,
3771 				     sigrdataset DNS__DB_FLARG_PASS);
3772 		}
3773 	}
3774 
3775 	if (wild) {
3776 		foundname->attributes.wildcard = true;
3777 	}
3778 
3779 node_exit:
3780 	NODE_UNLOCK(lock, &nlocktype);
3781 
3782 tree_exit:
3783 	if (nsec3) {
3784 		dns_qpread_destroy(qpdb->nsec3, &search.qpr);
3785 	} else {
3786 		dns_qpread_destroy(qpdb->tree, &search.qpr);
3787 	}
3788 
3789 	/*
3790 	 * If we found a zonecut but aren't going to use it, we have to
3791 	 * let go of it.
3792 	 */
3793 	if (search.need_cleanup) {
3794 		node = search.zonecut;
3795 		INSIST(node != NULL);
3796 		lock = &(search.qpdb->node_locks[node->locknum].lock);
3797 
3798 		NODE_RDLOCK(lock, &nlocktype);
3799 		decref(search.qpdb, node, 0, &nlocktype DNS__DB_FLARG_PASS);
3800 		NODE_UNLOCK(lock, &nlocktype);
3801 	}
3802 
3803 	if (close_version) {
3804 		closeversion(db, &version, false DNS__DB_FLARG_PASS);
3805 	}
3806 
3807 	return result;
3808 }
3809 
3810 static isc_result_t
3811 allrdatasets(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
3812 	     unsigned int options, isc_stdtime_t now ISC_ATTR_UNUSED,
3813 	     dns_rdatasetiter_t **iteratorp DNS__DB_FLARG) {
3814 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
3815 	qpznode_t *node = (qpznode_t *)dbnode;
3816 	qpz_version_t *version = dbversion;
3817 	qpdb_rdatasetiter_t *iterator = NULL;
3818 
3819 	REQUIRE(VALID_QPZONE(qpdb));
3820 
3821 	if (version == NULL) {
3822 		currentversion(db, (dns_dbversion_t **)(void *)(&version));
3823 	} else {
3824 		INSIST(version->qpdb == qpdb);
3825 		isc_refcount_increment(&version->references);
3826 	}
3827 
3828 	iterator = isc_mem_get(qpdb->common.mctx, sizeof(*iterator));
3829 	*iterator = (qpdb_rdatasetiter_t){
3830 		.common.methods = &rdatasetiter_methods,
3831 		.common.db = db,
3832 		.common.node = node,
3833 		.common.version = (dns_dbversion_t *)version,
3834 		.common.options = options,
3835 		.common.magic = DNS_RDATASETITER_MAGIC,
3836 	};
3837 
3838 	newref(qpdb, node DNS__DB_FLARG_PASS);
3839 
3840 	*iteratorp = (dns_rdatasetiter_t *)iterator;
3841 	return ISC_R_SUCCESS;
3842 }
3843 
3844 static void
3845 attachnode(dns_db_t *db, dns_dbnode_t *source,
3846 	   dns_dbnode_t **targetp DNS__DB_FLARG) {
3847 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
3848 	qpznode_t *node = (qpznode_t *)source;
3849 
3850 	REQUIRE(VALID_QPZONE(qpdb));
3851 	REQUIRE(targetp != NULL && *targetp == NULL);
3852 
3853 	newref(qpdb, node DNS__DB_FLARG_PASS);
3854 
3855 	*targetp = source;
3856 }
3857 
3858 static void
3859 detachnode(dns_db_t *db, dns_dbnode_t **targetp DNS__DB_FLARG) {
3860 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
3861 	qpznode_t *node = NULL;
3862 	bool want_free = false;
3863 	bool inactive = false;
3864 	db_nodelock_t *nodelock = NULL;
3865 	isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
3866 
3867 	REQUIRE(VALID_QPZONE(qpdb));
3868 	REQUIRE(targetp != NULL && *targetp != NULL);
3869 
3870 	node = (qpznode_t *)(*targetp);
3871 	nodelock = &qpdb->node_locks[node->locknum];
3872 
3873 	NODE_RDLOCK(&nodelock->lock, &nlocktype);
3874 	decref(qpdb, node, 0, &nlocktype DNS__DB_FLARG_PASS);
3875 	if (isc_refcount_current(&nodelock->references) == 0 &&
3876 	    nodelock->exiting)
3877 	{
3878 		inactive = true;
3879 	}
3880 	NODE_UNLOCK(&nodelock->lock, &nlocktype);
3881 
3882 	*targetp = NULL;
3883 
3884 	if (inactive) {
3885 		RWLOCK(&qpdb->lock, isc_rwlocktype_write);
3886 		qpdb->active--;
3887 		if (qpdb->active == 0) {
3888 			want_free = true;
3889 		}
3890 		RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
3891 		if (want_free) {
3892 			char buf[DNS_NAME_FORMATSIZE];
3893 			if (dns_name_dynamic(&qpdb->common.origin)) {
3894 				dns_name_format(&qpdb->common.origin, buf,
3895 						sizeof(buf));
3896 			} else {
3897 				strlcpy(buf, "<UNKNOWN>", sizeof(buf));
3898 			}
3899 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
3900 				      DNS_LOGMODULE_DB, ISC_LOG_DEBUG(1),
3901 				      "calling free_qpdb(%s)", buf);
3902 			free_qpdb(qpdb, true);
3903 		}
3904 	}
3905 }
3906 
3907 static unsigned int
3908 nodecount(dns_db_t *db, dns_dbtree_t tree) {
3909 	qpzonedb_t *qpdb = NULL;
3910 	dns_qp_memusage_t mu;
3911 
3912 	qpdb = (qpzonedb_t *)db;
3913 
3914 	REQUIRE(VALID_QPZONE(qpdb));
3915 
3916 	switch (tree) {
3917 	case dns_dbtree_main:
3918 		mu = dns_qpmulti_memusage(qpdb->tree);
3919 		break;
3920 	case dns_dbtree_nsec:
3921 		mu = dns_qpmulti_memusage(qpdb->nsec);
3922 		break;
3923 	case dns_dbtree_nsec3:
3924 		mu = dns_qpmulti_memusage(qpdb->nsec3);
3925 		break;
3926 	default:
3927 		UNREACHABLE();
3928 	}
3929 
3930 	return mu.leaves;
3931 }
3932 
3933 static void
3934 setloop(dns_db_t *db, isc_loop_t *loop) {
3935 	qpzonedb_t *qpdb = NULL;
3936 
3937 	qpdb = (qpzonedb_t *)db;
3938 
3939 	REQUIRE(VALID_QPZONE(qpdb));
3940 
3941 	RWLOCK(&qpdb->lock, isc_rwlocktype_write);
3942 	if (qpdb->loop != NULL) {
3943 		isc_loop_detach(&qpdb->loop);
3944 	}
3945 	if (loop != NULL) {
3946 		isc_loop_attach(loop, &qpdb->loop);
3947 	}
3948 	RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
3949 }
3950 
3951 static isc_result_t
3952 getoriginnode(dns_db_t *db, dns_dbnode_t **nodep DNS__DB_FLARG) {
3953 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
3954 	qpznode_t *onode = NULL;
3955 
3956 	REQUIRE(VALID_QPZONE(qpdb));
3957 	REQUIRE(nodep != NULL && *nodep == NULL);
3958 
3959 	/* Note that the access to the origin node doesn't require a DB lock */
3960 	onode = (qpznode_t *)qpdb->origin;
3961 	INSIST(onode != NULL);
3962 	newref(qpdb, onode DNS__DB_FLARG_PASS);
3963 	*nodep = onode;
3964 
3965 	return ISC_R_SUCCESS;
3966 }
3967 
3968 static void
3969 locknode(dns_db_t *db, dns_dbnode_t *dbnode, isc_rwlocktype_t type) {
3970 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
3971 	qpznode_t *node = (qpznode_t *)dbnode;
3972 
3973 	RWLOCK(&qpdb->node_locks[node->locknum].lock, type);
3974 }
3975 
3976 static void
3977 unlocknode(dns_db_t *db, dns_dbnode_t *dbnode, isc_rwlocktype_t type) {
3978 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
3979 	qpznode_t *node = (qpznode_t *)dbnode;
3980 
3981 	RWUNLOCK(&qpdb->node_locks[node->locknum].lock, type);
3982 }
3983 
3984 static void
3985 deletedata(dns_db_t *db ISC_ATTR_UNUSED, dns_dbnode_t *node ISC_ATTR_UNUSED,
3986 	   void *data) {
3987 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
3988 	dns_slabheader_t *header = data;
3989 
3990 	if (header->heap != NULL && header->heap_index != 0) {
3991 		RWLOCK(&qpdb->lock, isc_rwlocktype_write);
3992 		isc_heap_delete(header->heap, header->heap_index);
3993 		RWUNLOCK(&qpdb->lock, isc_rwlocktype_write);
3994 	}
3995 	header->heap_index = 0;
3996 }
3997 
3998 /*
3999  * Rdataset Iterator Methods
4000  */
4001 
4002 static void
4003 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp DNS__DB_FLARG) {
4004 	qpdb_rdatasetiter_t *qrditer = NULL;
4005 
4006 	qrditer = (qpdb_rdatasetiter_t *)(*iteratorp);
4007 
4008 	if (qrditer->common.version != NULL) {
4009 		closeversion(qrditer->common.db, &qrditer->common.version,
4010 			     false DNS__DB_FLARG_PASS);
4011 	}
4012 	dns__db_detachnode(qrditer->common.db,
4013 			   &qrditer->common.node DNS__DB_FLARG_PASS);
4014 	isc_mem_put(qrditer->common.db->mctx, qrditer, sizeof(*qrditer));
4015 
4016 	*iteratorp = NULL;
4017 }
4018 
4019 static isc_result_t
4020 rdatasetiter_first(dns_rdatasetiter_t *iterator DNS__DB_FLARG) {
4021 	qpdb_rdatasetiter_t *qrditer = (qpdb_rdatasetiter_t *)iterator;
4022 	qpzonedb_t *qpdb = (qpzonedb_t *)(qrditer->common.db);
4023 	qpznode_t *node = qrditer->common.node;
4024 	qpz_version_t *version = qrditer->common.version;
4025 	dns_slabheader_t *header = NULL, *top_next = NULL;
4026 	isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
4027 
4028 	NODE_RDLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
4029 
4030 	for (header = node->data; header != NULL; header = top_next) {
4031 		top_next = header->next;
4032 		do {
4033 			if (header->serial <= version->serial &&
4034 			    !IGNORE(header))
4035 			{
4036 				if (NONEXISTENT(header)) {
4037 					header = NULL;
4038 				}
4039 				break;
4040 			} else {
4041 				header = header->down;
4042 			}
4043 		} while (header != NULL);
4044 		if (header != NULL) {
4045 			break;
4046 		}
4047 	}
4048 
4049 	NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
4050 
4051 	qrditer->current = header;
4052 
4053 	if (header == NULL) {
4054 		return ISC_R_NOMORE;
4055 	}
4056 
4057 	return ISC_R_SUCCESS;
4058 }
4059 
4060 static isc_result_t
4061 rdatasetiter_next(dns_rdatasetiter_t *iterator DNS__DB_FLARG) {
4062 	qpdb_rdatasetiter_t *qrditer = (qpdb_rdatasetiter_t *)iterator;
4063 	qpzonedb_t *qpdb = (qpzonedb_t *)(qrditer->common.db);
4064 	qpznode_t *node = qrditer->common.node;
4065 	qpz_version_t *version = qrditer->common.version;
4066 	dns_slabheader_t *header = NULL, *top_next = NULL;
4067 	dns_typepair_t type, negtype;
4068 	dns_rdatatype_t rdtype;
4069 	isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
4070 
4071 	header = qrditer->current;
4072 	if (header == NULL) {
4073 		return ISC_R_NOMORE;
4074 	}
4075 
4076 	NODE_RDLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
4077 
4078 	type = header->type;
4079 	rdtype = DNS_TYPEPAIR_TYPE(header->type);
4080 	negtype = DNS_TYPEPAIR_VALUE(0, rdtype);
4081 
4082 	/*
4083 	 * Find the start of the header chain for the next type
4084 	 * by walking back up the list.
4085 	 */
4086 	top_next = header->next;
4087 	while (top_next != NULL &&
4088 	       (top_next->type == type || top_next->type == negtype))
4089 	{
4090 		top_next = top_next->next;
4091 	}
4092 	for (header = top_next; header != NULL; header = top_next) {
4093 		top_next = header->next;
4094 		do {
4095 			if (header->serial <= version->serial &&
4096 			    !IGNORE(header))
4097 			{
4098 				if (NONEXISTENT(header)) {
4099 					header = NULL;
4100 				}
4101 				break;
4102 			} else {
4103 				header = header->down;
4104 			}
4105 		} while (header != NULL);
4106 		if (header != NULL) {
4107 			break;
4108 		}
4109 		/*
4110 		 * Find the start of the header chain for the next type
4111 		 * by walking back up the list.
4112 		 */
4113 		while (top_next != NULL &&
4114 		       (top_next->type == type || top_next->type == negtype))
4115 		{
4116 			top_next = top_next->next;
4117 		}
4118 	}
4119 
4120 	NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
4121 
4122 	qrditer->current = header;
4123 
4124 	if (header == NULL) {
4125 		return ISC_R_NOMORE;
4126 	}
4127 
4128 	return ISC_R_SUCCESS;
4129 }
4130 
4131 static void
4132 rdatasetiter_current(dns_rdatasetiter_t *iterator,
4133 		     dns_rdataset_t *rdataset DNS__DB_FLARG) {
4134 	qpdb_rdatasetiter_t *qrditer = (qpdb_rdatasetiter_t *)iterator;
4135 	qpzonedb_t *qpdb = (qpzonedb_t *)(qrditer->common.db);
4136 	qpznode_t *node = qrditer->common.node;
4137 	dns_slabheader_t *header = NULL;
4138 	isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
4139 
4140 	header = qrditer->current;
4141 	REQUIRE(header != NULL);
4142 
4143 	NODE_RDLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
4144 
4145 	bindrdataset(qpdb, node, header, qrditer->common.now,
4146 		     rdataset DNS__DB_FLARG_PASS);
4147 
4148 	NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
4149 }
4150 
4151 /*
4152  * Database Iterator Methods
4153  */
4154 static void
4155 reference_iter_node(qpdb_dbiterator_t *iter DNS__DB_FLARG) {
4156 	qpzonedb_t *qpdb = (qpzonedb_t *)iter->common.db;
4157 	qpznode_t *node = iter->node;
4158 
4159 	if (node == NULL) {
4160 		return;
4161 	}
4162 
4163 	newref(qpdb, node DNS__DB_FLARG_PASS);
4164 }
4165 
4166 static void
4167 dereference_iter_node(qpdb_dbiterator_t *iter DNS__DB_FLARG) {
4168 	qpzonedb_t *qpdb = (qpzonedb_t *)iter->common.db;
4169 	qpznode_t *node = iter->node;
4170 	isc_rwlock_t *lock = NULL;
4171 	isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
4172 
4173 	if (node == NULL) {
4174 		return;
4175 	}
4176 
4177 	lock = &qpdb->node_locks[node->locknum].lock;
4178 	NODE_RDLOCK(lock, &nlocktype);
4179 	decref(qpdb, node, 0, &nlocktype DNS__DB_FLARG_PASS);
4180 	NODE_UNLOCK(lock, &nlocktype);
4181 	iter->node = NULL;
4182 }
4183 
4184 static void
4185 dbiterator_destroy(dns_dbiterator_t **iteratorp DNS__DB_FLARG) {
4186 	qpdb_dbiterator_t *iter = (qpdb_dbiterator_t *)(*iteratorp);
4187 	dns_db_t *db = NULL;
4188 
4189 	dereference_iter_node(iter DNS__DB_FLARG_PASS);
4190 
4191 	dns_db_attach(iter->common.db, &db);
4192 	dns_db_detach(&iter->common.db);
4193 
4194 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
4195 	dns_qpsnap_destroy(qpdb->tree, &iter->tsnap);
4196 	dns_qpsnap_destroy(qpdb->nsec3, &iter->nsnap);
4197 
4198 	isc_mem_put(db->mctx, iter, sizeof(*iter));
4199 	dns_db_detach(&db);
4200 
4201 	*iteratorp = NULL;
4202 }
4203 
4204 static isc_result_t
4205 dbiterator_first(dns_dbiterator_t *iterator DNS__DB_FLARG) {
4206 	isc_result_t result;
4207 	qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator;
4208 	qpzonedb_t *qpdb = (qpzonedb_t *)iterator->db;
4209 
4210 	if (qpdbiter->result != ISC_R_SUCCESS &&
4211 	    qpdbiter->result != ISC_R_NOTFOUND &&
4212 	    qpdbiter->result != DNS_R_PARTIALMATCH &&
4213 	    qpdbiter->result != ISC_R_NOMORE)
4214 	{
4215 		return qpdbiter->result;
4216 	}
4217 
4218 	dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
4219 
4220 	switch (qpdbiter->nsec3mode) {
4221 	case nsec3only:
4222 		qpdbiter->current = &qpdbiter->nsec3iter;
4223 		dns_qpiter_init(qpdbiter->nsnap, qpdbiter->current);
4224 		result = dns_qpiter_next(qpdbiter->current, NULL,
4225 					 (void **)&qpdbiter->node, NULL);
4226 		if (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
4227 			/* If we're in the NSEC3 tree, skip the origin */
4228 			if (QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) {
4229 				result = dns_qpiter_next(
4230 					qpdbiter->current, NULL,
4231 					(void **)&qpdbiter->node, NULL);
4232 			}
4233 		}
4234 		break;
4235 	case nonsec3:
4236 		qpdbiter->current = &qpdbiter->mainiter;
4237 		dns_qpiter_init(qpdbiter->tsnap, qpdbiter->current);
4238 		result = dns_qpiter_next(qpdbiter->current, NULL,
4239 					 (void **)&qpdbiter->node, NULL);
4240 		break;
4241 	case full:
4242 		qpdbiter->current = &qpdbiter->mainiter;
4243 		dns_qpiter_init(qpdbiter->tsnap, qpdbiter->current);
4244 		result = dns_qpiter_next(qpdbiter->current, NULL,
4245 					 (void **)&qpdbiter->node, NULL);
4246 		if (result == ISC_R_NOMORE) {
4247 			qpdbiter->current = &qpdbiter->nsec3iter;
4248 			dns_qpiter_init(qpdbiter->nsnap, qpdbiter->current);
4249 			result = dns_qpiter_next(qpdbiter->current, NULL,
4250 						 (void **)&qpdbiter->node,
4251 						 NULL);
4252 		}
4253 		break;
4254 	default:
4255 		UNREACHABLE();
4256 	}
4257 
4258 	if (result == ISC_R_SUCCESS) {
4259 		reference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
4260 	} else {
4261 		qpdbiter->node = NULL;
4262 	}
4263 	qpdbiter->result = result;
4264 	return result;
4265 }
4266 
4267 static isc_result_t
4268 dbiterator_last(dns_dbiterator_t *iterator DNS__DB_FLARG) {
4269 	isc_result_t result;
4270 	qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator;
4271 	qpzonedb_t *qpdb = (qpzonedb_t *)iterator->db;
4272 
4273 	if (qpdbiter->result != ISC_R_SUCCESS &&
4274 	    qpdbiter->result != ISC_R_NOTFOUND &&
4275 	    qpdbiter->result != DNS_R_PARTIALMATCH &&
4276 	    qpdbiter->result != ISC_R_NOMORE)
4277 	{
4278 		return qpdbiter->result;
4279 	}
4280 
4281 	dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
4282 
4283 	switch (qpdbiter->nsec3mode) {
4284 	case nsec3only:
4285 		qpdbiter->current = &qpdbiter->nsec3iter;
4286 		dns_qpiter_init(qpdbiter->nsnap, qpdbiter->current);
4287 		result = dns_qpiter_prev(qpdbiter->current, NULL,
4288 					 (void **)&qpdbiter->node, NULL);
4289 		if ((result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) &&
4290 		    QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter))
4291 		{
4292 			/*
4293 			 * NSEC3 tree only has an origin node.
4294 			 */
4295 			qpdbiter->node = NULL;
4296 			result = ISC_R_NOMORE;
4297 		}
4298 		break;
4299 	case nonsec3:
4300 		qpdbiter->current = &qpdbiter->mainiter;
4301 		dns_qpiter_init(qpdbiter->tsnap, qpdbiter->current);
4302 		result = dns_qpiter_prev(qpdbiter->current, NULL,
4303 					 (void **)&qpdbiter->node, NULL);
4304 		break;
4305 	case full:
4306 		qpdbiter->current = &qpdbiter->nsec3iter;
4307 		dns_qpiter_init(qpdbiter->nsnap, qpdbiter->current);
4308 		result = dns_qpiter_prev(qpdbiter->current, NULL,
4309 					 (void **)&qpdbiter->node, NULL);
4310 		if ((result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) &&
4311 		    QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter))
4312 		{
4313 			/*
4314 			 * NSEC3 tree only has an origin node.
4315 			 */
4316 			qpdbiter->node = NULL;
4317 			result = ISC_R_NOMORE;
4318 		}
4319 		if (result == ISC_R_NOMORE) {
4320 			qpdbiter->current = &qpdbiter->mainiter;
4321 			dns_qpiter_init(qpdbiter->tsnap, qpdbiter->current);
4322 			result = dns_qpiter_prev(qpdbiter->current, NULL,
4323 						 (void **)&qpdbiter->node,
4324 						 NULL);
4325 		}
4326 		break;
4327 	default:
4328 		UNREACHABLE();
4329 	}
4330 
4331 	if (result == ISC_R_SUCCESS) {
4332 		reference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
4333 	} else {
4334 		qpdbiter->node = NULL;
4335 	}
4336 	qpdbiter->result = result;
4337 	return result;
4338 }
4339 
4340 static isc_result_t
4341 dbiterator_seek(dns_dbiterator_t *iterator,
4342 		const dns_name_t *name DNS__DB_FLARG) {
4343 	isc_result_t result, tresult;
4344 	qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator;
4345 
4346 	if (qpdbiter->result != ISC_R_SUCCESS &&
4347 	    qpdbiter->result != ISC_R_NOTFOUND &&
4348 	    qpdbiter->result != DNS_R_PARTIALMATCH &&
4349 	    qpdbiter->result != ISC_R_NOMORE)
4350 	{
4351 		return qpdbiter->result;
4352 	}
4353 
4354 	dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
4355 
4356 	switch (qpdbiter->nsec3mode) {
4357 	case nsec3only:
4358 		qpdbiter->current = &qpdbiter->nsec3iter;
4359 		result = dns_qp_lookup(qpdbiter->nsnap, name, NULL,
4360 				       qpdbiter->current, NULL,
4361 				       (void **)&qpdbiter->node, NULL);
4362 		break;
4363 	case nonsec3:
4364 		qpdbiter->current = &qpdbiter->mainiter;
4365 		result = dns_qp_lookup(qpdbiter->tsnap, name, NULL,
4366 				       qpdbiter->current, NULL,
4367 				       (void **)&qpdbiter->node, NULL);
4368 		break;
4369 	case full:
4370 		/*
4371 		 * Stay on main chain if not found on
4372 		 * either iterator.
4373 		 */
4374 		qpdbiter->current = &qpdbiter->mainiter;
4375 		result = dns_qp_lookup(qpdbiter->tsnap, name, NULL,
4376 				       qpdbiter->current, NULL,
4377 				       (void **)&qpdbiter->node, NULL);
4378 		if (result == DNS_R_PARTIALMATCH) {
4379 			tresult = dns_qp_lookup(qpdbiter->nsnap, name, NULL,
4380 						&qpdbiter->nsec3iter, NULL,
4381 						NULL, NULL);
4382 			if (tresult == ISC_R_SUCCESS) {
4383 				qpdbiter->current = &qpdbiter->nsec3iter;
4384 				result = tresult;
4385 			}
4386 		}
4387 		break;
4388 	default:
4389 		UNREACHABLE();
4390 	}
4391 
4392 	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
4393 		reference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
4394 	} else {
4395 		qpdbiter->node = NULL;
4396 	}
4397 
4398 	qpdbiter->result = (result == DNS_R_PARTIALMATCH) ? ISC_R_SUCCESS
4399 							  : result;
4400 	return result;
4401 }
4402 
4403 static isc_result_t
4404 dbiterator_prev(dns_dbiterator_t *iterator DNS__DB_FLARG) {
4405 	isc_result_t result;
4406 	qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator;
4407 	qpzonedb_t *qpdb = (qpzonedb_t *)iterator->db;
4408 
4409 	REQUIRE(qpdbiter->node != NULL);
4410 
4411 	if (qpdbiter->result != ISC_R_SUCCESS) {
4412 		return qpdbiter->result;
4413 	}
4414 
4415 	dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
4416 
4417 	result = dns_qpiter_prev(qpdbiter->current, NULL,
4418 				 (void **)&qpdbiter->node, NULL);
4419 
4420 	if (qpdbiter->current == &qpdbiter->nsec3iter) {
4421 		if (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
4422 			/*
4423 			 * If we're in the NSEC3 tree, it's empty or
4424 			 * we've reached the origin, then we're done
4425 			 * with it.
4426 			 */
4427 			if (QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) {
4428 				qpdbiter->node = NULL;
4429 				result = ISC_R_NOMORE;
4430 			}
4431 		}
4432 		if (result == ISC_R_NOMORE && qpdbiter->nsec3mode == full) {
4433 			qpdbiter->current = &qpdbiter->mainiter;
4434 			dns_qpiter_init(qpdbiter->tsnap, qpdbiter->current);
4435 			result = dns_qpiter_prev(qpdbiter->current, NULL,
4436 						 (void **)&qpdbiter->node,
4437 						 NULL);
4438 		}
4439 	}
4440 
4441 	if (result == ISC_R_SUCCESS) {
4442 		reference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
4443 	} else {
4444 		qpdbiter->node = NULL;
4445 	}
4446 
4447 	qpdbiter->result = result;
4448 	return result;
4449 }
4450 
4451 static isc_result_t
4452 dbiterator_next(dns_dbiterator_t *iterator DNS__DB_FLARG) {
4453 	isc_result_t result;
4454 	qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator;
4455 	qpzonedb_t *qpdb = (qpzonedb_t *)iterator->db;
4456 
4457 	REQUIRE(qpdbiter->node != NULL);
4458 
4459 	if (qpdbiter->result != ISC_R_SUCCESS) {
4460 		return qpdbiter->result;
4461 	}
4462 
4463 	dereference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
4464 
4465 	result = dns_qpiter_next(qpdbiter->current, NULL,
4466 				 (void **)&qpdbiter->node, NULL);
4467 
4468 	if (result == ISC_R_NOMORE && qpdbiter->nsec3mode == full &&
4469 	    qpdbiter->current == &qpdbiter->mainiter)
4470 	{
4471 		qpdbiter->current = &qpdbiter->nsec3iter;
4472 		dns_qpiter_init(qpdbiter->nsnap, qpdbiter->current);
4473 		result = dns_qpiter_next(qpdbiter->current, NULL,
4474 					 (void **)&qpdbiter->node, NULL);
4475 	}
4476 
4477 	if (result == ISC_R_SUCCESS) {
4478 		/*
4479 		 * If we've just started the NSEC3 tree,
4480 		 * skip over the origin.
4481 		 */
4482 		if (QPDBITER_NSEC3_ORIGIN_NODE(qpdb, qpdbiter)) {
4483 			switch (qpdbiter->nsec3mode) {
4484 			case nsec3only:
4485 			case full:
4486 				result = dns_qpiter_next(
4487 					qpdbiter->current, NULL,
4488 					(void **)&qpdbiter->node, NULL);
4489 				break;
4490 			case nonsec3:
4491 				result = ISC_R_NOMORE;
4492 				qpdbiter->node = NULL;
4493 				break;
4494 			default:
4495 				UNREACHABLE();
4496 			}
4497 		}
4498 	}
4499 
4500 	if (result == ISC_R_SUCCESS) {
4501 		reference_iter_node(qpdbiter DNS__DB_FLARG_PASS);
4502 	} else {
4503 		qpdbiter->node = NULL;
4504 	}
4505 
4506 	qpdbiter->result = result;
4507 	return result;
4508 }
4509 
4510 static isc_result_t
4511 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
4512 		   dns_name_t *name DNS__DB_FLARG) {
4513 	qpzonedb_t *qpdb = (qpzonedb_t *)iterator->db;
4514 	qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator;
4515 	qpznode_t *node = qpdbiter->node;
4516 
4517 	REQUIRE(qpdbiter->result == ISC_R_SUCCESS);
4518 	REQUIRE(qpdbiter->node != NULL);
4519 
4520 	if (name != NULL) {
4521 		dns_name_copy(&qpdbiter->node->name, name);
4522 	}
4523 
4524 	newref(qpdb, node DNS__DB_FLARG_PASS);
4525 
4526 	*nodep = qpdbiter->node;
4527 
4528 	return ISC_R_SUCCESS;
4529 }
4530 
4531 static isc_result_t
4532 dbiterator_pause(dns_dbiterator_t *iterator ISC_ATTR_UNUSED) {
4533 	return ISC_R_SUCCESS;
4534 }
4535 
4536 static isc_result_t
4537 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
4538 	qpdb_dbiterator_t *qpdbiter = (qpdb_dbiterator_t *)iterator;
4539 
4540 	if (qpdbiter->result != ISC_R_SUCCESS) {
4541 		return qpdbiter->result;
4542 	}
4543 
4544 	dns_name_copy(dns_rootname, name);
4545 	return ISC_R_SUCCESS;
4546 }
4547 
4548 static isc_result_t
4549 createiterator(dns_db_t *db, unsigned int options,
4550 	       dns_dbiterator_t **iteratorp) {
4551 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
4552 	qpdb_dbiterator_t *iter = NULL;
4553 
4554 	REQUIRE(VALID_QPZONE(qpdb));
4555 
4556 	iter = isc_mem_get(qpdb->common.mctx, sizeof(*iter));
4557 	*iter = (qpdb_dbiterator_t){
4558 		.common.magic = DNS_DBITERATOR_MAGIC,
4559 		.common.methods = &dbiterator_methods,
4560 		.common.relative_names = ((options & DNS_DB_RELATIVENAMES) !=
4561 					  0),
4562 	};
4563 
4564 	if ((options & DNS_DB_NSEC3ONLY) != 0) {
4565 		iter->nsec3mode = nsec3only;
4566 		iter->current = &iter->nsec3iter;
4567 	} else if ((options & DNS_DB_NONSEC3) != 0) {
4568 		iter->nsec3mode = nonsec3;
4569 		iter->current = &iter->mainiter;
4570 	} else {
4571 		iter->nsec3mode = full;
4572 		iter->current = &iter->mainiter;
4573 	}
4574 
4575 	dns_db_attach(db, &iter->common.db);
4576 
4577 	dns_qpmulti_snapshot(qpdb->tree, &iter->tsnap);
4578 	dns_qpiter_init(iter->tsnap, &iter->mainiter);
4579 
4580 	dns_qpmulti_snapshot(qpdb->nsec3, &iter->nsnap);
4581 	dns_qpiter_init(iter->nsnap, &iter->nsec3iter);
4582 
4583 	*iteratorp = (dns_dbiterator_t *)iter;
4584 	return ISC_R_SUCCESS;
4585 }
4586 
4587 static isc_result_t
4588 addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
4589 	    isc_stdtime_t now ISC_ATTR_UNUSED, dns_rdataset_t *rdataset,
4590 	    unsigned int options, dns_rdataset_t *addedrdataset DNS__DB_FLARG) {
4591 	isc_result_t result;
4592 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
4593 	qpznode_t *node = (qpznode_t *)dbnode;
4594 	qpz_version_t *version = dbversion;
4595 	isc_region_t region;
4596 	dns_slabheader_t *newheader = NULL;
4597 	isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
4598 	dns_fixedname_t fn;
4599 	dns_name_t *name = dns_fixedname_initname(&fn);
4600 	dns_qp_t *nsec = NULL;
4601 
4602 	REQUIRE(VALID_QPZONE(qpdb));
4603 	REQUIRE(version != NULL && version->qpdb == qpdb);
4604 
4605 	/*
4606 	 * SOA records are only allowed at top of zone.
4607 	 */
4608 	if (rdataset->type == dns_rdatatype_soa && node != qpdb->origin) {
4609 		return DNS_R_NOTZONETOP;
4610 	}
4611 
4612 	REQUIRE((node->nsec == DNS_DB_NSEC_NSEC3 &&
4613 		 (rdataset->type == dns_rdatatype_nsec3 ||
4614 		  rdataset->covers == dns_rdatatype_nsec3)) ||
4615 		(node->nsec != DNS_DB_NSEC_NSEC3 &&
4616 		 rdataset->type != dns_rdatatype_nsec3 &&
4617 		 rdataset->covers != dns_rdatatype_nsec3));
4618 
4619 	result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx,
4620 					    &region, sizeof(dns_slabheader_t),
4621 					    qpdb->maxrrperset);
4622 	if (result != ISC_R_SUCCESS) {
4623 		if (result == DNS_R_TOOMANYRECORDS) {
4624 			dns__db_logtoomanyrecords((dns_db_t *)qpdb, &node->name,
4625 						  rdataset->type, "adding",
4626 						  qpdb->maxrrperset);
4627 		}
4628 		return result;
4629 	}
4630 
4631 	dns_name_copy(&node->name, name);
4632 	dns_rdataset_getownercase(rdataset, name);
4633 
4634 	newheader = (dns_slabheader_t *)region.base;
4635 	*newheader = (dns_slabheader_t){
4636 		.type = DNS_TYPEPAIR_VALUE(rdataset->type, rdataset->covers),
4637 		.trust = rdataset->trust,
4638 		.node = node,
4639 	};
4640 
4641 	dns_slabheader_reset(newheader, db, node);
4642 	newheader->ttl = rdataset->ttl;
4643 	if (rdataset->ttl == 0U) {
4644 		DNS_SLABHEADER_SETATTR(newheader, DNS_SLABHEADERATTR_ZEROTTL);
4645 	}
4646 	atomic_init(&newheader->count,
4647 		    atomic_fetch_add_relaxed(&init_count, 1));
4648 
4649 	newheader->serial = version->serial;
4650 	if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
4651 		DNS_SLABHEADER_SETATTR(newheader, DNS_SLABHEADERATTR_RESIGN);
4652 		newheader->resign =
4653 			(isc_stdtime_t)(dns_time64_from32(rdataset->resign) >>
4654 					1);
4655 		newheader->resign_lsb = rdataset->resign & 0x1;
4656 	}
4657 
4658 	/*
4659 	 * Add to the auxiliary NSEC tree if we're adding an NSEC record.
4660 	 */
4661 	if (node->nsec != DNS_DB_NSEC_HAS_NSEC &&
4662 	    rdataset->type == dns_rdatatype_nsec)
4663 	{
4664 		dns_qpmulti_write(qpdb->nsec, &nsec);
4665 	}
4666 
4667 	/*
4668 	 * If we're adding a delegation type or adding to the auxiliary NSEC
4669 	 * tree hold an exclusive lock on the tree.  In the latter case the
4670 	 * lock does not necessarily have to be acquired but it will help
4671 	 * purge ancient entries more effectively.
4672 	 *
4673 	 * (Note: node lock must be acquired after starting
4674 	 * the QPDB transaction and released before committing.)
4675 	 */
4676 	NODE_WRLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
4677 
4678 	result = ISC_R_SUCCESS;
4679 	if (nsec != NULL) {
4680 		qpznode_t *nsecnode = new_qpznode(qpdb, name);
4681 		result = dns_qp_insert(nsec, nsecnode, 0);
4682 		if (result == ISC_R_SUCCESS) {
4683 			nsecnode->nsec = DNS_DB_NSEC_NSEC;
4684 			node->nsec = DNS_DB_NSEC_HAS_NSEC;
4685 		} else if (result == ISC_R_EXISTS) {
4686 			node->nsec = DNS_DB_NSEC_HAS_NSEC;
4687 			result = ISC_R_SUCCESS;
4688 		}
4689 		qpznode_detach(&nsecnode);
4690 	}
4691 
4692 	if (result == ISC_R_SUCCESS) {
4693 		result = add(qpdb, node, name, version, newheader, options,
4694 			     false, addedrdataset, 0 DNS__DB_FLARG_PASS);
4695 	}
4696 
4697 	/*
4698 	 * If we're adding a delegation type (e.g. NS or DNAME),
4699 	 * then we need to set the callback bit on the node.
4700 	 */
4701 	if (result == ISC_R_SUCCESS &&
4702 	    delegating_type(qpdb, node, rdataset->type))
4703 	{
4704 		node->delegating = true;
4705 	}
4706 
4707 	NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
4708 
4709 	if (nsec != NULL) {
4710 		dns_qpmulti_commit(qpdb->nsec, &nsec);
4711 	}
4712 
4713 	return result;
4714 }
4715 
4716 static isc_result_t
4717 subtractrdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
4718 		 dns_rdataset_t *rdataset, unsigned int options,
4719 		 dns_rdataset_t *newrdataset DNS__DB_FLARG) {
4720 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
4721 	qpznode_t *node = (qpznode_t *)dbnode;
4722 	qpz_version_t *version = dbversion;
4723 	dns_fixedname_t fname;
4724 	dns_name_t *nodename = dns_fixedname_initname(&fname);
4725 	dns_slabheader_t *topheader = NULL, *topheader_prev = NULL;
4726 	dns_slabheader_t *header = NULL, *newheader = NULL;
4727 	unsigned char *subresult = NULL;
4728 	isc_region_t region;
4729 	isc_result_t result;
4730 	qpz_changed_t *changed = NULL;
4731 	isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
4732 
4733 	REQUIRE(VALID_QPZONE(qpdb));
4734 	REQUIRE(version != NULL && version->qpdb == qpdb);
4735 
4736 	REQUIRE((node->nsec == DNS_DB_NSEC_NSEC3 &&
4737 		 (rdataset->type == dns_rdatatype_nsec3 ||
4738 		  rdataset->covers == dns_rdatatype_nsec3)) ||
4739 		(node->nsec != DNS_DB_NSEC_NSEC3 &&
4740 		 rdataset->type != dns_rdatatype_nsec3 &&
4741 		 rdataset->covers != dns_rdatatype_nsec3));
4742 
4743 	dns_name_copy(&node->name, nodename);
4744 	result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx,
4745 					    &region, sizeof(dns_slabheader_t),
4746 					    0);
4747 	if (result != ISC_R_SUCCESS) {
4748 		return result;
4749 	}
4750 
4751 	newheader = (dns_slabheader_t *)region.base;
4752 	dns_slabheader_reset(newheader, db, node);
4753 	newheader->ttl = rdataset->ttl;
4754 	newheader->type = DNS_TYPEPAIR_VALUE(rdataset->type, rdataset->covers);
4755 	atomic_init(&newheader->attributes, 0);
4756 	newheader->serial = version->serial;
4757 	newheader->trust = 0;
4758 	newheader->noqname = NULL;
4759 	newheader->closest = NULL;
4760 	atomic_init(&newheader->count,
4761 		    atomic_fetch_add_relaxed(&init_count, 1));
4762 	newheader->last_used = 0;
4763 	newheader->node = node;
4764 	newheader->db = (dns_db_t *)qpdb;
4765 	if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
4766 		DNS_SLABHEADER_SETATTR(newheader, DNS_SLABHEADERATTR_RESIGN);
4767 		newheader->resign =
4768 			(isc_stdtime_t)(dns_time64_from32(rdataset->resign) >>
4769 					1);
4770 		newheader->resign_lsb = rdataset->resign & 0x1;
4771 	} else {
4772 		newheader->resign = 0;
4773 		newheader->resign_lsb = 0;
4774 	}
4775 
4776 	NODE_WRLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
4777 
4778 	changed = add_changed(newheader, version DNS__DB_FLARG_PASS);
4779 	for (topheader = node->data; topheader != NULL;
4780 	     topheader = topheader->next)
4781 	{
4782 		if (topheader->type == newheader->type) {
4783 			break;
4784 		}
4785 		topheader_prev = topheader;
4786 	}
4787 	/*
4788 	 * If header isn't NULL, we've found the right type.  There may be
4789 	 * IGNORE rdatasets between the top of the chain and the first real
4790 	 * data.  We skip over them.
4791 	 */
4792 	header = topheader;
4793 	while (header != NULL && IGNORE(header)) {
4794 		header = header->down;
4795 	}
4796 	if (header != NULL && !NONEXISTENT(header)) {
4797 		unsigned int flags = 0;
4798 		subresult = NULL;
4799 		result = ISC_R_SUCCESS;
4800 		if ((options & DNS_DBSUB_EXACT) != 0) {
4801 			flags |= DNS_RDATASLAB_EXACT;
4802 			if (newheader->ttl != header->ttl) {
4803 				result = DNS_R_NOTEXACT;
4804 			}
4805 		}
4806 		if (result == ISC_R_SUCCESS) {
4807 			result = dns_rdataslab_subtract(
4808 				(unsigned char *)header,
4809 				(unsigned char *)newheader,
4810 				(unsigned int)(sizeof(*newheader)),
4811 				qpdb->common.mctx, qpdb->common.rdclass,
4812 				(dns_rdatatype_t)header->type, flags,
4813 				&subresult);
4814 		}
4815 		if (result == ISC_R_SUCCESS) {
4816 			dns_slabheader_destroy(&newheader);
4817 			newheader = (dns_slabheader_t *)subresult;
4818 			dns_slabheader_reset(newheader, db, node);
4819 			dns_slabheader_copycase(newheader, header);
4820 			if (RESIGN(header)) {
4821 				DNS_SLABHEADER_SETATTR(
4822 					newheader, DNS_SLABHEADERATTR_RESIGN);
4823 				newheader->resign = header->resign;
4824 				newheader->resign_lsb = header->resign_lsb;
4825 				resigninsert(qpdb, newheader);
4826 			}
4827 			/*
4828 			 * We have to set the serial since the rdataslab
4829 			 * subtraction routine copies the reserved portion of
4830 			 * header, not newheader.
4831 			 */
4832 			newheader->serial = version->serial;
4833 			/*
4834 			 * XXXJT: dns_rdataslab_subtract() copied the pointers
4835 			 * to additional info.  We need to clear these fields
4836 			 * to avoid having duplicated references.
4837 			 */
4838 			maybe_update_recordsandsize(true, version, newheader,
4839 						    nodename->length);
4840 		} else if (result == DNS_R_NXRRSET) {
4841 			/*
4842 			 * This subtraction would remove all of the rdata;
4843 			 * add a nonexistent header instead.
4844 			 */
4845 			dns_slabheader_destroy(&newheader);
4846 			newheader = dns_slabheader_new((dns_db_t *)qpdb,
4847 						       (dns_dbnode_t *)node);
4848 			newheader->ttl = 0;
4849 			newheader->type = topheader->type;
4850 			atomic_init(&newheader->attributes,
4851 				    DNS_SLABHEADERATTR_NONEXISTENT);
4852 			newheader->serial = version->serial;
4853 		} else {
4854 			dns_slabheader_destroy(&newheader);
4855 			goto unlock;
4856 		}
4857 
4858 		/*
4859 		 * If we're here, we want to link newheader in front of
4860 		 * topheader.
4861 		 */
4862 		INSIST(version->serial >= topheader->serial);
4863 		maybe_update_recordsandsize(false, version, header,
4864 					    nodename->length);
4865 		if (topheader_prev != NULL) {
4866 			topheader_prev->next = newheader;
4867 		} else {
4868 			node->data = newheader;
4869 		}
4870 		newheader->next = topheader->next;
4871 		newheader->down = topheader;
4872 		topheader->next = newheader;
4873 		node->dirty = true;
4874 		changed->dirty = true;
4875 		resigndelete(qpdb, version, header DNS__DB_FLARG_PASS);
4876 	} else {
4877 		/*
4878 		 * The rdataset doesn't exist, so we don't need to do anything
4879 		 * to satisfy the deletion request.
4880 		 */
4881 		dns_slabheader_destroy(&newheader);
4882 		if ((options & DNS_DBSUB_EXACT) != 0) {
4883 			result = DNS_R_NOTEXACT;
4884 		} else {
4885 			result = DNS_R_UNCHANGED;
4886 		}
4887 	}
4888 
4889 	if (result == ISC_R_SUCCESS && newrdataset != NULL) {
4890 		bindrdataset(qpdb, node, newheader, 0,
4891 			     newrdataset DNS__DB_FLARG_PASS);
4892 	}
4893 
4894 	if (result == DNS_R_NXRRSET && newrdataset != NULL &&
4895 	    (options & DNS_DBSUB_WANTOLD) != 0)
4896 	{
4897 		bindrdataset(qpdb, node, header, 0,
4898 			     newrdataset DNS__DB_FLARG_PASS);
4899 	}
4900 
4901 unlock:
4902 	NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
4903 	return result;
4904 }
4905 
4906 static isc_result_t
4907 deleterdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
4908 	       dns_rdatatype_t type, dns_rdatatype_t covers DNS__DB_FLARG) {
4909 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
4910 	qpznode_t *node = (qpznode_t *)dbnode;
4911 	qpz_version_t *version = dbversion;
4912 	dns_fixedname_t fname;
4913 	dns_name_t *nodename = dns_fixedname_initname(&fname);
4914 	isc_result_t result;
4915 	dns_slabheader_t *newheader = NULL;
4916 	isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
4917 
4918 	REQUIRE(VALID_QPZONE(qpdb));
4919 	REQUIRE(version != NULL && version->qpdb == qpdb);
4920 
4921 	if (type == dns_rdatatype_any) {
4922 		return ISC_R_NOTIMPLEMENTED;
4923 	}
4924 	if (type == dns_rdatatype_rrsig && covers == 0) {
4925 		return ISC_R_NOTIMPLEMENTED;
4926 	}
4927 
4928 	newheader = dns_slabheader_new(db, node);
4929 	newheader->type = DNS_TYPEPAIR_VALUE(type, covers);
4930 	newheader->ttl = 0;
4931 	atomic_init(&newheader->attributes, DNS_SLABHEADERATTR_NONEXISTENT);
4932 	newheader->serial = version->serial;
4933 
4934 	dns_name_copy(&node->name, nodename);
4935 
4936 	NODE_WRLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
4937 	result = add(qpdb, node, nodename, version, newheader, DNS_DBADD_FORCE,
4938 		     false, NULL, 0 DNS__DB_FLARG_PASS);
4939 	NODE_UNLOCK(&qpdb->node_locks[node->locknum].lock, &nlocktype);
4940 	return result;
4941 }
4942 
4943 static isc_result_t
4944 nodefullname(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name) {
4945 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
4946 	qpznode_t *qpnode = (qpznode_t *)node;
4947 	isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
4948 
4949 	REQUIRE(VALID_QPZONE(qpdb));
4950 	REQUIRE(node != NULL);
4951 	REQUIRE(name != NULL);
4952 
4953 	NODE_RDLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
4954 	dns_name_copy(&qpnode->name, name);
4955 	NODE_UNLOCK(&qpdb->node_locks[qpnode->locknum].lock, &nlocktype);
4956 	return ISC_R_SUCCESS;
4957 }
4958 
4959 static dns_glue_t *
4960 new_gluelist(isc_mem_t *mctx, dns_name_t *name) {
4961 	dns_glue_t *glue = isc_mem_get(mctx, sizeof(*glue));
4962 	*glue = (dns_glue_t){ 0 };
4963 	dns_name_t *gluename = dns_fixedname_initname(&glue->fixedname);
4964 
4965 	dns_name_copy(name, gluename);
4966 
4967 	return glue;
4968 }
4969 
4970 static isc_result_t
4971 glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
4972 		dns_rdataset_t *unused DNS__DB_FLARG) {
4973 	dns_glue_additionaldata_ctx_t *ctx = NULL;
4974 	isc_result_t result;
4975 	dns_fixedname_t fixedname_a;
4976 	dns_name_t *name_a = NULL;
4977 	dns_rdataset_t rdataset_a, sigrdataset_a;
4978 	qpznode_t *node_a = NULL;
4979 	dns_fixedname_t fixedname_aaaa;
4980 	dns_name_t *name_aaaa = NULL;
4981 	dns_rdataset_t rdataset_aaaa, sigrdataset_aaaa;
4982 	qpznode_t *node_aaaa = NULL;
4983 	dns_glue_t *glue = NULL;
4984 
4985 	UNUSED(unused);
4986 
4987 	/*
4988 	 * NS records want addresses in additional records.
4989 	 */
4990 	INSIST(qtype == dns_rdatatype_a);
4991 
4992 	ctx = (dns_glue_additionaldata_ctx_t *)arg;
4993 
4994 	name_a = dns_fixedname_initname(&fixedname_a);
4995 	dns_rdataset_init(&rdataset_a);
4996 	dns_rdataset_init(&sigrdataset_a);
4997 
4998 	name_aaaa = dns_fixedname_initname(&fixedname_aaaa);
4999 	dns_rdataset_init(&rdataset_aaaa);
5000 	dns_rdataset_init(&sigrdataset_aaaa);
5001 
5002 	result = find(ctx->db, name, ctx->version, dns_rdatatype_a,
5003 		      DNS_DBFIND_GLUEOK, 0, (dns_dbnode_t **)&node_a, name_a,
5004 		      &rdataset_a, &sigrdataset_a DNS__DB_FLARG_PASS);
5005 	if (result == DNS_R_GLUE) {
5006 		glue = new_gluelist(ctx->db->mctx, name_a);
5007 
5008 		dns_rdataset_init(&glue->rdataset_a);
5009 		dns_rdataset_init(&glue->sigrdataset_a);
5010 		dns_rdataset_init(&glue->rdataset_aaaa);
5011 		dns_rdataset_init(&glue->sigrdataset_aaaa);
5012 
5013 		dns_rdataset_clone(&rdataset_a, &glue->rdataset_a);
5014 		if (dns_rdataset_isassociated(&sigrdataset_a)) {
5015 			dns_rdataset_clone(&sigrdataset_a,
5016 					   &glue->sigrdataset_a);
5017 		}
5018 	}
5019 
5020 	result = find(ctx->db, name, ctx->version, dns_rdatatype_aaaa,
5021 		      DNS_DBFIND_GLUEOK, 0, (dns_dbnode_t **)&node_aaaa,
5022 		      name_aaaa, &rdataset_aaaa,
5023 		      &sigrdataset_aaaa DNS__DB_FLARG_PASS);
5024 	if (result == DNS_R_GLUE) {
5025 		if (glue == NULL) {
5026 			glue = new_gluelist(ctx->db->mctx, name_aaaa);
5027 
5028 			dns_rdataset_init(&glue->rdataset_a);
5029 			dns_rdataset_init(&glue->sigrdataset_a);
5030 			dns_rdataset_init(&glue->rdataset_aaaa);
5031 			dns_rdataset_init(&glue->sigrdataset_aaaa);
5032 		} else {
5033 			INSIST(node_a == node_aaaa);
5034 			INSIST(dns_name_equal(name_a, name_aaaa));
5035 		}
5036 
5037 		dns_rdataset_clone(&rdataset_aaaa, &glue->rdataset_aaaa);
5038 		if (dns_rdataset_isassociated(&sigrdataset_aaaa)) {
5039 			dns_rdataset_clone(&sigrdataset_aaaa,
5040 					   &glue->sigrdataset_aaaa);
5041 		}
5042 	}
5043 
5044 	/*
5045 	 * If the currently processed NS record is in-bailiwick, mark any glue
5046 	 * RRsets found for it with DNS_RDATASETATTR_REQUIRED.  Note that for
5047 	 * simplicity, glue RRsets for all in-bailiwick NS records are marked
5048 	 * this way, even though dns_message_rendersection() only checks the
5049 	 * attributes for the first rdataset associated with the first name
5050 	 * added to the ADDITIONAL section.
5051 	 */
5052 	if (glue != NULL && dns_name_issubdomain(name, ctx->nodename)) {
5053 		if (dns_rdataset_isassociated(&glue->rdataset_a)) {
5054 			glue->rdataset_a.attributes |=
5055 				DNS_RDATASETATTR_REQUIRED;
5056 		}
5057 		if (dns_rdataset_isassociated(&glue->rdataset_aaaa)) {
5058 			glue->rdataset_aaaa.attributes |=
5059 				DNS_RDATASETATTR_REQUIRED;
5060 		}
5061 	}
5062 
5063 	if (glue != NULL) {
5064 		glue->next = ctx->glue_list;
5065 		ctx->glue_list = glue;
5066 	}
5067 
5068 	result = ISC_R_SUCCESS;
5069 
5070 	if (dns_rdataset_isassociated(&rdataset_a)) {
5071 		dns_rdataset_disassociate(&rdataset_a);
5072 	}
5073 	if (dns_rdataset_isassociated(&sigrdataset_a)) {
5074 		dns_rdataset_disassociate(&sigrdataset_a);
5075 	}
5076 
5077 	if (dns_rdataset_isassociated(&rdataset_aaaa)) {
5078 		dns_rdataset_disassociate(&rdataset_aaaa);
5079 	}
5080 	if (dns_rdataset_isassociated(&sigrdataset_aaaa)) {
5081 		dns_rdataset_disassociate(&sigrdataset_aaaa);
5082 	}
5083 
5084 	if (node_a != NULL) {
5085 		dns__db_detachnode(ctx->db,
5086 				   (dns_dbnode_t *)&node_a DNS__DB_FLARG_PASS);
5087 	}
5088 	if (node_aaaa != NULL) {
5089 		dns__db_detachnode(
5090 			ctx->db, (dns_dbnode_t *)&node_aaaa DNS__DB_FLARG_PASS);
5091 	}
5092 
5093 	return result;
5094 }
5095 
5096 #define IS_REQUIRED_GLUE(r) (((r)->attributes & DNS_RDATASETATTR_REQUIRED) != 0)
5097 
5098 static void
5099 addglue_to_message(dns_glue_t *ge, dns_message_t *msg) {
5100 	for (; ge != NULL; ge = ge->next) {
5101 		dns_name_t *name = NULL;
5102 		dns_rdataset_t *rdataset_a = NULL;
5103 		dns_rdataset_t *sigrdataset_a = NULL;
5104 		dns_rdataset_t *rdataset_aaaa = NULL;
5105 		dns_rdataset_t *sigrdataset_aaaa = NULL;
5106 		dns_name_t *gluename = dns_fixedname_name(&ge->fixedname);
5107 		bool prepend_name = false;
5108 
5109 		dns_message_gettempname(msg, &name);
5110 
5111 		dns_name_copy(gluename, name);
5112 
5113 		if (dns_rdataset_isassociated(&ge->rdataset_a)) {
5114 			dns_message_gettemprdataset(msg, &rdataset_a);
5115 		}
5116 
5117 		if (dns_rdataset_isassociated(&ge->sigrdataset_a)) {
5118 			dns_message_gettemprdataset(msg, &sigrdataset_a);
5119 		}
5120 
5121 		if (dns_rdataset_isassociated(&ge->rdataset_aaaa)) {
5122 			dns_message_gettemprdataset(msg, &rdataset_aaaa);
5123 		}
5124 
5125 		if (dns_rdataset_isassociated(&ge->sigrdataset_aaaa)) {
5126 			dns_message_gettemprdataset(msg, &sigrdataset_aaaa);
5127 		}
5128 
5129 		if (rdataset_a != NULL) {
5130 			dns_rdataset_clone(&ge->rdataset_a, rdataset_a);
5131 			ISC_LIST_APPEND(name->list, rdataset_a, link);
5132 			if (IS_REQUIRED_GLUE(rdataset_a)) {
5133 				prepend_name = true;
5134 			}
5135 		}
5136 
5137 		if (sigrdataset_a != NULL) {
5138 			dns_rdataset_clone(&ge->sigrdataset_a, sigrdataset_a);
5139 			ISC_LIST_APPEND(name->list, sigrdataset_a, link);
5140 		}
5141 
5142 		if (rdataset_aaaa != NULL) {
5143 			dns_rdataset_clone(&ge->rdataset_aaaa, rdataset_aaaa);
5144 			ISC_LIST_APPEND(name->list, rdataset_aaaa, link);
5145 			if (IS_REQUIRED_GLUE(rdataset_aaaa)) {
5146 				prepend_name = true;
5147 			}
5148 		}
5149 		if (sigrdataset_aaaa != NULL) {
5150 			dns_rdataset_clone(&ge->sigrdataset_aaaa,
5151 					   sigrdataset_aaaa);
5152 			ISC_LIST_APPEND(name->list, sigrdataset_aaaa, link);
5153 		}
5154 
5155 		dns_message_addname(msg, name, DNS_SECTION_ADDITIONAL);
5156 
5157 		/*
5158 		 * When looking for required glue, dns_message_rendersection()
5159 		 * only processes the first rdataset associated with the first
5160 		 * name added to the ADDITIONAL section.  dns_message_addname()
5161 		 * performs an append on the list of names in a given section,
5162 		 * so if any glue record was marked as required, we need to
5163 		 * move the name it is associated with to the beginning of the
5164 		 * list for the ADDITIONAL section or else required glue might
5165 		 * not be rendered.
5166 		 */
5167 		if (prepend_name) {
5168 			ISC_LIST_UNLINK(msg->sections[DNS_SECTION_ADDITIONAL],
5169 					name, link);
5170 			ISC_LIST_PREPEND(msg->sections[DNS_SECTION_ADDITIONAL],
5171 					 name, link);
5172 		}
5173 	}
5174 }
5175 
5176 static dns_glue_t *
5177 newglue(dns_db_t *db, qpz_version_t *version, qpznode_t *node,
5178 	dns_rdataset_t *rdataset) {
5179 	dns_fixedname_t nodename;
5180 	dns_glue_additionaldata_ctx_t ctx = {
5181 		.db = db,
5182 		.version = (dns_dbversion_t *)version,
5183 		.nodename = dns_fixedname_initname(&nodename),
5184 	};
5185 
5186 	/*
5187 	 * Get the owner name of the NS RRset - it will be necessary for
5188 	 * identifying required glue in glue_nsdname_cb() (by
5189 	 * determining which NS records in the delegation are
5190 	 * in-bailiwick).
5191 	 */
5192 	dns_name_copy(&node->name, ctx.nodename);
5193 
5194 	(void)dns_rdataset_additionaldata(rdataset, dns_rootname,
5195 					  glue_nsdname_cb, &ctx);
5196 
5197 	return ctx.glue_list;
5198 }
5199 
5200 static dns_gluenode_t *
5201 new_gluenode(dns_db_t *db, qpz_version_t *version, qpznode_t *node,
5202 	     dns_rdataset_t *rdataset) {
5203 	dns_gluenode_t *gluenode = isc_mem_get(db->mctx, sizeof(*gluenode));
5204 	*gluenode = (dns_gluenode_t){
5205 		.glue = newglue(db, version, node, rdataset),
5206 	};
5207 
5208 	isc_mem_attach(db->mctx, &gluenode->mctx);
5209 	qpznode_attach(node, &gluenode->node);
5210 
5211 	return gluenode;
5212 }
5213 
5214 static void
5215 freeglue(isc_mem_t *mctx, dns_glue_t *glue) {
5216 	while (glue != NULL) {
5217 		dns_glue_t *next = glue->next;
5218 
5219 		if (dns_rdataset_isassociated(&glue->rdataset_a)) {
5220 			dns_rdataset_disassociate(&glue->rdataset_a);
5221 		}
5222 		if (dns_rdataset_isassociated(&glue->sigrdataset_a)) {
5223 			dns_rdataset_disassociate(&glue->sigrdataset_a);
5224 		}
5225 
5226 		if (dns_rdataset_isassociated(&glue->rdataset_aaaa)) {
5227 			dns_rdataset_disassociate(&glue->rdataset_aaaa);
5228 		}
5229 		if (dns_rdataset_isassociated(&glue->sigrdataset_aaaa)) {
5230 			dns_rdataset_disassociate(&glue->sigrdataset_aaaa);
5231 		}
5232 
5233 		dns_rdataset_invalidate(&glue->rdataset_a);
5234 		dns_rdataset_invalidate(&glue->sigrdataset_a);
5235 		dns_rdataset_invalidate(&glue->rdataset_aaaa);
5236 		dns_rdataset_invalidate(&glue->sigrdataset_aaaa);
5237 
5238 		isc_mem_put(mctx, glue, sizeof(*glue));
5239 
5240 		glue = next;
5241 	}
5242 }
5243 
5244 static void
5245 free_gluenode_rcu(struct rcu_head *rcu_head) {
5246 	dns_gluenode_t *gluenode = caa_container_of(rcu_head, dns_gluenode_t,
5247 						    rcu_head);
5248 
5249 	freeglue(gluenode->mctx, gluenode->glue);
5250 
5251 	qpznode_detach(&gluenode->node);
5252 
5253 	isc_mem_putanddetach(&gluenode->mctx, gluenode, sizeof(*gluenode));
5254 }
5255 
5256 static void
5257 free_gluenode(dns_gluenode_t *gluenode) {
5258 	call_rcu(&gluenode->rcu_head, free_gluenode_rcu);
5259 }
5260 
5261 static uint32_t
5262 qpznode_hash(const qpznode_t *node) {
5263 	return isc_hash32(&node, sizeof(node), true);
5264 }
5265 
5266 static int
5267 qpznode_match(struct cds_lfht_node *ht_node, const void *key) {
5268 	const dns_gluenode_t *gluenode =
5269 		caa_container_of(ht_node, dns_gluenode_t, ht_node);
5270 	const qpznode_t *node = key;
5271 
5272 	return gluenode->node == node;
5273 }
5274 
5275 static uint32_t
5276 gluenode_hash(const dns_gluenode_t *gluenode) {
5277 	return qpznode_hash(gluenode->node);
5278 }
5279 
5280 static int
5281 gluenode_match(struct cds_lfht_node *ht_node, const void *key) {
5282 	const dns_gluenode_t *gluenode = key;
5283 
5284 	return qpznode_match(ht_node, gluenode->node);
5285 }
5286 
5287 static void
5288 addglue(dns_db_t *db, dns_dbversion_t *dbversion, dns_rdataset_t *rdataset,
5289 	dns_message_t *msg) {
5290 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
5291 	qpz_version_t *version = dbversion;
5292 	qpznode_t *node = (qpznode_t *)rdataset->slab.node;
5293 	dns_gluenode_t *gluenode = NULL;
5294 
5295 	REQUIRE(rdataset->type == dns_rdatatype_ns);
5296 	REQUIRE(qpdb == (qpzonedb_t *)rdataset->slab.db);
5297 	REQUIRE(qpdb == version->qpdb);
5298 	REQUIRE(!IS_STUB(qpdb));
5299 
5300 	/*
5301 	 * The glue table cache that forms a part of the DB version
5302 	 * structure is not explicitly bounded and there's no cache
5303 	 * cleaning. The zone data size itself is an implicit bound.
5304 	 *
5305 	 * The key into the glue hashtable is the node pointer. This is
5306 	 * because the glue hashtable is a property of the DB version,
5307 	 * and the glue is keyed for the ownername/NS tuple. We don't
5308 	 * bother with using an expensive dns_name_t comparison here as
5309 	 * the node pointer is a fixed value that won't change for a DB
5310 	 * version and can be compared directly.
5311 	 */
5312 
5313 	rcu_read_lock();
5314 
5315 	struct cds_lfht_iter iter;
5316 	cds_lfht_lookup(version->glue_table, qpznode_hash(node), qpznode_match,
5317 			node, &iter);
5318 
5319 	gluenode = cds_lfht_entry(cds_lfht_iter_get_node(&iter), dns_gluenode_t,
5320 				  ht_node);
5321 	if (gluenode == NULL) {
5322 		/* No cached glue was found in the table. Get new glue. */
5323 		gluenode = new_gluenode(db, version, node, rdataset);
5324 
5325 		struct cds_lfht_node *ht_node = cds_lfht_add_unique(
5326 			version->glue_table, gluenode_hash(gluenode),
5327 			gluenode_match, gluenode, &gluenode->ht_node);
5328 
5329 		if (ht_node != &gluenode->ht_node) {
5330 			free_gluenode_rcu(&gluenode->rcu_head);
5331 
5332 			gluenode = cds_lfht_entry(ht_node, dns_gluenode_t,
5333 						  ht_node);
5334 		}
5335 	}
5336 
5337 	INSIST(gluenode != NULL);
5338 
5339 	dns_glue_t *glue = gluenode->glue;
5340 	isc_statscounter_t counter = dns_gluecachestatscounter_hits_present;
5341 
5342 	if (glue != NULL) {
5343 		/* We have a cached result. Add it to the message and return. */
5344 		addglue_to_message(glue, msg);
5345 	} else {
5346 		counter = dns_gluecachestatscounter_hits_absent;
5347 	}
5348 
5349 	rcu_read_unlock();
5350 
5351 	if (qpdb->gluecachestats != NULL) {
5352 		isc_stats_increment(qpdb->gluecachestats, counter);
5353 	}
5354 }
5355 
5356 static void
5357 setmaxrrperset(dns_db_t *db, uint32_t value) {
5358 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
5359 
5360 	REQUIRE(VALID_QPZONE(qpdb));
5361 
5362 	qpdb->maxrrperset = value;
5363 }
5364 
5365 static void
5366 setmaxtypepername(dns_db_t *db, uint32_t value) {
5367 	qpzonedb_t *qpdb = (qpzonedb_t *)db;
5368 
5369 	REQUIRE(VALID_QPZONE(qpdb));
5370 
5371 	qpdb->maxtypepername = value;
5372 }
5373 
5374 static dns_dbmethods_t qpdb_zonemethods = {
5375 	.destroy = qpdb_destroy,
5376 	.beginload = beginload,
5377 	.endload = endload,
5378 	.currentversion = currentversion,
5379 	.newversion = newversion,
5380 	.attachversion = attachversion,
5381 	.closeversion = closeversion,
5382 	.findnode = findnode,
5383 	.find = find,
5384 	.attachnode = attachnode,
5385 	.detachnode = detachnode,
5386 	.createiterator = createiterator,
5387 	.findrdataset = findrdataset,
5388 	.allrdatasets = allrdatasets,
5389 	.addrdataset = addrdataset,
5390 	.subtractrdataset = subtractrdataset,
5391 	.deleterdataset = deleterdataset,
5392 	.issecure = issecure,
5393 	.nodecount = nodecount,
5394 	.setloop = setloop,
5395 	.getoriginnode = getoriginnode,
5396 	.getnsec3parameters = getnsec3parameters,
5397 	.findnsec3node = findnsec3node,
5398 	.setsigningtime = setsigningtime,
5399 	.getsigningtime = getsigningtime,
5400 	.getsize = getsize,
5401 	.setgluecachestats = setgluecachestats,
5402 	.locknode = locknode,
5403 	.unlocknode = unlocknode,
5404 	.addglue = addglue,
5405 	.deletedata = deletedata,
5406 	.nodefullname = nodefullname,
5407 	.setmaxrrperset = setmaxrrperset,
5408 	.setmaxtypepername = setmaxtypepername,
5409 };
5410 
5411 static void
5412 destroy_qpznode(qpznode_t *node) {
5413 	dns_slabheader_t *current = NULL, *next = NULL;
5414 
5415 	for (current = node->data; current != NULL; current = next) {
5416 		dns_slabheader_t *down = current->down, *down_next = NULL;
5417 
5418 		next = current->next;
5419 
5420 		for (down = current->down; down != NULL; down = down_next) {
5421 			down_next = down->down;
5422 			dns_slabheader_destroy(&down);
5423 		}
5424 
5425 		dns_slabheader_destroy(&current);
5426 	}
5427 
5428 	dns_name_free(&node->name, node->mctx);
5429 	isc_mem_putanddetach(&node->mctx, node, sizeof(qpznode_t));
5430 }
5431 
5432 #if DNS_DB_NODETRACE
5433 ISC_REFCOUNT_STATIC_TRACE_IMPL(qpznode, destroy_qpznode);
5434 #else
5435 ISC_REFCOUNT_STATIC_IMPL(qpznode, destroy_qpznode);
5436 #endif
5437 
5438 static void
5439 qp_attach(void *uctx ISC_ATTR_UNUSED, void *pval,
5440 	  uint32_t ival ISC_ATTR_UNUSED) {
5441 	qpznode_t *data = pval;
5442 	qpznode_ref(data);
5443 }
5444 
5445 static void
5446 qp_detach(void *uctx ISC_ATTR_UNUSED, void *pval,
5447 	  uint32_t ival ISC_ATTR_UNUSED) {
5448 	qpznode_t *data = pval;
5449 	qpznode_detach(&data);
5450 }
5451 
5452 static size_t
5453 qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval,
5454 	   uint32_t ival ISC_ATTR_UNUSED) {
5455 	qpznode_t *data = pval;
5456 	return dns_qpkey_fromname(key, &data->name);
5457 }
5458 
5459 static void
5460 qp_triename(void *uctx ISC_ATTR_UNUSED, char *buf, size_t size) {
5461 	snprintf(buf, size, "QPDB");
5462 }
5463