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