1 /* $NetBSD: sdlz.c,v 1.14 2025/01/26 16:25:25 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 AND ISC 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 /* 17 * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl. 18 * 19 * Permission to use, copy, modify, and distribute this software for any 20 * purpose with or without fee is hereby granted, provided that the 21 * above copyright notice and this permission notice appear in all 22 * copies. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET 25 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 27 * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 28 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 29 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 30 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE 31 * USE OR PERFORMANCE OF THIS SOFTWARE. 32 * 33 * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was 34 * conceived and contributed by Rob Butler. 35 * 36 * Permission to use, copy, modify, and distribute this software for any 37 * purpose with or without fee is hereby granted, provided that the 38 * above copyright notice and this permission notice appear in all 39 * copies. 40 * 41 * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER 42 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 44 * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 45 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 46 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 47 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE 48 * USE OR PERFORMANCE OF THIS SOFTWARE. 49 */ 50 51 /*! \file */ 52 53 #include <inttypes.h> 54 #include <stdbool.h> 55 #include <string.h> 56 57 #include <isc/ascii.h> 58 #include <isc/buffer.h> 59 #include <isc/lex.h> 60 #include <isc/log.h> 61 #include <isc/magic.h> 62 #include <isc/mem.h> 63 #include <isc/once.h> 64 #include <isc/region.h> 65 #include <isc/result.h> 66 #include <isc/rwlock.h> 67 #include <isc/string.h> 68 #include <isc/util.h> 69 70 #include <dns/callbacks.h> 71 #include <dns/db.h> 72 #include <dns/dbiterator.h> 73 #include <dns/dlz.h> 74 #include <dns/fixedname.h> 75 #include <dns/log.h> 76 #include <dns/master.h> 77 #include <dns/rdata.h> 78 #include <dns/rdatalist.h> 79 #include <dns/rdataset.h> 80 #include <dns/rdatasetiter.h> 81 #include <dns/rdatatype.h> 82 #include <dns/sdlz.h> 83 #include <dns/types.h> 84 85 /* 86 * Private Types 87 */ 88 89 struct dns_sdlzimplementation { 90 const dns_sdlzmethods_t *methods; 91 isc_mem_t *mctx; 92 void *driverarg; 93 unsigned int flags; 94 isc_mutex_t driverlock; 95 dns_dlzimplementation_t *dlz_imp; 96 }; 97 98 struct dns_sdlz_db { 99 /* Unlocked */ 100 dns_db_t common; 101 void *dbdata; 102 dns_sdlzimplementation_t *dlzimp; 103 104 /* Locked */ 105 dns_dbversion_t *future_version; 106 int dummy_version; 107 }; 108 109 struct dns_sdlzlookup { 110 /* Unlocked */ 111 unsigned int magic; 112 dns_sdlz_db_t *sdlz; 113 ISC_LIST(dns_rdatalist_t) lists; 114 ISC_LIST(isc_buffer_t) buffers; 115 dns_name_t *name; 116 ISC_LINK(dns_sdlzlookup_t) link; 117 dns_rdatacallbacks_t callbacks; 118 119 /* Atomic */ 120 isc_refcount_t references; 121 }; 122 123 typedef struct dns_sdlzlookup dns_sdlznode_t; 124 125 struct dns_sdlzallnodes { 126 dns_dbiterator_t common; 127 ISC_LIST(dns_sdlznode_t) nodelist; 128 dns_sdlznode_t *current; 129 dns_sdlznode_t *origin; 130 }; 131 132 typedef dns_sdlzallnodes_t sdlz_dbiterator_t; 133 134 typedef struct sdlz_rdatasetiter { 135 dns_rdatasetiter_t common; 136 dns_rdatalist_t *current; 137 } sdlz_rdatasetiter_t; 138 139 #define SDLZDB_MAGIC ISC_MAGIC('D', 'L', 'Z', 'S') 140 141 /* 142 * Note that "impmagic" is not the first four bytes of the struct, so 143 * ISC_MAGIC_VALID cannot be used. 144 */ 145 146 #define VALID_SDLZDB(sdlzdb) \ 147 ((sdlzdb) != NULL && (sdlzdb)->common.impmagic == SDLZDB_MAGIC) 148 149 #define SDLZLOOKUP_MAGIC ISC_MAGIC('D', 'L', 'Z', 'L') 150 #define VALID_SDLZLOOKUP(sdlzl) ISC_MAGIC_VALID(sdlzl, SDLZLOOKUP_MAGIC) 151 #define VALID_SDLZNODE(sdlzn) VALID_SDLZLOOKUP(sdlzn) 152 153 /* These values are taken from RFC 1537 */ 154 #define SDLZ_DEFAULT_REFRESH 28800U /* 8 hours */ 155 #define SDLZ_DEFAULT_RETRY 7200U /* 2 hours */ 156 #define SDLZ_DEFAULT_EXPIRE 604800U /* 7 days */ 157 #define SDLZ_DEFAULT_MINIMUM 86400U /* 1 day */ 158 159 /* This is a reasonable value */ 160 #define SDLZ_DEFAULT_TTL (60 * 60 * 24) 161 162 #ifdef __COVERITY__ 163 #define MAYBE_LOCK(imp) LOCK(&imp->driverlock) 164 #define MAYBE_UNLOCK(imp) UNLOCK(&imp->driverlock) 165 #else /* ifdef __COVERITY__ */ 166 #define MAYBE_LOCK(imp) \ 167 do { \ 168 unsigned int flags = imp->flags; \ 169 if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \ 170 LOCK(&imp->driverlock); \ 171 } while (0) 172 173 #define MAYBE_UNLOCK(imp) \ 174 do { \ 175 unsigned int flags = imp->flags; \ 176 if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \ 177 UNLOCK(&imp->driverlock); \ 178 } while (0) 179 #endif /* ifdef __COVERITY__ */ 180 181 /* 182 * Forward references. 183 */ 184 static isc_result_t 185 getnodedata(dns_db_t *db, const dns_name_t *name, bool create, 186 unsigned int options, dns_clientinfomethods_t *methods, 187 dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep); 188 189 static void 190 list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node, 191 dns_rdataset_t *rdataset); 192 193 static void 194 detachnode(dns_db_t *db, dns_dbnode_t **targetp DNS__DB_FLARG); 195 196 static void 197 dbiterator_destroy(dns_dbiterator_t **iteratorp DNS__DB_FLARG); 198 static isc_result_t 199 dbiterator_first(dns_dbiterator_t *iterator DNS__DB_FLARG); 200 static isc_result_t 201 dbiterator_last(dns_dbiterator_t *iterator DNS__DB_FLARG); 202 static isc_result_t 203 dbiterator_seek(dns_dbiterator_t *iterator, 204 const dns_name_t *name DNS__DB_FLARG); 205 static isc_result_t 206 dbiterator_prev(dns_dbiterator_t *iterator DNS__DB_FLARG); 207 static isc_result_t 208 dbiterator_next(dns_dbiterator_t *iterator DNS__DB_FLARG); 209 static isc_result_t 210 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, 211 dns_name_t *name DNS__DB_FLARG); 212 static isc_result_t 213 dbiterator_pause(dns_dbiterator_t *iterator); 214 static isc_result_t 215 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name); 216 217 static dns_dbiteratormethods_t dbiterator_methods = { 218 dbiterator_destroy, dbiterator_first, dbiterator_last, 219 dbiterator_seek, dbiterator_prev, dbiterator_next, 220 dbiterator_current, dbiterator_pause, dbiterator_origin 221 }; 222 223 /* 224 * Utility functions 225 */ 226 227 /* 228 * Log a message at the given level 229 */ 230 static void 231 sdlz_log(int level, const char *fmt, ...) { 232 va_list ap; 233 va_start(ap, fmt); 234 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, 235 ISC_LOG_DEBUG(level), fmt, ap); 236 va_end(ap); 237 } 238 239 static unsigned int 240 initial_size(const char *data) { 241 unsigned int len = (strlen(data) / 64) + 1; 242 return len * 64 + 64; 243 } 244 245 /* 246 * Rdataset Iterator Methods. These methods were "borrowed" from the SDB 247 * driver interface. See the SDB driver interface documentation for more info. 248 */ 249 250 static void 251 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp DNS__DB_FLARG) { 252 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)(*iteratorp); 253 254 detachnode(sdlziterator->common.db, 255 &sdlziterator->common.node DNS__DB_FLARG_PASS); 256 isc_mem_put(sdlziterator->common.db->mctx, sdlziterator, 257 sizeof(sdlz_rdatasetiter_t)); 258 *iteratorp = NULL; 259 } 260 261 static isc_result_t 262 rdatasetiter_first(dns_rdatasetiter_t *iterator DNS__DB_FLARG) { 263 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator; 264 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)iterator->node; 265 266 if (ISC_LIST_EMPTY(sdlznode->lists)) { 267 return ISC_R_NOMORE; 268 } 269 sdlziterator->current = ISC_LIST_HEAD(sdlznode->lists); 270 return ISC_R_SUCCESS; 271 } 272 273 static isc_result_t 274 rdatasetiter_next(dns_rdatasetiter_t *iterator DNS__DB_FLARG) { 275 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator; 276 277 sdlziterator->current = ISC_LIST_NEXT(sdlziterator->current, link); 278 if (sdlziterator->current == NULL) { 279 return ISC_R_NOMORE; 280 } else { 281 return ISC_R_SUCCESS; 282 } 283 } 284 285 static void 286 rdatasetiter_current(dns_rdatasetiter_t *iterator, 287 dns_rdataset_t *rdataset DNS__DB_FLARG) { 288 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator; 289 290 list_tordataset(sdlziterator->current, iterator->db, iterator->node, 291 rdataset); 292 } 293 294 static dns_rdatasetitermethods_t rdatasetiter_methods = { 295 rdatasetiter_destroy, rdatasetiter_first, rdatasetiter_next, 296 rdatasetiter_current 297 }; 298 299 /* 300 * DB routines. These methods were "borrowed" from the SDB driver interface. 301 * See the SDB driver interface documentation for more info. 302 */ 303 304 static void 305 destroy(dns_db_t *db) { 306 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 307 308 sdlz->common.magic = 0; 309 sdlz->common.impmagic = 0; 310 311 dns_name_free(&sdlz->common.origin, sdlz->common.mctx); 312 313 isc_refcount_destroy(&sdlz->common.references); 314 isc_mem_putanddetach(&sdlz->common.mctx, sdlz, sizeof(dns_sdlz_db_t)); 315 } 316 317 static void 318 currentversion(dns_db_t *db, dns_dbversion_t **versionp) { 319 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 320 REQUIRE(VALID_SDLZDB(sdlz)); 321 REQUIRE(versionp != NULL && *versionp == NULL); 322 323 *versionp = (void *)&sdlz->dummy_version; 324 return; 325 } 326 327 static isc_result_t 328 newversion(dns_db_t *db, dns_dbversion_t **versionp) { 329 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 330 char origin[DNS_NAME_MAXTEXT + 1]; 331 isc_result_t result; 332 333 REQUIRE(VALID_SDLZDB(sdlz)); 334 335 if (sdlz->dlzimp->methods->newversion == NULL) { 336 return ISC_R_NOTIMPLEMENTED; 337 } 338 339 dns_name_format(&sdlz->common.origin, origin, sizeof(origin)); 340 341 result = sdlz->dlzimp->methods->newversion( 342 origin, sdlz->dlzimp->driverarg, sdlz->dbdata, versionp); 343 if (result != ISC_R_SUCCESS) { 344 sdlz_log(ISC_LOG_ERROR, 345 "sdlz newversion on origin %s failed : %s", origin, 346 isc_result_totext(result)); 347 return result; 348 } 349 350 sdlz->future_version = *versionp; 351 return ISC_R_SUCCESS; 352 } 353 354 static void 355 attachversion(dns_db_t *db, dns_dbversion_t *source, 356 dns_dbversion_t **targetp) { 357 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 358 359 REQUIRE(VALID_SDLZDB(sdlz)); 360 REQUIRE(source != NULL && source == (void *)&sdlz->dummy_version); 361 362 *targetp = source; 363 } 364 365 static void 366 closeversion(dns_db_t *db, dns_dbversion_t **versionp, 367 bool commit DNS__DB_FLARG) { 368 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 369 char origin[DNS_NAME_MAXTEXT + 1]; 370 371 REQUIRE(VALID_SDLZDB(sdlz)); 372 REQUIRE(versionp != NULL); 373 374 if (*versionp == (void *)&sdlz->dummy_version) { 375 *versionp = NULL; 376 return; 377 } 378 379 REQUIRE(*versionp == sdlz->future_version); 380 REQUIRE(sdlz->dlzimp->methods->closeversion != NULL); 381 382 dns_name_format(&sdlz->common.origin, origin, sizeof(origin)); 383 384 sdlz->dlzimp->methods->closeversion(origin, commit, 385 sdlz->dlzimp->driverarg, 386 sdlz->dbdata, versionp); 387 if (*versionp != NULL) { 388 sdlz_log(ISC_LOG_ERROR, "sdlz closeversion on origin %s failed", 389 origin); 390 } 391 392 sdlz->future_version = NULL; 393 } 394 395 static isc_result_t 396 createnode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) { 397 dns_sdlznode_t *node; 398 399 node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t)); 400 401 node->sdlz = NULL; 402 dns_db_attach((dns_db_t *)sdlz, (dns_db_t **)&node->sdlz); 403 ISC_LIST_INIT(node->lists); 404 ISC_LIST_INIT(node->buffers); 405 ISC_LINK_INIT(node, link); 406 node->name = NULL; 407 dns_rdatacallbacks_init(&node->callbacks); 408 409 isc_refcount_init(&node->references, 1); 410 node->magic = SDLZLOOKUP_MAGIC; 411 412 *nodep = node; 413 return ISC_R_SUCCESS; 414 } 415 416 static void 417 destroynode(dns_sdlznode_t *node) { 418 dns_rdatalist_t *list; 419 dns_rdata_t *rdata; 420 isc_buffer_t *b; 421 dns_sdlz_db_t *sdlz; 422 dns_db_t *db; 423 isc_mem_t *mctx; 424 425 isc_refcount_destroy(&node->references); 426 427 sdlz = node->sdlz; 428 mctx = sdlz->common.mctx; 429 430 while (!ISC_LIST_EMPTY(node->lists)) { 431 list = ISC_LIST_HEAD(node->lists); 432 while (!ISC_LIST_EMPTY(list->rdata)) { 433 rdata = ISC_LIST_HEAD(list->rdata); 434 ISC_LIST_UNLINK(list->rdata, rdata, link); 435 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t)); 436 } 437 ISC_LIST_UNLINK(node->lists, list, link); 438 isc_mem_put(mctx, list, sizeof(dns_rdatalist_t)); 439 } 440 441 while (!ISC_LIST_EMPTY(node->buffers)) { 442 b = ISC_LIST_HEAD(node->buffers); 443 ISC_LIST_UNLINK(node->buffers, b, link); 444 isc_buffer_free(&b); 445 } 446 447 if (node->name != NULL) { 448 dns_name_free(node->name, mctx); 449 isc_mem_put(mctx, node->name, sizeof(dns_name_t)); 450 } 451 452 node->magic = 0; 453 isc_mem_put(mctx, node, sizeof(dns_sdlznode_t)); 454 db = &sdlz->common; 455 dns_db_detach(&db); 456 } 457 458 static isc_result_t 459 getnodedata(dns_db_t *db, const dns_name_t *name, bool create, 460 unsigned int options, dns_clientinfomethods_t *methods, 461 dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep) { 462 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 463 dns_sdlznode_t *node = NULL; 464 isc_result_t result; 465 isc_buffer_t b; 466 char namestr[DNS_NAME_MAXTEXT + 1]; 467 isc_buffer_t b2; 468 char zonestr[DNS_NAME_MAXTEXT + 1]; 469 bool isorigin; 470 dns_sdlzauthorityfunc_t authority; 471 472 REQUIRE(VALID_SDLZDB(sdlz)); 473 REQUIRE(nodep != NULL && *nodep == NULL); 474 475 if (sdlz->dlzimp->methods->newversion == NULL) { 476 REQUIRE(!create); 477 } 478 479 isc_buffer_init(&b, namestr, sizeof(namestr)); 480 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) { 481 dns_name_t relname; 482 unsigned int labels; 483 484 labels = dns_name_countlabels(name) - 485 dns_name_countlabels(&sdlz->common.origin); 486 dns_name_init(&relname, NULL); 487 dns_name_getlabelsequence(name, 0, labels, &relname); 488 result = dns_name_totext(&relname, DNS_NAME_OMITFINALDOT, &b); 489 if (result != ISC_R_SUCCESS) { 490 return result; 491 } 492 } else { 493 result = dns_name_totext(name, DNS_NAME_OMITFINALDOT, &b); 494 if (result != ISC_R_SUCCESS) { 495 return result; 496 } 497 } 498 isc_buffer_putuint8(&b, 0); 499 500 isc_buffer_init(&b2, zonestr, sizeof(zonestr)); 501 result = dns_name_totext(&sdlz->common.origin, DNS_NAME_OMITFINALDOT, 502 &b2); 503 if (result != ISC_R_SUCCESS) { 504 return result; 505 } 506 isc_buffer_putuint8(&b2, 0); 507 508 result = createnode(sdlz, &node); 509 if (result != ISC_R_SUCCESS) { 510 return result; 511 } 512 513 isorigin = dns_name_equal(name, &sdlz->common.origin); 514 515 /* make sure strings are always lowercase */ 516 isc_ascii_strtolower(zonestr); 517 isc_ascii_strtolower(namestr); 518 519 MAYBE_LOCK(sdlz->dlzimp); 520 521 /* try to lookup the host (namestr) */ 522 result = sdlz->dlzimp->methods->lookup( 523 zonestr, namestr, sdlz->dlzimp->driverarg, sdlz->dbdata, node, 524 methods, clientinfo); 525 526 /* 527 * If the name was not found and DNS_DBFIND_NOWILD is not 528 * set, then we try to find a wildcard entry. 529 * 530 * If DNS_DBFIND_NOZONECUT is set and there are multiple 531 * levels between the host and the zone origin, we also look 532 * for wildcards at each level. 533 */ 534 if (result == ISC_R_NOTFOUND && !create && 535 (options & DNS_DBFIND_NOWILD) == 0) 536 { 537 unsigned int i, dlabels, nlabels; 538 539 nlabels = dns_name_countlabels(name); 540 dlabels = nlabels - dns_name_countlabels(&sdlz->common.origin); 541 for (i = 0; i < dlabels; i++) { 542 char wildstr[DNS_NAME_MAXTEXT + 1]; 543 dns_fixedname_t fixed; 544 const dns_name_t *wild; 545 546 dns_fixedname_init(&fixed); 547 if (i == dlabels - 1) { 548 wild = dns_wildcardname; 549 } else { 550 dns_name_t *fname; 551 fname = dns_fixedname_name(&fixed); 552 dns_name_getlabelsequence( 553 name, i + 1, dlabels - i - 1, fname); 554 result = dns_name_concatenate( 555 dns_wildcardname, fname, fname, NULL); 556 if (result != ISC_R_SUCCESS) { 557 MAYBE_UNLOCK(sdlz->dlzimp); 558 return result; 559 } 560 wild = fname; 561 } 562 563 isc_buffer_init(&b, wildstr, sizeof(wildstr)); 564 result = dns_name_totext(wild, DNS_NAME_OMITFINALDOT, 565 &b); 566 if (result != ISC_R_SUCCESS) { 567 MAYBE_UNLOCK(sdlz->dlzimp); 568 return result; 569 } 570 isc_buffer_putuint8(&b, 0); 571 572 result = sdlz->dlzimp->methods->lookup( 573 zonestr, wildstr, sdlz->dlzimp->driverarg, 574 sdlz->dbdata, node, methods, clientinfo); 575 if (result == ISC_R_SUCCESS) { 576 break; 577 } 578 } 579 } 580 581 MAYBE_UNLOCK(sdlz->dlzimp); 582 583 if (result == ISC_R_NOTFOUND && (isorigin || create)) { 584 result = ISC_R_SUCCESS; 585 } 586 587 if (result != ISC_R_SUCCESS) { 588 isc_refcount_decrementz(&node->references); 589 destroynode(node); 590 return result; 591 } 592 593 if (isorigin && sdlz->dlzimp->methods->authority != NULL) { 594 MAYBE_LOCK(sdlz->dlzimp); 595 authority = sdlz->dlzimp->methods->authority; 596 result = (*authority)(zonestr, sdlz->dlzimp->driverarg, 597 sdlz->dbdata, node); 598 MAYBE_UNLOCK(sdlz->dlzimp); 599 if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) { 600 isc_refcount_decrementz(&node->references); 601 destroynode(node); 602 return result; 603 } 604 } 605 606 if (node->name == NULL) { 607 node->name = isc_mem_get(sdlz->common.mctx, sizeof(dns_name_t)); 608 dns_name_init(node->name, NULL); 609 dns_name_dup(name, sdlz->common.mctx, node->name); 610 } 611 612 *nodep = node; 613 return ISC_R_SUCCESS; 614 } 615 616 static isc_result_t 617 findnodeext(dns_db_t *db, const dns_name_t *name, bool create, 618 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, 619 dns_dbnode_t **nodep DNS__DB_FLARG) { 620 return getnodedata(db, name, create, 0, methods, clientinfo, nodep); 621 } 622 623 static isc_result_t 624 findnode(dns_db_t *db, const dns_name_t *name, bool create, 625 dns_dbnode_t **nodep DNS__DB_FLARG) { 626 return getnodedata(db, name, create, 0, NULL, NULL, nodep); 627 } 628 629 static void 630 attachnode(dns_db_t *db, dns_dbnode_t *source, 631 dns_dbnode_t **targetp DNS__DB_FLARG) { 632 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 633 dns_sdlznode_t *node = (dns_sdlznode_t *)source; 634 uint_fast32_t refs; 635 636 REQUIRE(VALID_SDLZDB(sdlz)); 637 638 UNUSED(sdlz); 639 640 refs = isc_refcount_increment(&node->references); 641 #if DNS_DB_NODETRACE 642 fprintf(stderr, "incr:node:%s:%s:%u:%p->references = %" PRIuFAST32 "\n", 643 func, file, line, node, refs + 1); 644 #else 645 UNUSED(refs); 646 #endif 647 648 *targetp = source; 649 } 650 651 static void 652 detachnode(dns_db_t *db, dns_dbnode_t **targetp DNS__DB_FLARG) { 653 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 654 dns_sdlznode_t *node; 655 uint_fast32_t refs; 656 657 REQUIRE(VALID_SDLZDB(sdlz)); 658 REQUIRE(targetp != NULL && *targetp != NULL); 659 660 UNUSED(sdlz); 661 662 node = (dns_sdlznode_t *)(*targetp); 663 *targetp = NULL; 664 665 refs = isc_refcount_decrement(&node->references); 666 #if DNS_DB_NODETRACE 667 fprintf(stderr, "decr:node:%s:%s:%u:%p->references = %" PRIuFAST32 "\n", 668 func, file, line, node, refs - 1); 669 #else 670 UNUSED(refs); 671 #endif 672 673 if (refs == 1) { 674 destroynode(node); 675 } 676 } 677 678 static isc_result_t 679 createiterator(dns_db_t *db, unsigned int options, 680 dns_dbiterator_t **iteratorp) { 681 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 682 sdlz_dbiterator_t *sdlziter; 683 isc_result_t result; 684 isc_buffer_t b; 685 char zonestr[DNS_NAME_MAXTEXT + 1]; 686 687 REQUIRE(VALID_SDLZDB(sdlz)); 688 689 if (sdlz->dlzimp->methods->allnodes == NULL) { 690 return ISC_R_NOTIMPLEMENTED; 691 } 692 693 if ((options & DNS_DB_NSEC3ONLY) != 0 || 694 (options & DNS_DB_NONSEC3) != 0) 695 { 696 return ISC_R_NOTIMPLEMENTED; 697 } 698 699 isc_buffer_init(&b, zonestr, sizeof(zonestr)); 700 result = dns_name_totext(&sdlz->common.origin, DNS_NAME_OMITFINALDOT, 701 &b); 702 if (result != ISC_R_SUCCESS) { 703 return result; 704 } 705 isc_buffer_putuint8(&b, 0); 706 707 sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t)); 708 709 sdlziter->common.methods = &dbiterator_methods; 710 sdlziter->common.db = NULL; 711 dns_db_attach(db, &sdlziter->common.db); 712 sdlziter->common.relative_names = ((options & DNS_DB_RELATIVENAMES) != 713 0); 714 sdlziter->common.magic = DNS_DBITERATOR_MAGIC; 715 ISC_LIST_INIT(sdlziter->nodelist); 716 sdlziter->current = NULL; 717 sdlziter->origin = NULL; 718 719 /* make sure strings are always lowercase */ 720 isc_ascii_strtolower(zonestr); 721 722 MAYBE_LOCK(sdlz->dlzimp); 723 result = sdlz->dlzimp->methods->allnodes( 724 zonestr, sdlz->dlzimp->driverarg, sdlz->dbdata, sdlziter); 725 MAYBE_UNLOCK(sdlz->dlzimp); 726 if (result != ISC_R_SUCCESS) { 727 dns_dbiterator_t *iter = &sdlziter->common; 728 dbiterator_destroy(&iter DNS__DB_FILELINE); 729 return result; 730 } 731 732 if (sdlziter->origin != NULL) { 733 ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link); 734 ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link); 735 } 736 737 *iteratorp = (dns_dbiterator_t *)sdlziter; 738 739 return ISC_R_SUCCESS; 740 } 741 742 static isc_result_t 743 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 744 dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now, 745 dns_rdataset_t *rdataset, 746 dns_rdataset_t *sigrdataset DNS__DB_FLARG) { 747 REQUIRE(VALID_SDLZNODE(node)); 748 dns_rdatalist_t *list; 749 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node; 750 751 UNUSED(db); 752 UNUSED(version); 753 UNUSED(covers); 754 UNUSED(now); 755 UNUSED(sigrdataset); 756 757 if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig) { 758 return ISC_R_NOTIMPLEMENTED; 759 } 760 761 list = ISC_LIST_HEAD(sdlznode->lists); 762 while (list != NULL) { 763 if (list->type == type) { 764 break; 765 } 766 list = ISC_LIST_NEXT(list, link); 767 } 768 if (list == NULL) { 769 return ISC_R_NOTFOUND; 770 } 771 772 list_tordataset(list, db, node, rdataset); 773 774 return ISC_R_SUCCESS; 775 } 776 777 static isc_result_t 778 findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, 779 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, 780 dns_dbnode_t **nodep, dns_name_t *foundname, 781 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, 782 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset DNS__DB_FLARG) { 783 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 784 dns_dbnode_t *node = NULL; 785 dns_fixedname_t fname; 786 dns_rdataset_t xrdataset; 787 dns_name_t *xname; 788 unsigned int nlabels, olabels; 789 isc_result_t result; 790 unsigned int i; 791 792 REQUIRE(VALID_SDLZDB(sdlz)); 793 REQUIRE(nodep == NULL || *nodep == NULL); 794 REQUIRE(version == NULL || version == (void *)&sdlz->dummy_version || 795 version == sdlz->future_version); 796 797 UNUSED(sdlz); 798 799 if (!dns_name_issubdomain(name, &db->origin)) { 800 return DNS_R_NXDOMAIN; 801 } 802 803 olabels = dns_name_countlabels(&db->origin); 804 nlabels = dns_name_countlabels(name); 805 806 xname = dns_fixedname_initname(&fname); 807 808 if (rdataset == NULL) { 809 dns_rdataset_init(&xrdataset); 810 rdataset = &xrdataset; 811 } 812 813 result = DNS_R_NXDOMAIN; 814 815 /* 816 * If we're not walking down searching for zone 817 * cuts, we can cut straight to the chase 818 */ 819 if ((options & DNS_DBFIND_NOZONECUT) != 0) { 820 i = nlabels; 821 goto search; 822 } 823 824 for (i = olabels; i <= nlabels; i++) { 825 search: 826 /* 827 * Look up the next label. 828 */ 829 dns_name_getlabelsequence(name, nlabels - i, i, xname); 830 result = getnodedata(db, xname, false, options, methods, 831 clientinfo, &node); 832 if (result == ISC_R_NOTFOUND) { 833 result = DNS_R_NXDOMAIN; 834 continue; 835 } else if (result != ISC_R_SUCCESS) { 836 break; 837 } 838 839 /* 840 * Look for a DNAME at the current label, unless this is 841 * the qname. 842 */ 843 if (i < nlabels) { 844 result = findrdataset( 845 db, node, version, dns_rdatatype_dname, 0, now, 846 rdataset, sigrdataset DNS__DB_FLARG_PASS); 847 if (result == ISC_R_SUCCESS) { 848 result = DNS_R_DNAME; 849 break; 850 } 851 } 852 853 /* 854 * Look for an NS at the current label, unless this is the 855 * origin, glue is ok, or there are known to be no zone cuts. 856 */ 857 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0 && 858 (options & DNS_DBFIND_NOZONECUT) == 0) 859 { 860 result = findrdataset( 861 db, node, version, dns_rdatatype_ns, 0, now, 862 rdataset, sigrdataset DNS__DB_FLARG_PASS); 863 864 if (result == ISC_R_SUCCESS && i == nlabels && 865 type == dns_rdatatype_any) 866 { 867 result = DNS_R_ZONECUT; 868 dns_rdataset_disassociate(rdataset); 869 if (sigrdataset != NULL && 870 dns_rdataset_isassociated(sigrdataset)) 871 { 872 dns_rdataset_disassociate(sigrdataset); 873 } 874 break; 875 } else if (result == ISC_R_SUCCESS) { 876 result = DNS_R_DELEGATION; 877 break; 878 } 879 } 880 881 /* 882 * If the current name is not the qname, add another label 883 * and try again. 884 */ 885 if (i < nlabels) { 886 detachnode(db, &node DNS__DB_FLARG_PASS); 887 node = NULL; 888 continue; 889 } 890 891 /* 892 * If we're looking for ANY, we're done. 893 */ 894 if (type == dns_rdatatype_any) { 895 result = ISC_R_SUCCESS; 896 break; 897 } 898 899 /* 900 * Look for the qtype. 901 */ 902 result = findrdataset(db, node, version, type, 0, now, rdataset, 903 sigrdataset DNS__DB_FLARG_PASS); 904 if (result == ISC_R_SUCCESS) { 905 break; 906 } 907 908 /* 909 * Look for a CNAME 910 */ 911 if (type != dns_rdatatype_cname) { 912 result = findrdataset( 913 db, node, version, dns_rdatatype_cname, 0, now, 914 rdataset, sigrdataset DNS__DB_FLARG_PASS); 915 if (result == ISC_R_SUCCESS) { 916 result = DNS_R_CNAME; 917 break; 918 } 919 } 920 921 result = DNS_R_NXRRSET; 922 break; 923 } 924 925 if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) { 926 dns_rdataset_disassociate(rdataset); 927 } 928 929 if (foundname != NULL) { 930 dns_name_copy(xname, foundname); 931 } 932 933 if (nodep != NULL) { 934 *nodep = node; 935 } else if (node != NULL) { 936 detachnode(db, &node DNS__DB_FLARG_PASS); 937 } 938 939 return result; 940 } 941 942 static isc_result_t 943 find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, 944 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, 945 dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset, 946 dns_rdataset_t *sigrdataset DNS__DB_FLARG) { 947 return findext(db, name, version, type, options, now, nodep, foundname, 948 NULL, NULL, rdataset, sigrdataset DNS__DB_FLARG_PASS); 949 } 950 951 static isc_result_t 952 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 953 unsigned int options, isc_stdtime_t now, 954 dns_rdatasetiter_t **iteratorp DNS__DB_FLARG) { 955 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 956 sdlz_rdatasetiter_t *iterator; 957 958 REQUIRE(VALID_SDLZDB(sdlz)); 959 960 REQUIRE(version == NULL || version == (void *)&sdlz->dummy_version || 961 version == sdlz->future_version); 962 963 UNUSED(version); 964 UNUSED(now); 965 966 iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t)); 967 968 iterator->common.magic = DNS_RDATASETITER_MAGIC; 969 iterator->common.methods = &rdatasetiter_methods; 970 iterator->common.db = db; 971 iterator->common.node = NULL; 972 attachnode(db, node, &iterator->common.node DNS__DB_FLARG_PASS); 973 iterator->common.version = version; 974 iterator->common.options = options; 975 iterator->common.now = now; 976 977 *iteratorp = (dns_rdatasetiter_t *)iterator; 978 979 return ISC_R_SUCCESS; 980 } 981 982 static isc_result_t 983 modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 984 dns_rdataset_t *rdataset, unsigned int options, 985 dns_sdlzmodrdataset_t mod_function) { 986 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 987 dns_master_style_t *style = NULL; 988 isc_result_t result; 989 isc_buffer_t *buffer = NULL; 990 isc_mem_t *mctx; 991 dns_sdlznode_t *sdlznode; 992 char *rdatastr = NULL; 993 char name[DNS_NAME_MAXTEXT + 1]; 994 995 REQUIRE(VALID_SDLZDB(sdlz)); 996 997 if (mod_function == NULL) { 998 return ISC_R_NOTIMPLEMENTED; 999 } 1000 1001 sdlznode = (dns_sdlznode_t *)node; 1002 1003 UNUSED(options); 1004 1005 dns_name_format(sdlznode->name, name, sizeof(name)); 1006 1007 mctx = sdlz->common.mctx; 1008 1009 isc_buffer_allocate(mctx, &buffer, 1024); 1010 1011 result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1, 0xffffffff, 1012 mctx); 1013 if (result != ISC_R_SUCCESS) { 1014 goto cleanup; 1015 } 1016 1017 result = dns_master_rdatasettotext(sdlznode->name, rdataset, style, 1018 NULL, buffer); 1019 if (result != ISC_R_SUCCESS) { 1020 goto cleanup; 1021 } 1022 1023 if (isc_buffer_usedlength(buffer) < 1) { 1024 result = ISC_R_BADADDRESSFORM; 1025 goto cleanup; 1026 } 1027 1028 rdatastr = isc_buffer_base(buffer); 1029 if (rdatastr == NULL) { 1030 result = ISC_R_NOMEMORY; 1031 goto cleanup; 1032 } 1033 rdatastr[isc_buffer_usedlength(buffer) - 1] = 0; 1034 1035 MAYBE_LOCK(sdlz->dlzimp); 1036 result = mod_function(name, rdatastr, sdlz->dlzimp->driverarg, 1037 sdlz->dbdata, version); 1038 MAYBE_UNLOCK(sdlz->dlzimp); 1039 1040 cleanup: 1041 isc_buffer_free(&buffer); 1042 if (style != NULL) { 1043 dns_master_styledestroy(&style, mctx); 1044 } 1045 1046 return result; 1047 } 1048 1049 static isc_result_t 1050 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1051 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, 1052 dns_rdataset_t *addedrdataset DNS__DB_FLARG) { 1053 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 1054 isc_result_t result; 1055 1056 UNUSED(now); 1057 UNUSED(addedrdataset); 1058 REQUIRE(VALID_SDLZDB(sdlz)); 1059 1060 if (sdlz->dlzimp->methods->addrdataset == NULL) { 1061 return ISC_R_NOTIMPLEMENTED; 1062 } 1063 1064 result = modrdataset(db, node, version, rdataset, options, 1065 sdlz->dlzimp->methods->addrdataset); 1066 return result; 1067 } 1068 1069 static isc_result_t 1070 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1071 dns_rdataset_t *rdataset, unsigned int options, 1072 dns_rdataset_t *newrdataset DNS__DB_FLARG) { 1073 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 1074 isc_result_t result; 1075 1076 UNUSED(newrdataset); 1077 REQUIRE(VALID_SDLZDB(sdlz)); 1078 1079 if (sdlz->dlzimp->methods->subtractrdataset == NULL) { 1080 return ISC_R_NOTIMPLEMENTED; 1081 } 1082 1083 result = modrdataset(db, node, version, rdataset, options, 1084 sdlz->dlzimp->methods->subtractrdataset); 1085 return result; 1086 } 1087 1088 static isc_result_t 1089 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1090 dns_rdatatype_t type, dns_rdatatype_t covers DNS__DB_FLARG) { 1091 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 1092 char name[DNS_NAME_MAXTEXT + 1]; 1093 char b_type[DNS_RDATATYPE_FORMATSIZE]; 1094 dns_sdlznode_t *sdlznode; 1095 isc_result_t result; 1096 1097 UNUSED(covers); 1098 1099 REQUIRE(VALID_SDLZDB(sdlz)); 1100 1101 if (sdlz->dlzimp->methods->delrdataset == NULL) { 1102 return ISC_R_NOTIMPLEMENTED; 1103 } 1104 1105 sdlznode = (dns_sdlznode_t *)node; 1106 dns_name_format(sdlznode->name, name, sizeof(name)); 1107 dns_rdatatype_format(type, b_type, sizeof(b_type)); 1108 1109 MAYBE_LOCK(sdlz->dlzimp); 1110 result = sdlz->dlzimp->methods->delrdataset( 1111 name, b_type, sdlz->dlzimp->driverarg, sdlz->dbdata, version); 1112 MAYBE_UNLOCK(sdlz->dlzimp); 1113 1114 return result; 1115 } 1116 1117 static bool 1118 issecure(dns_db_t *db) { 1119 UNUSED(db); 1120 1121 return false; 1122 } 1123 1124 static unsigned int 1125 nodecount(dns_db_t *db, dns_dbtree_t tree) { 1126 UNUSED(db); 1127 UNUSED(tree); 1128 1129 return 0; 1130 } 1131 1132 static void 1133 setloop(dns_db_t *db, isc_loop_t *loop) { 1134 UNUSED(db); 1135 UNUSED(loop); 1136 } 1137 1138 /* 1139 * getoriginnode() is used by the update code to find the 1140 * dns_rdatatype_dnskey record for a zone 1141 */ 1142 static isc_result_t 1143 getoriginnode(dns_db_t *db, dns_dbnode_t **nodep DNS__DB_FLARG) { 1144 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 1145 isc_result_t result; 1146 1147 REQUIRE(VALID_SDLZDB(sdlz)); 1148 if (sdlz->dlzimp->methods->newversion == NULL) { 1149 return ISC_R_NOTIMPLEMENTED; 1150 } 1151 1152 result = getnodedata(db, &sdlz->common.origin, false, 0, NULL, NULL, 1153 nodep); 1154 if (result != ISC_R_SUCCESS) { 1155 sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed: %s", 1156 isc_result_totext(result)); 1157 } 1158 return result; 1159 } 1160 1161 static dns_dbmethods_t sdlzdb_methods = { 1162 .destroy = destroy, 1163 .currentversion = currentversion, 1164 .newversion = newversion, 1165 .attachversion = attachversion, 1166 .closeversion = closeversion, 1167 .findnode = findnode, 1168 .find = find, 1169 .attachnode = attachnode, 1170 .detachnode = detachnode, 1171 .createiterator = createiterator, 1172 .findrdataset = findrdataset, 1173 .allrdatasets = allrdatasets, 1174 .addrdataset = addrdataset, 1175 .subtractrdataset = subtractrdataset, 1176 .deleterdataset = deleterdataset, 1177 .issecure = issecure, 1178 .nodecount = nodecount, 1179 .setloop = setloop, 1180 .getoriginnode = getoriginnode, 1181 .findnodeext = findnodeext, 1182 .findext = findext, 1183 }; 1184 1185 /* 1186 * Database Iterator Methods. These methods were "borrowed" from the SDB 1187 * driver interface. See the SDB driver interface documentation for more info. 1188 */ 1189 1190 static void 1191 dbiterator_destroy(dns_dbiterator_t **iteratorp DNS__DB_FLARG) { 1192 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp); 1193 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db; 1194 1195 while (!ISC_LIST_EMPTY(sdlziter->nodelist)) { 1196 dns_sdlznode_t *node; 1197 node = ISC_LIST_HEAD(sdlziter->nodelist); 1198 ISC_LIST_UNLINK(sdlziter->nodelist, node, link); 1199 isc_refcount_decrementz(&node->references); 1200 destroynode(node); 1201 } 1202 1203 dns_db_detach(&sdlziter->common.db); 1204 isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t)); 1205 1206 *iteratorp = NULL; 1207 } 1208 1209 static isc_result_t 1210 dbiterator_first(dns_dbiterator_t *iterator DNS__DB_FLARG) { 1211 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1212 1213 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist); 1214 if (sdlziter->current == NULL) { 1215 return ISC_R_NOMORE; 1216 } else { 1217 return ISC_R_SUCCESS; 1218 } 1219 } 1220 1221 static isc_result_t 1222 dbiterator_last(dns_dbiterator_t *iterator DNS__DB_FLARG) { 1223 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1224 1225 sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist); 1226 if (sdlziter->current == NULL) { 1227 return ISC_R_NOMORE; 1228 } else { 1229 return ISC_R_SUCCESS; 1230 } 1231 } 1232 1233 static isc_result_t 1234 dbiterator_seek(dns_dbiterator_t *iterator, 1235 const dns_name_t *name DNS__DB_FLARG) { 1236 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1237 1238 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist); 1239 while (sdlziter->current != NULL) { 1240 if (dns_name_equal(sdlziter->current->name, name)) { 1241 return ISC_R_SUCCESS; 1242 } 1243 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link); 1244 } 1245 return ISC_R_NOTFOUND; 1246 } 1247 1248 static isc_result_t 1249 dbiterator_prev(dns_dbiterator_t *iterator DNS__DB_FLARG) { 1250 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1251 1252 sdlziter->current = ISC_LIST_PREV(sdlziter->current, link); 1253 if (sdlziter->current == NULL) { 1254 return ISC_R_NOMORE; 1255 } else { 1256 return ISC_R_SUCCESS; 1257 } 1258 } 1259 1260 static isc_result_t 1261 dbiterator_next(dns_dbiterator_t *iterator DNS__DB_FLARG) { 1262 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1263 1264 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link); 1265 if (sdlziter->current == NULL) { 1266 return ISC_R_NOMORE; 1267 } else { 1268 return ISC_R_SUCCESS; 1269 } 1270 } 1271 1272 static isc_result_t 1273 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, 1274 dns_name_t *name DNS__DB_FLARG) { 1275 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1276 1277 attachnode(iterator->db, sdlziter->current, nodep DNS__DB_FLARG_PASS); 1278 if (name != NULL) { 1279 dns_name_copy(sdlziter->current->name, name); 1280 return ISC_R_SUCCESS; 1281 } 1282 return ISC_R_SUCCESS; 1283 } 1284 1285 static isc_result_t 1286 dbiterator_pause(dns_dbiterator_t *iterator) { 1287 UNUSED(iterator); 1288 return ISC_R_SUCCESS; 1289 } 1290 1291 static isc_result_t 1292 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) { 1293 UNUSED(iterator); 1294 dns_name_copy(dns_rootname, name); 1295 return ISC_R_SUCCESS; 1296 } 1297 1298 /* 1299 * Rdataset Methods. These methods were "borrowed" from the SDB driver 1300 * interface. See the SDB driver interface documentation for more info. 1301 */ 1302 1303 static void 1304 disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG) { 1305 dns_dbnode_t *node = rdataset->rdlist.node; 1306 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node; 1307 dns_db_t *db = (dns_db_t *)sdlznode->sdlz; 1308 1309 detachnode(db, &node DNS__DB_FLARG_PASS); 1310 dns_rdatalist_disassociate(rdataset DNS__DB_FLARG_PASS); 1311 } 1312 1313 static void 1314 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target DNS__DB_FLARG) { 1315 dns_dbnode_t *node = source->rdlist.node; 1316 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node; 1317 dns_db_t *db = (dns_db_t *)sdlznode->sdlz; 1318 1319 dns_rdatalist_clone(source, target DNS__DB_FLARG_PASS); 1320 attachnode(db, node, &target->rdlist.node DNS__DB_FLARG_PASS); 1321 } 1322 1323 static dns_rdatasetmethods_t rdataset_methods = { 1324 .disassociate = disassociate, 1325 .first = dns_rdatalist_first, 1326 .next = dns_rdatalist_next, 1327 .current = dns_rdatalist_current, 1328 .clone = rdataset_clone, 1329 .count = dns_rdatalist_count, 1330 .addnoqname = dns_rdatalist_addnoqname, 1331 .getnoqname = dns_rdatalist_getnoqname, 1332 }; 1333 1334 static void 1335 list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node, 1336 dns_rdataset_t *rdataset) { 1337 /* 1338 * The sdlz rdataset is an rdatalist, but additionally holds 1339 * a database node reference. 1340 */ 1341 1342 dns_rdatalist_tordataset(rdatalist, rdataset); 1343 rdataset->methods = &rdataset_methods; 1344 dns_db_attachnode(db, node, &rdataset->rdlist.node); 1345 } 1346 1347 /* 1348 * SDLZ core methods. This is the core of the new DLZ functionality. 1349 */ 1350 1351 /*% 1352 * Build a 'bind' database driver structure to be returned by 1353 * either the find zone or the allow zone transfer method. 1354 * This method is only available in this source file, it is 1355 * not made available anywhere else. 1356 */ 1357 1358 static isc_result_t 1359 dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata, 1360 const dns_name_t *name, dns_rdataclass_t rdclass, 1361 dns_db_t **dbp) { 1362 dns_sdlz_db_t *sdlzdb; 1363 dns_sdlzimplementation_t *imp; 1364 1365 /* check that things are as we expect */ 1366 REQUIRE(dbp != NULL && *dbp == NULL); 1367 REQUIRE(name != NULL); 1368 1369 imp = (dns_sdlzimplementation_t *)driverarg; 1370 1371 /* allocate and zero memory for driver structure */ 1372 sdlzdb = isc_mem_get(mctx, sizeof(*sdlzdb)); 1373 1374 *sdlzdb = (dns_sdlz_db_t) { 1375 .dlzimp = imp, 1376 .common = { .methods = &sdlzdb_methods, 1377 .rdclass = rdclass, }, 1378 .dbdata = dbdata, 1379 }; 1380 1381 /* initialize and set origin */ 1382 dns_name_init(&sdlzdb->common.origin, NULL); 1383 dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin); 1384 1385 isc_refcount_init(&sdlzdb->common.references, 1); 1386 1387 /* attach to the memory context */ 1388 isc_mem_attach(mctx, &sdlzdb->common.mctx); 1389 1390 /* mark structure as valid */ 1391 sdlzdb->common.magic = DNS_DB_MAGIC; 1392 sdlzdb->common.impmagic = SDLZDB_MAGIC; 1393 *dbp = (dns_db_t *)sdlzdb; 1394 1395 return ISC_R_SUCCESS; 1396 } 1397 1398 static isc_result_t 1399 dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx, 1400 dns_rdataclass_t rdclass, const dns_name_t *name, 1401 const isc_sockaddr_t *clientaddr, dns_db_t **dbp) { 1402 isc_buffer_t b; 1403 isc_buffer_t b2; 1404 char namestr[DNS_NAME_MAXTEXT + 1]; 1405 char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255." 1406 "255") + 1407 1]; 1408 isc_netaddr_t netaddr; 1409 isc_result_t result; 1410 dns_sdlzimplementation_t *imp; 1411 1412 /* 1413 * Perform checks to make sure data is as we expect it to be. 1414 */ 1415 REQUIRE(driverarg != NULL); 1416 REQUIRE(name != NULL); 1417 REQUIRE(clientaddr != NULL); 1418 REQUIRE(dbp != NULL && *dbp == NULL); 1419 1420 imp = (dns_sdlzimplementation_t *)driverarg; 1421 1422 /* Convert DNS name to ascii text */ 1423 isc_buffer_init(&b, namestr, sizeof(namestr)); 1424 result = dns_name_totext(name, DNS_NAME_OMITFINALDOT, &b); 1425 if (result != ISC_R_SUCCESS) { 1426 return result; 1427 } 1428 isc_buffer_putuint8(&b, 0); 1429 1430 /* convert client address to ascii text */ 1431 isc_buffer_init(&b2, clientstr, sizeof(clientstr)); 1432 isc_netaddr_fromsockaddr(&netaddr, clientaddr); 1433 result = isc_netaddr_totext(&netaddr, &b2); 1434 if (result != ISC_R_SUCCESS) { 1435 return result; 1436 } 1437 isc_buffer_putuint8(&b2, 0); 1438 1439 /* make sure strings are always lowercase */ 1440 isc_ascii_strtolower(namestr); 1441 isc_ascii_strtolower(clientstr); 1442 1443 /* Call SDLZ driver's find zone method */ 1444 if (imp->methods->allowzonexfr != NULL) { 1445 isc_result_t rresult = ISC_R_SUCCESS; 1446 1447 MAYBE_LOCK(imp); 1448 result = imp->methods->allowzonexfr(imp->driverarg, dbdata, 1449 namestr, clientstr); 1450 MAYBE_UNLOCK(imp); 1451 /* 1452 * if zone is supported and transfers are (or might be) 1453 * allowed, build a 'bind' database driver 1454 */ 1455 if (result == ISC_R_SUCCESS || result == ISC_R_DEFAULT) { 1456 rresult = dns_sdlzcreateDBP(mctx, driverarg, dbdata, 1457 name, rdclass, dbp); 1458 } 1459 if (rresult != ISC_R_SUCCESS) { 1460 result = rresult; 1461 } 1462 return result; 1463 } 1464 1465 return ISC_R_NOTIMPLEMENTED; 1466 } 1467 1468 static isc_result_t 1469 dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc, 1470 char *argv[], void *driverarg, void **dbdata) { 1471 dns_sdlzimplementation_t *imp; 1472 isc_result_t result = ISC_R_NOTFOUND; 1473 1474 /* Write debugging message to log */ 1475 sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver."); 1476 1477 /* 1478 * Performs checks to make sure data is as we expect it to be. 1479 */ 1480 REQUIRE(driverarg != NULL); 1481 REQUIRE(dlzname != NULL); 1482 REQUIRE(dbdata != NULL); 1483 UNUSED(mctx); 1484 1485 imp = driverarg; 1486 1487 /* If the create method exists, call it. */ 1488 if (imp->methods->create != NULL) { 1489 MAYBE_LOCK(imp); 1490 result = imp->methods->create(dlzname, argc, argv, 1491 imp->driverarg, dbdata); 1492 MAYBE_UNLOCK(imp); 1493 } 1494 1495 /* Write debugging message to log */ 1496 if (result == ISC_R_SUCCESS) { 1497 sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully."); 1498 } else { 1499 sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load."); 1500 } 1501 1502 return result; 1503 } 1504 1505 static void 1506 dns_sdlzdestroy(void *driverdata, void **dbdata) { 1507 dns_sdlzimplementation_t *imp; 1508 1509 /* Write debugging message to log */ 1510 sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver."); 1511 1512 imp = driverdata; 1513 1514 /* If the destroy method exists, call it. */ 1515 if (imp->methods->destroy != NULL) { 1516 MAYBE_LOCK(imp); 1517 imp->methods->destroy(imp->driverarg, dbdata); 1518 MAYBE_UNLOCK(imp); 1519 } 1520 } 1521 1522 static isc_result_t 1523 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx, 1524 dns_rdataclass_t rdclass, const dns_name_t *name, 1525 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, 1526 dns_db_t **dbp) { 1527 isc_buffer_t b; 1528 char namestr[DNS_NAME_MAXTEXT + 1]; 1529 isc_result_t result; 1530 dns_sdlzimplementation_t *imp; 1531 1532 /* 1533 * Perform checks to make sure data is as we expect it to be. 1534 */ 1535 REQUIRE(driverarg != NULL); 1536 REQUIRE(name != NULL); 1537 REQUIRE(dbp != NULL && *dbp == NULL); 1538 1539 imp = (dns_sdlzimplementation_t *)driverarg; 1540 1541 /* Convert DNS name to ascii text */ 1542 isc_buffer_init(&b, namestr, sizeof(namestr)); 1543 result = dns_name_totext(name, DNS_NAME_OMITFINALDOT, &b); 1544 if (result != ISC_R_SUCCESS) { 1545 return result; 1546 } 1547 isc_buffer_putuint8(&b, 0); 1548 1549 /* make sure strings are always lowercase */ 1550 isc_ascii_strtolower(namestr); 1551 1552 /* Call SDLZ driver's find zone method */ 1553 MAYBE_LOCK(imp); 1554 result = imp->methods->findzone(imp->driverarg, dbdata, namestr, 1555 methods, clientinfo); 1556 MAYBE_UNLOCK(imp); 1557 1558 /* 1559 * if zone is supported build a 'bind' database driver 1560 * structure to return 1561 */ 1562 if (result == ISC_R_SUCCESS) { 1563 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name, 1564 rdclass, dbp); 1565 } 1566 1567 return result; 1568 } 1569 1570 static isc_result_t 1571 dns_sdlzconfigure(void *driverarg, void *dbdata, dns_view_t *view, 1572 dns_dlzdb_t *dlzdb) { 1573 isc_result_t result; 1574 dns_sdlzimplementation_t *imp; 1575 1576 REQUIRE(driverarg != NULL); 1577 1578 imp = (dns_sdlzimplementation_t *)driverarg; 1579 1580 /* Call SDLZ driver's configure method */ 1581 if (imp->methods->configure != NULL) { 1582 MAYBE_LOCK(imp); 1583 result = imp->methods->configure(view, dlzdb, imp->driverarg, 1584 dbdata); 1585 MAYBE_UNLOCK(imp); 1586 } else { 1587 result = ISC_R_SUCCESS; 1588 } 1589 1590 return result; 1591 } 1592 1593 static bool 1594 dns_sdlzssumatch(const dns_name_t *signer, const dns_name_t *name, 1595 const isc_netaddr_t *tcpaddr, dns_rdatatype_t type, 1596 const dst_key_t *key, void *driverarg, void *dbdata) { 1597 dns_sdlzimplementation_t *imp; 1598 char b_signer[DNS_NAME_FORMATSIZE]; 1599 char b_name[DNS_NAME_FORMATSIZE]; 1600 char b_addr[ISC_NETADDR_FORMATSIZE]; 1601 char b_type[DNS_RDATATYPE_FORMATSIZE]; 1602 char b_key[DST_KEY_FORMATSIZE]; 1603 isc_buffer_t *tkey_token = NULL; 1604 isc_region_t token_region = { NULL, 0 }; 1605 uint32_t token_len = 0; 1606 bool ret; 1607 1608 REQUIRE(driverarg != NULL); 1609 1610 imp = (dns_sdlzimplementation_t *)driverarg; 1611 if (imp->methods->ssumatch == NULL) { 1612 return false; 1613 } 1614 1615 /* 1616 * Format the request elements. sdlz operates on strings, not 1617 * structures 1618 */ 1619 if (signer != NULL) { 1620 dns_name_format(signer, b_signer, sizeof(b_signer)); 1621 } else { 1622 b_signer[0] = 0; 1623 } 1624 1625 dns_name_format(name, b_name, sizeof(b_name)); 1626 1627 if (tcpaddr != NULL) { 1628 isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr)); 1629 } else { 1630 b_addr[0] = 0; 1631 } 1632 1633 dns_rdatatype_format(type, b_type, sizeof(b_type)); 1634 1635 if (key != NULL) { 1636 dst_key_format(key, b_key, sizeof(b_key)); 1637 tkey_token = dst_key_tkeytoken(key); 1638 } else { 1639 b_key[0] = 0; 1640 } 1641 1642 if (tkey_token != NULL) { 1643 isc_buffer_region(tkey_token, &token_region); 1644 token_len = token_region.length; 1645 } 1646 1647 MAYBE_LOCK(imp); 1648 ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key, 1649 token_len, 1650 token_len != 0 ? token_region.base : NULL, 1651 imp->driverarg, dbdata); 1652 MAYBE_UNLOCK(imp); 1653 return ret; 1654 } 1655 1656 static dns_dlzmethods_t sdlzmethods = { dns_sdlzcreate, dns_sdlzdestroy, 1657 dns_sdlzfindzone, dns_sdlzallowzonexfr, 1658 dns_sdlzconfigure, dns_sdlzssumatch }; 1659 1660 /* 1661 * Public functions. 1662 */ 1663 1664 isc_result_t 1665 dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl, 1666 const char *data) { 1667 dns_rdatalist_t *rdatalist; 1668 dns_rdata_t *rdata; 1669 dns_rdatatype_t typeval; 1670 isc_consttextregion_t r; 1671 isc_buffer_t b; 1672 isc_buffer_t *rdatabuf = NULL; 1673 isc_lex_t *lex; 1674 isc_result_t result; 1675 unsigned int size; 1676 isc_mem_t *mctx; 1677 const dns_name_t *origin; 1678 1679 REQUIRE(VALID_SDLZLOOKUP(lookup)); 1680 REQUIRE(type != NULL); 1681 REQUIRE(data != NULL); 1682 1683 mctx = lookup->sdlz->common.mctx; 1684 1685 r.base = type; 1686 r.length = strlen(type); 1687 result = dns_rdatatype_fromtext(&typeval, (void *)&r); 1688 if (result != ISC_R_SUCCESS) { 1689 return result; 1690 } 1691 1692 rdatalist = ISC_LIST_HEAD(lookup->lists); 1693 while (rdatalist != NULL) { 1694 if (rdatalist->type == typeval) { 1695 break; 1696 } 1697 rdatalist = ISC_LIST_NEXT(rdatalist, link); 1698 } 1699 1700 if (rdatalist == NULL) { 1701 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t)); 1702 dns_rdatalist_init(rdatalist); 1703 rdatalist->rdclass = lookup->sdlz->common.rdclass; 1704 rdatalist->type = typeval; 1705 rdatalist->ttl = ttl; 1706 ISC_LIST_APPEND(lookup->lists, rdatalist, link); 1707 } else if (rdatalist->ttl > ttl) { 1708 /* 1709 * BIND9 doesn't enforce all RRs in an RRset 1710 * having the same TTL, as per RFC 2136, 1711 * section 7.12. If a DLZ backend has 1712 * different TTLs, then the best 1713 * we can do is return the lowest. 1714 */ 1715 rdatalist->ttl = ttl; 1716 } 1717 1718 rdata = isc_mem_get(mctx, sizeof(dns_rdata_t)); 1719 dns_rdata_init(rdata); 1720 1721 if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) { 1722 origin = &lookup->sdlz->common.origin; 1723 } else { 1724 origin = dns_rootname; 1725 } 1726 1727 lex = NULL; 1728 isc_lex_create(mctx, 64, &lex); 1729 1730 size = initial_size(data); 1731 do { 1732 isc_buffer_constinit(&b, data, strlen(data)); 1733 isc_buffer_add(&b, strlen(data)); 1734 1735 result = isc_lex_openbuffer(lex, &b); 1736 if (result != ISC_R_SUCCESS) { 1737 goto failure; 1738 } 1739 1740 rdatabuf = NULL; 1741 isc_buffer_allocate(mctx, &rdatabuf, size); 1742 1743 result = dns_rdata_fromtext(rdata, rdatalist->rdclass, 1744 rdatalist->type, lex, origin, false, 1745 mctx, rdatabuf, &lookup->callbacks); 1746 if (result != ISC_R_SUCCESS) { 1747 isc_buffer_free(&rdatabuf); 1748 } 1749 if (size >= 65535) { 1750 break; 1751 } 1752 size *= 2; 1753 if (size >= 65535) { 1754 size = 65535; 1755 } 1756 } while (result == ISC_R_NOSPACE); 1757 1758 if (result != ISC_R_SUCCESS) { 1759 result = DNS_R_SERVFAIL; 1760 goto failure; 1761 } 1762 1763 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 1764 ISC_LIST_APPEND(lookup->buffers, rdatabuf, link); 1765 1766 if (lex != NULL) { 1767 isc_lex_destroy(&lex); 1768 } 1769 1770 return ISC_R_SUCCESS; 1771 1772 failure: 1773 if (rdatabuf != NULL) { 1774 isc_buffer_free(&rdatabuf); 1775 } 1776 if (lex != NULL) { 1777 isc_lex_destroy(&lex); 1778 } 1779 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t)); 1780 1781 return result; 1782 } 1783 1784 isc_result_t 1785 dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name, 1786 const char *type, dns_ttl_t ttl, const char *data) { 1787 dns_name_t *newname; 1788 const dns_name_t *origin; 1789 dns_fixedname_t fnewname; 1790 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db; 1791 dns_sdlznode_t *sdlznode; 1792 isc_mem_t *mctx = sdlz->common.mctx; 1793 isc_buffer_t b; 1794 isc_result_t result; 1795 1796 newname = dns_fixedname_initname(&fnewname); 1797 1798 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) { 1799 origin = &sdlz->common.origin; 1800 } else { 1801 origin = dns_rootname; 1802 } 1803 isc_buffer_constinit(&b, name, strlen(name)); 1804 isc_buffer_add(&b, strlen(name)); 1805 1806 result = dns_name_fromtext(newname, &b, origin, 0, NULL); 1807 if (result != ISC_R_SUCCESS) { 1808 return result; 1809 } 1810 1811 if (allnodes->common.relative_names) { 1812 /* All names are relative to the root */ 1813 unsigned int nlabels = dns_name_countlabels(newname); 1814 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname); 1815 } 1816 1817 sdlznode = ISC_LIST_HEAD(allnodes->nodelist); 1818 if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) { 1819 sdlznode = NULL; 1820 result = createnode(sdlz, &sdlznode); 1821 if (result != ISC_R_SUCCESS) { 1822 return result; 1823 } 1824 sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t)); 1825 dns_name_init(sdlznode->name, NULL); 1826 dns_name_dup(newname, mctx, sdlznode->name); 1827 ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link); 1828 if (allnodes->origin == NULL && 1829 dns_name_equal(newname, &sdlz->common.origin)) 1830 { 1831 allnodes->origin = sdlznode; 1832 } 1833 } 1834 return dns_sdlz_putrr(sdlznode, type, ttl, data); 1835 } 1836 1837 isc_result_t 1838 dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname, 1839 uint32_t serial) { 1840 char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7]; 1841 int n; 1842 1843 REQUIRE(mname != NULL); 1844 REQUIRE(rname != NULL); 1845 1846 n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u", mname, rname, 1847 serial, SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY, 1848 SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM); 1849 if (n >= (int)sizeof(str) || n < 0) { 1850 return ISC_R_NOSPACE; 1851 } 1852 return dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str); 1853 } 1854 1855 isc_result_t 1856 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods, 1857 void *driverarg, unsigned int flags, isc_mem_t *mctx, 1858 dns_sdlzimplementation_t **sdlzimp) { 1859 dns_sdlzimplementation_t *imp; 1860 isc_result_t result; 1861 1862 /* 1863 * Performs checks to make sure data is as we expect it to be. 1864 */ 1865 REQUIRE(drivername != NULL); 1866 REQUIRE(methods != NULL); 1867 REQUIRE(methods->findzone != NULL); 1868 REQUIRE(methods->lookup != NULL); 1869 REQUIRE(mctx != NULL); 1870 REQUIRE(sdlzimp != NULL && *sdlzimp == NULL); 1871 REQUIRE((flags & 1872 ~(DNS_SDLZFLAG_RELATIVEOWNER | DNS_SDLZFLAG_RELATIVERDATA | 1873 DNS_SDLZFLAG_THREADSAFE)) == 0); 1874 1875 /* Write debugging message to log */ 1876 sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername); 1877 1878 /* 1879 * Allocate memory for a sdlz_implementation object. Error if 1880 * we cannot. 1881 */ 1882 imp = isc_mem_get(mctx, sizeof(*imp)); 1883 1884 /* Store the data passed into this method */ 1885 *imp = (dns_sdlzimplementation_t){ 1886 .methods = methods, 1887 .driverarg = driverarg, 1888 .flags = flags, 1889 }; 1890 1891 /* attach the new sdlz_implementation object to a memory context */ 1892 isc_mem_attach(mctx, &imp->mctx); 1893 1894 /* 1895 * initialize the driver lock, error if we cannot 1896 * (used if a driver does not support multiple threads) 1897 */ 1898 isc_mutex_init(&imp->driverlock); 1899 1900 /* 1901 * register the DLZ driver. Pass in our "extra" sdlz information as 1902 * a driverarg. (that's why we stored the passed in driver arg in our 1903 * sdlz_implementation structure) Also, store the dlz_implementation 1904 * structure in our sdlz_implementation. 1905 */ 1906 result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx, 1907 &imp->dlz_imp); 1908 1909 /* if registration fails, cleanup and get outta here. */ 1910 if (result != ISC_R_SUCCESS) { 1911 goto cleanup_mutex; 1912 } 1913 1914 *sdlzimp = imp; 1915 1916 return ISC_R_SUCCESS; 1917 1918 cleanup_mutex: 1919 /* destroy the driver lock, we don't need it anymore */ 1920 isc_mutex_destroy(&imp->driverlock); 1921 1922 /* 1923 * return the memory back to the available memory pool and 1924 * remove it from the memory context. 1925 */ 1926 isc_mem_putanddetach(&imp->mctx, imp, sizeof(*imp)); 1927 return result; 1928 } 1929 1930 void 1931 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) { 1932 dns_sdlzimplementation_t *imp; 1933 1934 /* Write debugging message to log */ 1935 sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver."); 1936 1937 /* 1938 * Performs checks to make sure data is as we expect it to be. 1939 */ 1940 REQUIRE(sdlzimp != NULL && *sdlzimp != NULL); 1941 1942 imp = *sdlzimp; 1943 *sdlzimp = NULL; 1944 1945 /* Unregister the DLZ driver implementation */ 1946 dns_dlzunregister(&imp->dlz_imp); 1947 1948 /* destroy the driver lock, we don't need it anymore */ 1949 isc_mutex_destroy(&imp->driverlock); 1950 1951 /* 1952 * return the memory back to the available memory pool and 1953 * remove it from the memory context. 1954 */ 1955 isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t)); 1956 } 1957 1958 isc_result_t 1959 dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass, 1960 const dns_name_t *name, dns_db_t **dbp) { 1961 isc_result_t result; 1962 1963 result = dns_sdlzcreateDBP(dlzdatabase->mctx, 1964 dlzdatabase->implementation->driverarg, 1965 dlzdatabase->dbdata, name, rdclass, dbp); 1966 return result; 1967 } 1968