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(¤t); 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(¤t); 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, ®ion); 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 ®ion, 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, ®ion); 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 ®ion, 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 ®ion, 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(¤t); 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