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