1 1.1 christos /* $NetBSD: db.c,v 1.1 2024/02/18 20:57:31 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 1.1 christos * 6 1.1 christos * SPDX-License-Identifier: MPL-2.0 7 1.1 christos * 8 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public 9 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this 10 1.1 christos * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 1.1 christos * 12 1.1 christos * See the COPYRIGHT file distributed with this work for additional 13 1.1 christos * information regarding copyright ownership. 14 1.1 christos */ 15 1.1 christos 16 1.1 christos /*! \file */ 17 1.1 christos 18 1.1 christos /*** 19 1.1 christos *** Imports 20 1.1 christos ***/ 21 1.1 christos 22 1.1 christos #include <inttypes.h> 23 1.1 christos #include <stdbool.h> 24 1.1 christos 25 1.1 christos #include <isc/buffer.h> 26 1.1 christos #include <isc/mem.h> 27 1.1 christos #include <isc/once.h> 28 1.1 christos #include <isc/rwlock.h> 29 1.1 christos #include <isc/string.h> 30 1.1 christos #include <isc/util.h> 31 1.1 christos 32 1.1 christos #include <dns/callbacks.h> 33 1.1 christos #include <dns/clientinfo.h> 34 1.1 christos #include <dns/db.h> 35 1.1 christos #include <dns/dbiterator.h> 36 1.1 christos #include <dns/log.h> 37 1.1 christos #include <dns/master.h> 38 1.1 christos #include <dns/rdata.h> 39 1.1 christos #include <dns/rdataset.h> 40 1.1 christos #include <dns/rdatasetiter.h> 41 1.1 christos #include <dns/result.h> 42 1.1 christos 43 1.1 christos /*** 44 1.1 christos *** Private Types 45 1.1 christos ***/ 46 1.1 christos 47 1.1 christos struct dns_dbimplementation { 48 1.1 christos const char *name; 49 1.1 christos dns_dbcreatefunc_t create; 50 1.1 christos isc_mem_t *mctx; 51 1.1 christos void *driverarg; 52 1.1 christos ISC_LINK(dns_dbimplementation_t) link; 53 1.1 christos }; 54 1.1 christos 55 1.1 christos /*** 56 1.1 christos *** Supported DB Implementations Registry 57 1.1 christos ***/ 58 1.1 christos 59 1.1 christos /* 60 1.1 christos * Built in database implementations are registered here. 61 1.1 christos */ 62 1.1 christos 63 1.1 christos #include "rbtdb.h" 64 1.1 christos 65 1.1 christos static ISC_LIST(dns_dbimplementation_t) implementations; 66 1.1 christos static isc_rwlock_t implock; 67 1.1 christos static isc_once_t once = ISC_ONCE_INIT; 68 1.1 christos 69 1.1 christos static dns_dbimplementation_t rbtimp; 70 1.1 christos 71 1.1 christos static void 72 1.1 christos initialize(void) { 73 1.1 christos isc_rwlock_init(&implock, 0, 0); 74 1.1 christos 75 1.1 christos rbtimp.name = "rbt"; 76 1.1 christos rbtimp.create = dns_rbtdb_create; 77 1.1 christos rbtimp.mctx = NULL; 78 1.1 christos rbtimp.driverarg = NULL; 79 1.1 christos ISC_LINK_INIT(&rbtimp, link); 80 1.1 christos 81 1.1 christos ISC_LIST_INIT(implementations); 82 1.1 christos ISC_LIST_APPEND(implementations, &rbtimp, link); 83 1.1 christos } 84 1.1 christos 85 1.1 christos static dns_dbimplementation_t * 86 1.1 christos impfind(const char *name) { 87 1.1 christos dns_dbimplementation_t *imp; 88 1.1 christos 89 1.1 christos for (imp = ISC_LIST_HEAD(implementations); imp != NULL; 90 1.1 christos imp = ISC_LIST_NEXT(imp, link)) 91 1.1 christos { 92 1.1 christos if (strcasecmp(name, imp->name) == 0) { 93 1.1 christos return (imp); 94 1.1 christos } 95 1.1 christos } 96 1.1 christos return (NULL); 97 1.1 christos } 98 1.1 christos 99 1.1 christos /*** 100 1.1 christos *** Basic DB Methods 101 1.1 christos ***/ 102 1.1 christos 103 1.1 christos isc_result_t 104 1.1 christos dns_db_create(isc_mem_t *mctx, const char *db_type, const dns_name_t *origin, 105 1.1 christos dns_dbtype_t type, dns_rdataclass_t rdclass, unsigned int argc, 106 1.1 christos char *argv[], dns_db_t **dbp) { 107 1.1 christos dns_dbimplementation_t *impinfo; 108 1.1 christos 109 1.1 christos RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); 110 1.1 christos 111 1.1 christos /* 112 1.1 christos * Create a new database using implementation 'db_type'. 113 1.1 christos */ 114 1.1 christos 115 1.1 christos REQUIRE(dbp != NULL && *dbp == NULL); 116 1.1 christos REQUIRE(dns_name_isabsolute(origin)); 117 1.1 christos 118 1.1 christos RWLOCK(&implock, isc_rwlocktype_read); 119 1.1 christos impinfo = impfind(db_type); 120 1.1 christos if (impinfo != NULL) { 121 1.1 christos isc_result_t result; 122 1.1 christos result = ((impinfo->create)(mctx, origin, type, rdclass, argc, 123 1.1 christos argv, impinfo->driverarg, dbp)); 124 1.1 christos RWUNLOCK(&implock, isc_rwlocktype_read); 125 1.1 christos return (result); 126 1.1 christos } 127 1.1 christos 128 1.1 christos RWUNLOCK(&implock, isc_rwlocktype_read); 129 1.1 christos 130 1.1 christos isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DB, 131 1.1 christos ISC_LOG_ERROR, "unsupported database type '%s'", db_type); 132 1.1 christos 133 1.1 christos return (ISC_R_NOTFOUND); 134 1.1 christos } 135 1.1 christos 136 1.1 christos void 137 1.1 christos dns_db_attach(dns_db_t *source, dns_db_t **targetp) { 138 1.1 christos /* 139 1.1 christos * Attach *targetp to source. 140 1.1 christos */ 141 1.1 christos 142 1.1 christos REQUIRE(DNS_DB_VALID(source)); 143 1.1 christos REQUIRE(targetp != NULL && *targetp == NULL); 144 1.1 christos 145 1.1 christos (source->methods->attach)(source, targetp); 146 1.1 christos 147 1.1 christos ENSURE(*targetp == source); 148 1.1 christos } 149 1.1 christos 150 1.1 christos void 151 1.1 christos dns_db_detach(dns_db_t **dbp) { 152 1.1 christos /* 153 1.1 christos * Detach *dbp from its database. 154 1.1 christos */ 155 1.1 christos 156 1.1 christos REQUIRE(dbp != NULL); 157 1.1 christos REQUIRE(DNS_DB_VALID(*dbp)); 158 1.1 christos 159 1.1 christos ((*dbp)->methods->detach)(dbp); 160 1.1 christos 161 1.1 christos ENSURE(*dbp == NULL); 162 1.1 christos } 163 1.1 christos 164 1.1 christos bool 165 1.1 christos dns_db_iscache(dns_db_t *db) { 166 1.1 christos /* 167 1.1 christos * Does 'db' have cache semantics? 168 1.1 christos */ 169 1.1 christos 170 1.1 christos REQUIRE(DNS_DB_VALID(db)); 171 1.1 christos 172 1.1 christos if ((db->attributes & DNS_DBATTR_CACHE) != 0) { 173 1.1 christos return (true); 174 1.1 christos } 175 1.1 christos 176 1.1 christos return (false); 177 1.1 christos } 178 1.1 christos 179 1.1 christos bool 180 1.1 christos dns_db_iszone(dns_db_t *db) { 181 1.1 christos /* 182 1.1 christos * Does 'db' have zone semantics? 183 1.1 christos */ 184 1.1 christos 185 1.1 christos REQUIRE(DNS_DB_VALID(db)); 186 1.1 christos 187 1.1 christos if ((db->attributes & (DNS_DBATTR_CACHE | DNS_DBATTR_STUB)) == 0) { 188 1.1 christos return (true); 189 1.1 christos } 190 1.1 christos 191 1.1 christos return (false); 192 1.1 christos } 193 1.1 christos 194 1.1 christos bool 195 1.1 christos dns_db_isstub(dns_db_t *db) { 196 1.1 christos /* 197 1.1 christos * Does 'db' have stub semantics? 198 1.1 christos */ 199 1.1 christos 200 1.1 christos REQUIRE(DNS_DB_VALID(db)); 201 1.1 christos 202 1.1 christos if ((db->attributes & DNS_DBATTR_STUB) != 0) { 203 1.1 christos return (true); 204 1.1 christos } 205 1.1 christos 206 1.1 christos return (false); 207 1.1 christos } 208 1.1 christos 209 1.1 christos bool 210 1.1 christos dns_db_isdnssec(dns_db_t *db) { 211 1.1 christos /* 212 1.1 christos * Is 'db' secure or partially secure? 213 1.1 christos */ 214 1.1 christos 215 1.1 christos REQUIRE(DNS_DB_VALID(db)); 216 1.1 christos REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0); 217 1.1 christos 218 1.1 christos if (db->methods->isdnssec != NULL) { 219 1.1 christos return ((db->methods->isdnssec)(db)); 220 1.1 christos } 221 1.1 christos return ((db->methods->issecure)(db)); 222 1.1 christos } 223 1.1 christos 224 1.1 christos bool 225 1.1 christos dns_db_issecure(dns_db_t *db) { 226 1.1 christos /* 227 1.1 christos * Is 'db' secure? 228 1.1 christos */ 229 1.1 christos 230 1.1 christos REQUIRE(DNS_DB_VALID(db)); 231 1.1 christos REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0); 232 1.1 christos 233 1.1 christos return ((db->methods->issecure)(db)); 234 1.1 christos } 235 1.1 christos 236 1.1 christos bool 237 1.1 christos dns_db_ispersistent(dns_db_t *db) { 238 1.1 christos /* 239 1.1 christos * Is 'db' persistent? 240 1.1 christos */ 241 1.1 christos 242 1.1 christos REQUIRE(DNS_DB_VALID(db)); 243 1.1 christos 244 1.1 christos return ((db->methods->ispersistent)(db)); 245 1.1 christos } 246 1.1 christos 247 1.1 christos dns_name_t * 248 1.1 christos dns_db_origin(dns_db_t *db) { 249 1.1 christos /* 250 1.1 christos * The origin of the database. 251 1.1 christos */ 252 1.1 christos 253 1.1 christos REQUIRE(DNS_DB_VALID(db)); 254 1.1 christos 255 1.1 christos return (&db->origin); 256 1.1 christos } 257 1.1 christos 258 1.1 christos dns_rdataclass_t 259 1.1 christos dns_db_class(dns_db_t *db) { 260 1.1 christos /* 261 1.1 christos * The class of the database. 262 1.1 christos */ 263 1.1 christos 264 1.1 christos REQUIRE(DNS_DB_VALID(db)); 265 1.1 christos 266 1.1 christos return (db->rdclass); 267 1.1 christos } 268 1.1 christos 269 1.1 christos isc_result_t 270 1.1 christos dns_db_beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { 271 1.1 christos /* 272 1.1 christos * Begin loading 'db'. 273 1.1 christos */ 274 1.1 christos 275 1.1 christos REQUIRE(DNS_DB_VALID(db)); 276 1.1 christos REQUIRE(DNS_CALLBACK_VALID(callbacks)); 277 1.1 christos 278 1.1 christos return ((db->methods->beginload)(db, callbacks)); 279 1.1 christos } 280 1.1 christos 281 1.1 christos isc_result_t 282 1.1 christos dns_db_endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { 283 1.1 christos dns_dbonupdatelistener_t *listener; 284 1.1 christos 285 1.1 christos /* 286 1.1 christos * Finish loading 'db'. 287 1.1 christos */ 288 1.1 christos 289 1.1 christos REQUIRE(DNS_DB_VALID(db)); 290 1.1 christos REQUIRE(DNS_CALLBACK_VALID(callbacks)); 291 1.1 christos REQUIRE(callbacks->add_private != NULL); 292 1.1 christos 293 1.1 christos for (listener = ISC_LIST_HEAD(db->update_listeners); listener != NULL; 294 1.1 christos listener = ISC_LIST_NEXT(listener, link)) 295 1.1 christos { 296 1.1 christos listener->onupdate(db, listener->onupdate_arg); 297 1.1 christos } 298 1.1 christos 299 1.1 christos return ((db->methods->endload)(db, callbacks)); 300 1.1 christos } 301 1.1 christos 302 1.1 christos isc_result_t 303 1.1 christos dns_db_load(dns_db_t *db, const char *filename, dns_masterformat_t format, 304 1.1 christos unsigned int options) { 305 1.1 christos isc_result_t result, eresult; 306 1.1 christos dns_rdatacallbacks_t callbacks; 307 1.1 christos 308 1.1 christos /* 309 1.1 christos * Load master file 'filename' into 'db'. 310 1.1 christos */ 311 1.1 christos 312 1.1 christos REQUIRE(DNS_DB_VALID(db)); 313 1.1 christos 314 1.1 christos if ((db->attributes & DNS_DBATTR_CACHE) != 0) { 315 1.1 christos options |= DNS_MASTER_AGETTL; 316 1.1 christos } 317 1.1 christos 318 1.1 christos dns_rdatacallbacks_init(&callbacks); 319 1.1 christos result = dns_db_beginload(db, &callbacks); 320 1.1 christos if (result != ISC_R_SUCCESS) { 321 1.1 christos return (result); 322 1.1 christos } 323 1.1 christos result = dns_master_loadfile(filename, &db->origin, &db->origin, 324 1.1 christos db->rdclass, options, 0, &callbacks, NULL, 325 1.1 christos NULL, db->mctx, format, 0); 326 1.1 christos eresult = dns_db_endload(db, &callbacks); 327 1.1 christos /* 328 1.1 christos * We always call dns_db_endload(), but we only want to return its 329 1.1 christos * result if dns_master_loadfile() succeeded. If dns_master_loadfile() 330 1.1 christos * failed, we want to return the result code it gave us. 331 1.1 christos */ 332 1.1 christos if (eresult != ISC_R_SUCCESS && 333 1.1 christos (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE)) 334 1.1 christos { 335 1.1 christos result = eresult; 336 1.1 christos } 337 1.1 christos 338 1.1 christos return (result); 339 1.1 christos } 340 1.1 christos 341 1.1 christos isc_result_t 342 1.1 christos dns_db_serialize(dns_db_t *db, dns_dbversion_t *version, FILE *file) { 343 1.1 christos REQUIRE(DNS_DB_VALID(db)); 344 1.1 christos if (db->methods->serialize == NULL) { 345 1.1 christos return (ISC_R_NOTIMPLEMENTED); 346 1.1 christos } 347 1.1 christos return ((db->methods->serialize)(db, version, file)); 348 1.1 christos } 349 1.1 christos 350 1.1 christos isc_result_t 351 1.1 christos dns_db_dump(dns_db_t *db, dns_dbversion_t *version, const char *filename) { 352 1.1 christos return ((db->methods->dump)(db, version, filename, 353 1.1 christos dns_masterformat_text)); 354 1.1 christos } 355 1.1 christos 356 1.1 christos /*** 357 1.1 christos *** Version Methods 358 1.1 christos ***/ 359 1.1 christos 360 1.1 christos void 361 1.1 christos dns_db_currentversion(dns_db_t *db, dns_dbversion_t **versionp) { 362 1.1 christos /* 363 1.1 christos * Open the current version for reading. 364 1.1 christos */ 365 1.1 christos 366 1.1 christos REQUIRE(DNS_DB_VALID(db)); 367 1.1 christos REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0); 368 1.1 christos REQUIRE(versionp != NULL && *versionp == NULL); 369 1.1 christos 370 1.1 christos (db->methods->currentversion)(db, versionp); 371 1.1 christos } 372 1.1 christos 373 1.1 christos isc_result_t 374 1.1 christos dns_db_newversion(dns_db_t *db, dns_dbversion_t **versionp) { 375 1.1 christos /* 376 1.1 christos * Open a new version for reading and writing. 377 1.1 christos */ 378 1.1 christos 379 1.1 christos REQUIRE(DNS_DB_VALID(db)); 380 1.1 christos REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0); 381 1.1 christos REQUIRE(versionp != NULL && *versionp == NULL); 382 1.1 christos 383 1.1 christos return ((db->methods->newversion)(db, versionp)); 384 1.1 christos } 385 1.1 christos 386 1.1 christos void 387 1.1 christos dns_db_attachversion(dns_db_t *db, dns_dbversion_t *source, 388 1.1 christos dns_dbversion_t **targetp) { 389 1.1 christos /* 390 1.1 christos * Attach '*targetp' to 'source'. 391 1.1 christos */ 392 1.1 christos 393 1.1 christos REQUIRE(DNS_DB_VALID(db)); 394 1.1 christos REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0); 395 1.1 christos REQUIRE(source != NULL); 396 1.1 christos REQUIRE(targetp != NULL && *targetp == NULL); 397 1.1 christos 398 1.1 christos (db->methods->attachversion)(db, source, targetp); 399 1.1 christos 400 1.1 christos ENSURE(*targetp != NULL); 401 1.1 christos } 402 1.1 christos 403 1.1 christos void 404 1.1 christos dns_db_closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) { 405 1.1 christos dns_dbonupdatelistener_t *listener; 406 1.1 christos 407 1.1 christos /* 408 1.1 christos * Close version '*versionp'. 409 1.1 christos */ 410 1.1 christos 411 1.1 christos REQUIRE(DNS_DB_VALID(db)); 412 1.1 christos REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0); 413 1.1 christos REQUIRE(versionp != NULL && *versionp != NULL); 414 1.1 christos 415 1.1 christos (db->methods->closeversion)(db, versionp, commit); 416 1.1 christos 417 1.1 christos if (commit) { 418 1.1 christos for (listener = ISC_LIST_HEAD(db->update_listeners); 419 1.1 christos listener != NULL; listener = ISC_LIST_NEXT(listener, link)) 420 1.1 christos { 421 1.1 christos listener->onupdate(db, listener->onupdate_arg); 422 1.1 christos } 423 1.1 christos } 424 1.1 christos 425 1.1 christos ENSURE(*versionp == NULL); 426 1.1 christos } 427 1.1 christos 428 1.1 christos /*** 429 1.1 christos *** Node Methods 430 1.1 christos ***/ 431 1.1 christos 432 1.1 christos isc_result_t 433 1.1 christos dns_db_findnode(dns_db_t *db, const dns_name_t *name, bool create, 434 1.1 christos dns_dbnode_t **nodep) { 435 1.1 christos /* 436 1.1 christos * Find the node with name 'name'. 437 1.1 christos */ 438 1.1 christos 439 1.1 christos REQUIRE(DNS_DB_VALID(db)); 440 1.1 christos REQUIRE(nodep != NULL && *nodep == NULL); 441 1.1 christos 442 1.1 christos if (db->methods->findnode != NULL) { 443 1.1 christos return ((db->methods->findnode)(db, name, create, nodep)); 444 1.1 christos } else { 445 1.1 christos return ((db->methods->findnodeext)(db, name, create, NULL, NULL, 446 1.1 christos nodep)); 447 1.1 christos } 448 1.1 christos } 449 1.1 christos 450 1.1 christos isc_result_t 451 1.1 christos dns_db_findnodeext(dns_db_t *db, const dns_name_t *name, bool create, 452 1.1 christos dns_clientinfomethods_t *methods, 453 1.1 christos dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep) { 454 1.1 christos /* 455 1.1 christos * Find the node with name 'name', passing 'arg' to the database 456 1.1 christos * implementation. 457 1.1 christos */ 458 1.1 christos 459 1.1 christos REQUIRE(DNS_DB_VALID(db)); 460 1.1 christos REQUIRE(nodep != NULL && *nodep == NULL); 461 1.1 christos 462 1.1 christos if (db->methods->findnodeext != NULL) { 463 1.1 christos return ((db->methods->findnodeext)(db, name, create, methods, 464 1.1 christos clientinfo, nodep)); 465 1.1 christos } else { 466 1.1 christos return ((db->methods->findnode)(db, name, create, nodep)); 467 1.1 christos } 468 1.1 christos } 469 1.1 christos 470 1.1 christos isc_result_t 471 1.1 christos dns_db_findnsec3node(dns_db_t *db, const dns_name_t *name, bool create, 472 1.1 christos dns_dbnode_t **nodep) { 473 1.1 christos /* 474 1.1 christos * Find the node with name 'name'. 475 1.1 christos */ 476 1.1 christos 477 1.1 christos REQUIRE(DNS_DB_VALID(db)); 478 1.1 christos REQUIRE(nodep != NULL && *nodep == NULL); 479 1.1 christos 480 1.1 christos return ((db->methods->findnsec3node)(db, name, create, nodep)); 481 1.1 christos } 482 1.1 christos 483 1.1 christos isc_result_t 484 1.1 christos dns_db_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, 485 1.1 christos dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, 486 1.1 christos dns_dbnode_t **nodep, dns_name_t *foundname, 487 1.1 christos dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { 488 1.1 christos /* 489 1.1 christos * Find the best match for 'name' and 'type' in version 'version' 490 1.1 christos * of 'db'. 491 1.1 christos */ 492 1.1 christos 493 1.1 christos REQUIRE(DNS_DB_VALID(db)); 494 1.1 christos REQUIRE(type != dns_rdatatype_rrsig); 495 1.1 christos REQUIRE(nodep == NULL || *nodep == NULL); 496 1.1 christos REQUIRE(dns_name_hasbuffer(foundname)); 497 1.1 christos REQUIRE(rdataset == NULL || (DNS_RDATASET_VALID(rdataset) && 498 1.1 christos !dns_rdataset_isassociated(rdataset))); 499 1.1 christos REQUIRE(sigrdataset == NULL || 500 1.1 christos (DNS_RDATASET_VALID(sigrdataset) && 501 1.1 christos !dns_rdataset_isassociated(sigrdataset))); 502 1.1 christos 503 1.1 christos if (db->methods->find != NULL) { 504 1.1 christos return ((db->methods->find)(db, name, version, type, options, 505 1.1 christos now, nodep, foundname, rdataset, 506 1.1 christos sigrdataset)); 507 1.1 christos } else { 508 1.1 christos return ((db->methods->findext)(db, name, version, type, options, 509 1.1 christos now, nodep, foundname, NULL, 510 1.1 christos NULL, rdataset, sigrdataset)); 511 1.1 christos } 512 1.1 christos } 513 1.1 christos 514 1.1 christos isc_result_t 515 1.1 christos dns_db_findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, 516 1.1 christos dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, 517 1.1 christos dns_dbnode_t **nodep, dns_name_t *foundname, 518 1.1 christos dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, 519 1.1 christos dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { 520 1.1 christos /* 521 1.1 christos * Find the best match for 'name' and 'type' in version 'version' 522 1.1 christos * of 'db', passing in 'arg'. 523 1.1 christos */ 524 1.1 christos 525 1.1 christos REQUIRE(DNS_DB_VALID(db)); 526 1.1 christos REQUIRE(type != dns_rdatatype_rrsig); 527 1.1 christos REQUIRE(nodep == NULL || *nodep == NULL); 528 1.1 christos REQUIRE(dns_name_hasbuffer(foundname)); 529 1.1 christos REQUIRE(rdataset == NULL || (DNS_RDATASET_VALID(rdataset) && 530 1.1 christos !dns_rdataset_isassociated(rdataset))); 531 1.1 christos REQUIRE(sigrdataset == NULL || 532 1.1 christos (DNS_RDATASET_VALID(sigrdataset) && 533 1.1 christos !dns_rdataset_isassociated(sigrdataset))); 534 1.1 christos 535 1.1 christos if (db->methods->findext != NULL) { 536 1.1 christos return ((db->methods->findext)( 537 1.1 christos db, name, version, type, options, now, nodep, foundname, 538 1.1 christos methods, clientinfo, rdataset, sigrdataset)); 539 1.1 christos } else { 540 1.1 christos return ((db->methods->find)(db, name, version, type, options, 541 1.1 christos now, nodep, foundname, rdataset, 542 1.1 christos sigrdataset)); 543 1.1 christos } 544 1.1 christos } 545 1.1 christos 546 1.1 christos isc_result_t 547 1.1 christos dns_db_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options, 548 1.1 christos isc_stdtime_t now, dns_dbnode_t **nodep, 549 1.1 christos dns_name_t *foundname, dns_name_t *dcname, 550 1.1 christos dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { 551 1.1 christos /* 552 1.1 christos * Find the deepest known zonecut which encloses 'name' in 'db'. 553 1.1 christos * foundname is the zonecut, dcname is the deepest name we have 554 1.1 christos * in database that is part of queried name. 555 1.1 christos */ 556 1.1 christos 557 1.1 christos REQUIRE(DNS_DB_VALID(db)); 558 1.1 christos REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0); 559 1.1 christos REQUIRE(nodep == NULL || *nodep == NULL); 560 1.1 christos REQUIRE(dns_name_hasbuffer(foundname)); 561 1.1 christos REQUIRE(sigrdataset == NULL || 562 1.1 christos (DNS_RDATASET_VALID(sigrdataset) && 563 1.1 christos !dns_rdataset_isassociated(sigrdataset))); 564 1.1 christos 565 1.1 christos return ((db->methods->findzonecut)(db, name, options, now, nodep, 566 1.1 christos foundname, dcname, rdataset, 567 1.1 christos sigrdataset)); 568 1.1 christos } 569 1.1 christos 570 1.1 christos void 571 1.1 christos dns_db_attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) { 572 1.1 christos /* 573 1.1 christos * Attach *targetp to source. 574 1.1 christos */ 575 1.1 christos 576 1.1 christos REQUIRE(DNS_DB_VALID(db)); 577 1.1 christos REQUIRE(source != NULL); 578 1.1 christos REQUIRE(targetp != NULL && *targetp == NULL); 579 1.1 christos 580 1.1 christos (db->methods->attachnode)(db, source, targetp); 581 1.1 christos } 582 1.1 christos 583 1.1 christos void 584 1.1 christos dns_db_detachnode(dns_db_t *db, dns_dbnode_t **nodep) { 585 1.1 christos /* 586 1.1 christos * Detach *nodep from its node. 587 1.1 christos */ 588 1.1 christos 589 1.1 christos REQUIRE(DNS_DB_VALID(db)); 590 1.1 christos REQUIRE(nodep != NULL && *nodep != NULL); 591 1.1 christos 592 1.1 christos (db->methods->detachnode)(db, nodep); 593 1.1 christos 594 1.1 christos ENSURE(*nodep == NULL); 595 1.1 christos } 596 1.1 christos 597 1.1 christos void 598 1.1 christos dns_db_transfernode(dns_db_t *db, dns_dbnode_t **sourcep, 599 1.1 christos dns_dbnode_t **targetp) { 600 1.1 christos REQUIRE(DNS_DB_VALID(db)); 601 1.1 christos REQUIRE(targetp != NULL && *targetp == NULL); 602 1.1 christos /* 603 1.1 christos * This doesn't check the implementation magic. If we find that 604 1.1 christos * we need such checks in future then this will be done in the 605 1.1 christos * method. 606 1.1 christos */ 607 1.1 christos REQUIRE(sourcep != NULL && *sourcep != NULL); 608 1.1 christos 609 1.1 christos UNUSED(db); 610 1.1 christos 611 1.1 christos if (db->methods->transfernode == NULL) { 612 1.1 christos *targetp = *sourcep; 613 1.1 christos *sourcep = NULL; 614 1.1 christos } else { 615 1.1 christos (db->methods->transfernode)(db, sourcep, targetp); 616 1.1 christos } 617 1.1 christos 618 1.1 christos ENSURE(*sourcep == NULL); 619 1.1 christos } 620 1.1 christos 621 1.1 christos isc_result_t 622 1.1 christos dns_db_expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) { 623 1.1 christos /* 624 1.1 christos * Mark as stale all records at 'node' which expire at or before 'now'. 625 1.1 christos */ 626 1.1 christos 627 1.1 christos REQUIRE(DNS_DB_VALID(db)); 628 1.1 christos REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0); 629 1.1 christos REQUIRE(node != NULL); 630 1.1 christos 631 1.1 christos return ((db->methods->expirenode)(db, node, now)); 632 1.1 christos } 633 1.1 christos 634 1.1 christos void 635 1.1 christos dns_db_printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) { 636 1.1 christos /* 637 1.1 christos * Print a textual representation of the contents of the node to 638 1.1 christos * 'out'. 639 1.1 christos */ 640 1.1 christos 641 1.1 christos REQUIRE(DNS_DB_VALID(db)); 642 1.1 christos REQUIRE(node != NULL); 643 1.1 christos 644 1.1 christos (db->methods->printnode)(db, node, out); 645 1.1 christos } 646 1.1 christos 647 1.1 christos /*** 648 1.1 christos *** DB Iterator Creation 649 1.1 christos ***/ 650 1.1 christos 651 1.1 christos isc_result_t 652 1.1 christos dns_db_createiterator(dns_db_t *db, unsigned int flags, 653 1.1 christos dns_dbiterator_t **iteratorp) { 654 1.1 christos /* 655 1.1 christos * Create an iterator for version 'version' of 'db'. 656 1.1 christos */ 657 1.1 christos 658 1.1 christos REQUIRE(DNS_DB_VALID(db)); 659 1.1 christos REQUIRE(iteratorp != NULL && *iteratorp == NULL); 660 1.1 christos 661 1.1 christos return (db->methods->createiterator(db, flags, iteratorp)); 662 1.1 christos } 663 1.1 christos 664 1.1 christos /*** 665 1.1 christos *** Rdataset Methods 666 1.1 christos ***/ 667 1.1 christos 668 1.1 christos isc_result_t 669 1.1 christos dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 670 1.1 christos dns_rdatatype_t type, dns_rdatatype_t covers, 671 1.1 christos isc_stdtime_t now, dns_rdataset_t *rdataset, 672 1.1 christos dns_rdataset_t *sigrdataset) { 673 1.1 christos REQUIRE(DNS_DB_VALID(db)); 674 1.1 christos REQUIRE(node != NULL); 675 1.1 christos REQUIRE(DNS_RDATASET_VALID(rdataset)); 676 1.1 christos REQUIRE(!dns_rdataset_isassociated(rdataset)); 677 1.1 christos REQUIRE(covers == 0 || type == dns_rdatatype_rrsig); 678 1.1 christos REQUIRE(type != dns_rdatatype_any); 679 1.1 christos REQUIRE(sigrdataset == NULL || 680 1.1 christos (DNS_RDATASET_VALID(sigrdataset) && 681 1.1 christos !dns_rdataset_isassociated(sigrdataset))); 682 1.1 christos 683 1.1 christos return ((db->methods->findrdataset)(db, node, version, type, covers, 684 1.1 christos now, rdataset, sigrdataset)); 685 1.1 christos } 686 1.1 christos 687 1.1 christos isc_result_t 688 1.1 christos dns_db_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 689 1.1 christos unsigned int options, isc_stdtime_t now, 690 1.1 christos dns_rdatasetiter_t **iteratorp) { 691 1.1 christos /* 692 1.1 christos * Make '*iteratorp' an rdataset iteratator for all rdatasets at 693 1.1 christos * 'node' in version 'version' of 'db'. 694 1.1 christos */ 695 1.1 christos 696 1.1 christos REQUIRE(DNS_DB_VALID(db)); 697 1.1 christos REQUIRE(iteratorp != NULL && *iteratorp == NULL); 698 1.1 christos 699 1.1 christos return ((db->methods->allrdatasets)(db, node, version, options, now, 700 1.1 christos iteratorp)); 701 1.1 christos } 702 1.1 christos 703 1.1 christos isc_result_t 704 1.1 christos dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 705 1.1 christos isc_stdtime_t now, dns_rdataset_t *rdataset, 706 1.1 christos unsigned int options, dns_rdataset_t *addedrdataset) { 707 1.1 christos /* 708 1.1 christos * Add 'rdataset' to 'node' in version 'version' of 'db'. 709 1.1 christos */ 710 1.1 christos 711 1.1 christos REQUIRE(DNS_DB_VALID(db)); 712 1.1 christos REQUIRE(node != NULL); 713 1.1 christos REQUIRE(((db->attributes & DNS_DBATTR_CACHE) == 0 && version != NULL) || 714 1.1 christos ((db->attributes & DNS_DBATTR_CACHE) != 0 && version == NULL && 715 1.1 christos (options & DNS_DBADD_MERGE) == 0)); 716 1.1 christos REQUIRE((options & DNS_DBADD_EXACT) == 0 || 717 1.1 christos (options & DNS_DBADD_MERGE) != 0); 718 1.1 christos REQUIRE(DNS_RDATASET_VALID(rdataset)); 719 1.1 christos REQUIRE(dns_rdataset_isassociated(rdataset)); 720 1.1 christos REQUIRE(rdataset->rdclass == db->rdclass); 721 1.1 christos REQUIRE(addedrdataset == NULL || 722 1.1 christos (DNS_RDATASET_VALID(addedrdataset) && 723 1.1 christos !dns_rdataset_isassociated(addedrdataset))); 724 1.1 christos 725 1.1 christos return ((db->methods->addrdataset)(db, node, version, now, rdataset, 726 1.1 christos options, addedrdataset)); 727 1.1 christos } 728 1.1 christos 729 1.1 christos isc_result_t 730 1.1 christos dns_db_subtractrdataset(dns_db_t *db, dns_dbnode_t *node, 731 1.1 christos dns_dbversion_t *version, dns_rdataset_t *rdataset, 732 1.1 christos unsigned int options, dns_rdataset_t *newrdataset) { 733 1.1 christos /* 734 1.1 christos * Remove any rdata in 'rdataset' from 'node' in version 'version' of 735 1.1 christos * 'db'. 736 1.1 christos */ 737 1.1 christos 738 1.1 christos REQUIRE(DNS_DB_VALID(db)); 739 1.1 christos REQUIRE(node != NULL); 740 1.1 christos REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0 && version != NULL); 741 1.1 christos REQUIRE(DNS_RDATASET_VALID(rdataset)); 742 1.1 christos REQUIRE(dns_rdataset_isassociated(rdataset)); 743 1.1 christos REQUIRE(rdataset->rdclass == db->rdclass); 744 1.1 christos REQUIRE(newrdataset == NULL || 745 1.1 christos (DNS_RDATASET_VALID(newrdataset) && 746 1.1 christos !dns_rdataset_isassociated(newrdataset))); 747 1.1 christos 748 1.1 christos return ((db->methods->subtractrdataset)(db, node, version, rdataset, 749 1.1 christos options, newrdataset)); 750 1.1 christos } 751 1.1 christos 752 1.1 christos isc_result_t 753 1.1 christos dns_db_deleterdataset(dns_db_t *db, dns_dbnode_t *node, 754 1.1 christos dns_dbversion_t *version, dns_rdatatype_t type, 755 1.1 christos dns_rdatatype_t covers) { 756 1.1 christos /* 757 1.1 christos * Make it so that no rdataset of type 'type' exists at 'node' in 758 1.1 christos * version version 'version' of 'db'. 759 1.1 christos */ 760 1.1 christos 761 1.1 christos REQUIRE(DNS_DB_VALID(db)); 762 1.1 christos REQUIRE(node != NULL); 763 1.1 christos REQUIRE(((db->attributes & DNS_DBATTR_CACHE) == 0 && version != NULL) || 764 1.1 christos ((db->attributes & DNS_DBATTR_CACHE) != 0 && version == NULL)); 765 1.1 christos 766 1.1 christos return ((db->methods->deleterdataset)(db, node, version, type, covers)); 767 1.1 christos } 768 1.1 christos 769 1.1 christos void 770 1.1 christos dns_db_overmem(dns_db_t *db, bool overmem) { 771 1.1 christos REQUIRE(DNS_DB_VALID(db)); 772 1.1 christos 773 1.1 christos (db->methods->overmem)(db, overmem); 774 1.1 christos } 775 1.1 christos 776 1.1 christos isc_result_t 777 1.1 christos dns_db_getsoaserial(dns_db_t *db, dns_dbversion_t *ver, uint32_t *serialp) { 778 1.1 christos isc_result_t result; 779 1.1 christos dns_dbnode_t *node = NULL; 780 1.1 christos dns_rdataset_t rdataset; 781 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 782 1.1 christos isc_buffer_t buffer; 783 1.1 christos 784 1.1 christos REQUIRE(dns_db_iszone(db) || dns_db_isstub(db)); 785 1.1 christos 786 1.1 christos result = dns_db_findnode(db, dns_db_origin(db), false, &node); 787 1.1 christos if (result != ISC_R_SUCCESS) { 788 1.1 christos return (result); 789 1.1 christos } 790 1.1 christos 791 1.1 christos dns_rdataset_init(&rdataset); 792 1.1 christos result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa, 0, 793 1.1 christos (isc_stdtime_t)0, &rdataset, NULL); 794 1.1 christos if (result != ISC_R_SUCCESS) { 795 1.1 christos goto freenode; 796 1.1 christos } 797 1.1 christos 798 1.1 christos result = dns_rdataset_first(&rdataset); 799 1.1 christos if (result != ISC_R_SUCCESS) { 800 1.1 christos goto freerdataset; 801 1.1 christos } 802 1.1 christos dns_rdataset_current(&rdataset, &rdata); 803 1.1 christos result = dns_rdataset_next(&rdataset); 804 1.1 christos INSIST(result == ISC_R_NOMORE); 805 1.1 christos 806 1.1 christos INSIST(rdata.length > 20); 807 1.1 christos isc_buffer_init(&buffer, rdata.data, rdata.length); 808 1.1 christos isc_buffer_add(&buffer, rdata.length); 809 1.1 christos isc_buffer_forward(&buffer, rdata.length - 20); 810 1.1 christos *serialp = isc_buffer_getuint32(&buffer); 811 1.1 christos 812 1.1 christos result = ISC_R_SUCCESS; 813 1.1 christos 814 1.1 christos freerdataset: 815 1.1 christos dns_rdataset_disassociate(&rdataset); 816 1.1 christos 817 1.1 christos freenode: 818 1.1 christos dns_db_detachnode(db, &node); 819 1.1 christos return (result); 820 1.1 christos } 821 1.1 christos 822 1.1 christos unsigned int 823 1.1 christos dns_db_nodecount(dns_db_t *db) { 824 1.1 christos REQUIRE(DNS_DB_VALID(db)); 825 1.1 christos 826 1.1 christos return ((db->methods->nodecount)(db)); 827 1.1 christos } 828 1.1 christos 829 1.1 christos size_t 830 1.1 christos dns_db_hashsize(dns_db_t *db) { 831 1.1 christos REQUIRE(DNS_DB_VALID(db)); 832 1.1 christos 833 1.1 christos if (db->methods->hashsize == NULL) { 834 1.1 christos return (0); 835 1.1 christos } 836 1.1 christos 837 1.1 christos return ((db->methods->hashsize)(db)); 838 1.1 christos } 839 1.1 christos 840 1.1 christos isc_result_t 841 1.1 christos dns_db_adjusthashsize(dns_db_t *db, size_t size) { 842 1.1 christos REQUIRE(DNS_DB_VALID(db)); 843 1.1 christos 844 1.1 christos if (db->methods->adjusthashsize != NULL) { 845 1.1 christos return ((db->methods->adjusthashsize)(db, size)); 846 1.1 christos } 847 1.1 christos 848 1.1 christos return (ISC_R_NOTIMPLEMENTED); 849 1.1 christos } 850 1.1 christos 851 1.1 christos void 852 1.1 christos dns_db_settask(dns_db_t *db, isc_task_t *task) { 853 1.1 christos REQUIRE(DNS_DB_VALID(db)); 854 1.1 christos 855 1.1 christos (db->methods->settask)(db, task); 856 1.1 christos } 857 1.1 christos 858 1.1 christos isc_result_t 859 1.1 christos dns_db_register(const char *name, dns_dbcreatefunc_t create, void *driverarg, 860 1.1 christos isc_mem_t *mctx, dns_dbimplementation_t **dbimp) { 861 1.1 christos dns_dbimplementation_t *imp; 862 1.1 christos 863 1.1 christos REQUIRE(name != NULL); 864 1.1 christos REQUIRE(dbimp != NULL && *dbimp == NULL); 865 1.1 christos 866 1.1 christos RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); 867 1.1 christos 868 1.1 christos RWLOCK(&implock, isc_rwlocktype_write); 869 1.1 christos imp = impfind(name); 870 1.1 christos if (imp != NULL) { 871 1.1 christos RWUNLOCK(&implock, isc_rwlocktype_write); 872 1.1 christos return (ISC_R_EXISTS); 873 1.1 christos } 874 1.1 christos 875 1.1 christos imp = isc_mem_get(mctx, sizeof(dns_dbimplementation_t)); 876 1.1 christos imp->name = name; 877 1.1 christos imp->create = create; 878 1.1 christos imp->mctx = NULL; 879 1.1 christos imp->driverarg = driverarg; 880 1.1 christos isc_mem_attach(mctx, &imp->mctx); 881 1.1 christos ISC_LINK_INIT(imp, link); 882 1.1 christos ISC_LIST_APPEND(implementations, imp, link); 883 1.1 christos RWUNLOCK(&implock, isc_rwlocktype_write); 884 1.1 christos 885 1.1 christos *dbimp = imp; 886 1.1 christos 887 1.1 christos return (ISC_R_SUCCESS); 888 1.1 christos } 889 1.1 christos 890 1.1 christos void 891 1.1 christos dns_db_unregister(dns_dbimplementation_t **dbimp) { 892 1.1 christos dns_dbimplementation_t *imp; 893 1.1 christos 894 1.1 christos REQUIRE(dbimp != NULL && *dbimp != NULL); 895 1.1 christos 896 1.1 christos RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); 897 1.1 christos 898 1.1 christos imp = *dbimp; 899 1.1 christos *dbimp = NULL; 900 1.1 christos RWLOCK(&implock, isc_rwlocktype_write); 901 1.1 christos ISC_LIST_UNLINK(implementations, imp, link); 902 1.1 christos isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_dbimplementation_t)); 903 1.1 christos RWUNLOCK(&implock, isc_rwlocktype_write); 904 1.1 christos ENSURE(*dbimp == NULL); 905 1.1 christos } 906 1.1 christos 907 1.1 christos isc_result_t 908 1.1 christos dns_db_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) { 909 1.1 christos REQUIRE(DNS_DB_VALID(db)); 910 1.1 christos REQUIRE(dns_db_iszone(db)); 911 1.1 christos REQUIRE(nodep != NULL && *nodep == NULL); 912 1.1 christos 913 1.1 christos if (db->methods->getoriginnode != NULL) { 914 1.1 christos return ((db->methods->getoriginnode)(db, nodep)); 915 1.1 christos } 916 1.1 christos 917 1.1 christos return (ISC_R_NOTFOUND); 918 1.1 christos } 919 1.1 christos 920 1.1 christos dns_stats_t * 921 1.1 christos dns_db_getrrsetstats(dns_db_t *db) { 922 1.1 christos REQUIRE(DNS_DB_VALID(db)); 923 1.1 christos 924 1.1 christos if (db->methods->getrrsetstats != NULL) { 925 1.1 christos return ((db->methods->getrrsetstats)(db)); 926 1.1 christos } 927 1.1 christos 928 1.1 christos return (NULL); 929 1.1 christos } 930 1.1 christos 931 1.1 christos isc_result_t 932 1.1 christos dns_db_setcachestats(dns_db_t *db, isc_stats_t *stats) { 933 1.1 christos REQUIRE(DNS_DB_VALID(db)); 934 1.1 christos 935 1.1 christos if (db->methods->setcachestats != NULL) { 936 1.1 christos return ((db->methods->setcachestats)(db, stats)); 937 1.1 christos } 938 1.1 christos 939 1.1 christos return (ISC_R_NOTIMPLEMENTED); 940 1.1 christos } 941 1.1 christos 942 1.1 christos isc_result_t 943 1.1 christos dns_db_getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, 944 1.1 christos dns_hash_t *hash, uint8_t *flags, 945 1.1 christos uint16_t *iterations, unsigned char *salt, 946 1.1 christos size_t *salt_length) { 947 1.1 christos REQUIRE(DNS_DB_VALID(db)); 948 1.1 christos REQUIRE(dns_db_iszone(db)); 949 1.1 christos 950 1.1 christos if (db->methods->getnsec3parameters != NULL) { 951 1.1 christos return ((db->methods->getnsec3parameters)(db, version, hash, 952 1.1 christos flags, iterations, 953 1.1 christos salt, salt_length)); 954 1.1 christos } 955 1.1 christos 956 1.1 christos return (ISC_R_NOTFOUND); 957 1.1 christos } 958 1.1 christos 959 1.1 christos isc_result_t 960 1.1 christos dns_db_getsize(dns_db_t *db, dns_dbversion_t *version, uint64_t *records, 961 1.1 christos uint64_t *bytes) { 962 1.1 christos REQUIRE(DNS_DB_VALID(db)); 963 1.1 christos REQUIRE(dns_db_iszone(db)); 964 1.1 christos 965 1.1 christos if (db->methods->getsize != NULL) { 966 1.1 christos return ((db->methods->getsize)(db, version, records, bytes)); 967 1.1 christos } 968 1.1 christos 969 1.1 christos return (ISC_R_NOTFOUND); 970 1.1 christos } 971 1.1 christos 972 1.1 christos isc_result_t 973 1.1 christos dns_db_setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, 974 1.1 christos isc_stdtime_t resign) { 975 1.1 christos if (db->methods->setsigningtime != NULL) { 976 1.1 christos return ((db->methods->setsigningtime)(db, rdataset, resign)); 977 1.1 christos } 978 1.1 christos return (ISC_R_NOTIMPLEMENTED); 979 1.1 christos } 980 1.1 christos 981 1.1 christos isc_result_t 982 1.1 christos dns_db_getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, 983 1.1 christos dns_name_t *name) { 984 1.1 christos if (db->methods->getsigningtime != NULL) { 985 1.1 christos return ((db->methods->getsigningtime)(db, rdataset, name)); 986 1.1 christos } 987 1.1 christos return (ISC_R_NOTFOUND); 988 1.1 christos } 989 1.1 christos 990 1.1 christos void 991 1.1 christos dns_db_resigned(dns_db_t *db, dns_rdataset_t *rdataset, 992 1.1 christos dns_dbversion_t *version) { 993 1.1 christos if (db->methods->resigned != NULL) { 994 1.1 christos (db->methods->resigned)(db, rdataset, version); 995 1.1 christos } 996 1.1 christos } 997 1.1 christos 998 1.1 christos /* 999 1.1 christos * Attach a database to policy zone databases. 1000 1.1 christos * This should only happen when the caller has already ensured that 1001 1.1 christos * it is dealing with a database that understands response policy zones. 1002 1.1 christos */ 1003 1.1 christos void 1004 1.1 christos dns_db_rpz_attach(dns_db_t *db, void *rpzs, uint8_t rpz_num) { 1005 1.1 christos REQUIRE(db->methods->rpz_attach != NULL); 1006 1.1 christos (db->methods->rpz_attach)(db, rpzs, rpz_num); 1007 1.1 christos } 1008 1.1 christos 1009 1.1 christos /* 1010 1.1 christos * Finish loading a response policy zone. 1011 1.1 christos */ 1012 1.1 christos isc_result_t 1013 1.1 christos dns_db_rpz_ready(dns_db_t *db) { 1014 1.1 christos if (db->methods->rpz_ready == NULL) { 1015 1.1 christos return (ISC_R_SUCCESS); 1016 1.1 christos } 1017 1.1 christos return ((db->methods->rpz_ready)(db)); 1018 1.1 christos } 1019 1.1 christos 1020 1.1 christos /* 1021 1.1 christos * Attach a notify-on-update function the database 1022 1.1 christos */ 1023 1.1 christos isc_result_t 1024 1.1 christos dns_db_updatenotify_register(dns_db_t *db, dns_dbupdate_callback_t fn, 1025 1.1 christos void *fn_arg) { 1026 1.1 christos dns_dbonupdatelistener_t *listener; 1027 1.1 christos 1028 1.1 christos REQUIRE(db != NULL); 1029 1.1 christos REQUIRE(fn != NULL); 1030 1.1 christos 1031 1.1 christos for (listener = ISC_LIST_HEAD(db->update_listeners); listener != NULL; 1032 1.1 christos listener = ISC_LIST_NEXT(listener, link)) 1033 1.1 christos { 1034 1.1 christos if ((listener->onupdate == fn) && 1035 1.1 christos (listener->onupdate_arg == fn_arg)) 1036 1.1 christos { 1037 1.1 christos return (ISC_R_SUCCESS); 1038 1.1 christos } 1039 1.1 christos } 1040 1.1 christos 1041 1.1 christos listener = isc_mem_get(db->mctx, sizeof(dns_dbonupdatelistener_t)); 1042 1.1 christos 1043 1.1 christos listener->onupdate = fn; 1044 1.1 christos listener->onupdate_arg = fn_arg; 1045 1.1 christos 1046 1.1 christos ISC_LINK_INIT(listener, link); 1047 1.1 christos ISC_LIST_APPEND(db->update_listeners, listener, link); 1048 1.1 christos 1049 1.1 christos return (ISC_R_SUCCESS); 1050 1.1 christos } 1051 1.1 christos 1052 1.1 christos isc_result_t 1053 1.1 christos dns_db_updatenotify_unregister(dns_db_t *db, dns_dbupdate_callback_t fn, 1054 1.1 christos void *fn_arg) { 1055 1.1 christos dns_dbonupdatelistener_t *listener; 1056 1.1 christos 1057 1.1 christos REQUIRE(db != NULL); 1058 1.1 christos 1059 1.1 christos for (listener = ISC_LIST_HEAD(db->update_listeners); listener != NULL; 1060 1.1 christos listener = ISC_LIST_NEXT(listener, link)) 1061 1.1 christos { 1062 1.1 christos if ((listener->onupdate == fn) && 1063 1.1 christos (listener->onupdate_arg == fn_arg)) 1064 1.1 christos { 1065 1.1 christos ISC_LIST_UNLINK(db->update_listeners, listener, link); 1066 1.1 christos isc_mem_put(db->mctx, listener, 1067 1.1 christos sizeof(dns_dbonupdatelistener_t)); 1068 1.1 christos return (ISC_R_SUCCESS); 1069 1.1 christos } 1070 1.1 christos } 1071 1.1 christos 1072 1.1 christos return (ISC_R_NOTFOUND); 1073 1.1 christos } 1074 1.1 christos 1075 1.1 christos isc_result_t 1076 1.1 christos dns_db_nodefullname(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name) { 1077 1.1 christos REQUIRE(db != NULL); 1078 1.1 christos REQUIRE(node != NULL); 1079 1.1 christos REQUIRE(name != NULL); 1080 1.1 christos 1081 1.1 christos if (db->methods->nodefullname == NULL) { 1082 1.1 christos return (ISC_R_NOTIMPLEMENTED); 1083 1.1 christos } 1084 1.1 christos return ((db->methods->nodefullname)(db, node, name)); 1085 1.1 christos } 1086 1.1 christos 1087 1.1 christos isc_result_t 1088 1.1 christos dns_db_setservestalettl(dns_db_t *db, dns_ttl_t ttl) { 1089 1.1 christos REQUIRE(DNS_DB_VALID(db)); 1090 1.1 christos REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0); 1091 1.1 christos 1092 1.1 christos if (db->methods->setservestalettl != NULL) { 1093 1.1 christos return ((db->methods->setservestalettl)(db, ttl)); 1094 1.1 christos } 1095 1.1 christos return (ISC_R_NOTIMPLEMENTED); 1096 1.1 christos } 1097 1.1 christos 1098 1.1 christos isc_result_t 1099 1.1 christos dns_db_getservestalettl(dns_db_t *db, dns_ttl_t *ttl) { 1100 1.1 christos REQUIRE(DNS_DB_VALID(db)); 1101 1.1 christos REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0); 1102 1.1 christos 1103 1.1 christos if (db->methods->getservestalettl != NULL) { 1104 1.1 christos return ((db->methods->getservestalettl)(db, ttl)); 1105 1.1 christos } 1106 1.1 christos return (ISC_R_NOTIMPLEMENTED); 1107 1.1 christos } 1108 1.1 christos 1109 1.1 christos isc_result_t 1110 1.1 christos dns_db_setservestalerefresh(dns_db_t *db, uint32_t interval) { 1111 1.1 christos REQUIRE(DNS_DB_VALID(db)); 1112 1.1 christos REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0); 1113 1.1 christos 1114 1.1 christos if (db->methods->setservestalerefresh != NULL) { 1115 1.1 christos return ((db->methods->setservestalerefresh)(db, interval)); 1116 1.1 christos } 1117 1.1 christos return (ISC_R_NOTIMPLEMENTED); 1118 1.1 christos } 1119 1.1 christos 1120 1.1 christos isc_result_t 1121 1.1 christos dns_db_getservestalerefresh(dns_db_t *db, uint32_t *interval) { 1122 1.1 christos REQUIRE(DNS_DB_VALID(db)); 1123 1.1 christos REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0); 1124 1.1 christos 1125 1.1 christos if (db->methods->getservestalerefresh != NULL) { 1126 1.1 christos return ((db->methods->getservestalerefresh)(db, interval)); 1127 1.1 christos } 1128 1.1 christos return (ISC_R_NOTIMPLEMENTED); 1129 1.1 christos } 1130 1.1 christos 1131 1.1 christos isc_result_t 1132 1.1 christos dns_db_setgluecachestats(dns_db_t *db, isc_stats_t *stats) { 1133 1.1 christos REQUIRE(dns_db_iszone(db)); 1134 1.1 christos REQUIRE(stats != NULL); 1135 1.1 christos 1136 1.1 christos if (db->methods->setgluecachestats != NULL) { 1137 1.1 christos return ((db->methods->setgluecachestats)(db, stats)); 1138 1.1 christos } 1139 1.1 christos 1140 1.1 christos return (ISC_R_NOTIMPLEMENTED); 1141 1.1 christos } 1142