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