sdlz.c revision 174188
1/* 2 * Portions Copyright (C) 2005-2007 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: sdlz.c,v 1.2.2.11 2007/08/28 07:20:05 tbox Exp $ */ 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}; 112 113struct dns_sdlzlookup { 114 /* Unlocked */ 115 unsigned int magic; 116 dns_sdlz_db_t *sdlz; 117 ISC_LIST(dns_rdatalist_t) lists; 118 ISC_LIST(isc_buffer_t) buffers; 119 dns_name_t *name; 120 ISC_LINK(dns_sdlzlookup_t) link; 121 isc_mutex_t lock; 122 dns_rdatacallbacks_t callbacks; 123 /* Locked */ 124 unsigned int references; 125}; 126 127typedef struct dns_sdlzlookup dns_sdlznode_t; 128 129struct dns_sdlzallnodes { 130 dns_dbiterator_t common; 131 ISC_LIST(dns_sdlznode_t) nodelist; 132 dns_sdlznode_t *current; 133 dns_sdlznode_t *origin; 134}; 135 136typedef dns_sdlzallnodes_t sdlz_dbiterator_t; 137 138typedef struct sdlz_rdatasetiter { 139 dns_rdatasetiter_t common; 140 dns_rdatalist_t *current; 141} sdlz_rdatasetiter_t; 142 143 144#define SDLZDB_MAGIC ISC_MAGIC('D', 'L', 'Z', 'S') 145 146/* 147 * Note that "impmagic" is not the first four bytes of the struct, so 148 * ISC_MAGIC_VALID cannot be used. 149 */ 150 151#define VALID_SDLZDB(sdlzdb) ((sdlzdb) != NULL && \ 152 (sdlzdb)->common.impmagic == SDLZDB_MAGIC) 153 154#define SDLZLOOKUP_MAGIC ISC_MAGIC('D','L','Z','L') 155#define VALID_SDLZLOOKUP(sdlzl) ISC_MAGIC_VALID(sdlzl, SDLZLOOKUP_MAGIC) 156#define VALID_SDLZNODE(sdlzn) VALID_SDLZLOOKUP(sdlzn) 157 158/* These values are taken from RFC 1537 */ 159#define SDLZ_DEFAULT_REFRESH (60 * 60 * 8) 160#define SDLZ_DEFAULT_RETRY (60 * 60 * 2) 161#define SDLZ_DEFAULT_EXPIRE (60 * 60 * 24 * 7) 162#define SDLZ_DEFAULT_MINIMUM (60 * 60 * 24) 163 164/* This is a reasonable value */ 165#define SDLZ_DEFAULT_TTL (60 * 60 * 24) 166 167static int dummy; 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/*% Converts the input string to lowercase, in place. */ 229 230static void 231dns_sdlz_tolower(char *str) { 232 233 unsigned int len = strlen(str); 234 unsigned int i; 235 236 for (i = 0; i < len; i++) { 237 if (str[i] >= 'A' && str[i] <= 'Z') 238 str[i] += 32; 239 } 240 241} 242 243static inline unsigned int 244initial_size(const char *data) { 245 unsigned int len = (strlen(data) / 64) + 1; 246 return (len * 64 + 64); 247} 248 249/* 250 * Rdataset Iterator Methods. These methods were "borrowed" from the SDB 251 * driver interface. See the SDB driver interface documentation for more info. 252 */ 253 254static void 255rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) { 256 sdlz_rdatasetiter_t *sdlziterator = 257 (sdlz_rdatasetiter_t *)(*iteratorp); 258 259 detachnode(sdlziterator->common.db, &sdlziterator->common.node); 260 isc_mem_put(sdlziterator->common.db->mctx, sdlziterator, 261 sizeof(sdlz_rdatasetiter_t)); 262 *iteratorp = NULL; 263} 264 265static isc_result_t 266rdatasetiter_first(dns_rdatasetiter_t *iterator) { 267 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator; 268 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)iterator->node; 269 270 if (ISC_LIST_EMPTY(sdlznode->lists)) 271 return (ISC_R_NOMORE); 272 sdlziterator->current = ISC_LIST_HEAD(sdlznode->lists); 273 return (ISC_R_SUCCESS); 274} 275 276static isc_result_t 277rdatasetiter_next(dns_rdatasetiter_t *iterator) { 278 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator; 279 280 sdlziterator->current = ISC_LIST_NEXT(sdlziterator->current, link); 281 if (sdlziterator->current == NULL) 282 return (ISC_R_NOMORE); 283 else 284 return (ISC_R_SUCCESS); 285} 286 287static void 288rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) { 289 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator; 290 291 list_tordataset(sdlziterator->current, iterator->db, iterator->node, 292 rdataset); 293} 294 295static dns_rdatasetitermethods_t rdatasetiter_methods = { 296 rdatasetiter_destroy, 297 rdatasetiter_first, 298 rdatasetiter_next, 299 rdatasetiter_current 300}; 301 302/* 303 * DB routines. These methods were "borrowed" from the SDB driver interface. 304 * See the SDB driver interface documentation for more info. 305 */ 306 307static void 308attach(dns_db_t *source, dns_db_t **targetp) { 309 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) source; 310 311 REQUIRE(VALID_SDLZDB(sdlz)); 312 313 LOCK(&sdlz->refcnt_lock); 314 REQUIRE(sdlz->references > 0); 315 sdlz->references++; 316 UNLOCK(&sdlz->refcnt_lock); 317 318 *targetp = source; 319} 320 321static void 322destroy(dns_sdlz_db_t *sdlz) { 323 isc_mem_t *mctx; 324 mctx = sdlz->common.mctx; 325 326 sdlz->common.magic = 0; 327 sdlz->common.impmagic = 0; 328 329 isc_mutex_destroy(&sdlz->refcnt_lock); 330 331 dns_name_free(&sdlz->common.origin, mctx); 332 333 isc_mem_put(mctx, sdlz, sizeof(dns_sdlz_db_t)); 334 isc_mem_detach(&mctx); 335} 336 337static void 338detach(dns_db_t **dbp) { 339 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)(*dbp); 340 isc_boolean_t need_destroy = ISC_FALSE; 341 342 REQUIRE(VALID_SDLZDB(sdlz)); 343 LOCK(&sdlz->refcnt_lock); 344 REQUIRE(sdlz->references > 0); 345 sdlz->references--; 346 if (sdlz->references == 0) 347 need_destroy = ISC_TRUE; 348 UNLOCK(&sdlz->refcnt_lock); 349 350 if (need_destroy) 351 destroy(sdlz); 352 353 *dbp = NULL; 354} 355 356static isc_result_t 357beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) { 358 UNUSED(db); 359 UNUSED(addp); 360 UNUSED(dbloadp); 361 return (ISC_R_NOTIMPLEMENTED); 362} 363 364static isc_result_t 365endload(dns_db_t *db, dns_dbload_t **dbloadp) { 366 UNUSED(db); 367 UNUSED(dbloadp); 368 return (ISC_R_NOTIMPLEMENTED); 369} 370 371static isc_result_t 372dump(dns_db_t *db, dns_dbversion_t *version, const char *filename, 373 dns_masterformat_t masterformat) 374{ 375 UNUSED(db); 376 UNUSED(version); 377 UNUSED(filename); 378 UNUSED(masterformat); 379 return (ISC_R_NOTIMPLEMENTED); 380} 381 382static void 383currentversion(dns_db_t *db, dns_dbversion_t **versionp) { 384 REQUIRE(versionp != NULL && *versionp == NULL); 385 386 UNUSED(db); 387 388 *versionp = (void *) &dummy; 389 return; 390} 391 392static isc_result_t 393newversion(dns_db_t *db, dns_dbversion_t **versionp) { 394 UNUSED(db); 395 UNUSED(versionp); 396 397 return (ISC_R_NOTIMPLEMENTED); 398} 399 400static void 401attachversion(dns_db_t *db, dns_dbversion_t *source, 402 dns_dbversion_t **targetp) 403{ 404 REQUIRE(source != NULL && source == (void *) &dummy); 405 406 UNUSED(db); 407 UNUSED(source); 408 UNUSED(targetp); 409 *targetp = source; 410} 411 412static void 413closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { 414 REQUIRE(versionp != NULL && *versionp == (void *) &dummy); 415 REQUIRE(commit == ISC_FALSE); 416 417 UNUSED(db); 418 UNUSED(commit); 419 420 *versionp = NULL; 421} 422 423static isc_result_t 424createnode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) { 425 dns_sdlznode_t *node; 426 isc_result_t result; 427 428 node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t)); 429 if (node == NULL) 430 return (ISC_R_NOMEMORY); 431 432 node->sdlz = NULL; 433 attach((dns_db_t *)sdlz, (dns_db_t **)&node->sdlz); 434 ISC_LIST_INIT(node->lists); 435 ISC_LIST_INIT(node->buffers); 436 ISC_LINK_INIT(node, link); 437 node->name = NULL; 438 result = isc_mutex_init(&node->lock); 439 if (result != ISC_R_SUCCESS) { 440 UNEXPECTED_ERROR(__FILE__, __LINE__, 441 "isc_mutex_init() failed: %s", 442 isc_result_totext(result)); 443 isc_mem_put(sdlz->common.mctx, node, sizeof(dns_sdlznode_t)); 444 return (ISC_R_UNEXPECTED); 445 } 446 dns_rdatacallbacks_init(&node->callbacks); 447 node->references = 1; 448 node->magic = SDLZLOOKUP_MAGIC; 449 450 *nodep = node; 451 return (ISC_R_SUCCESS); 452} 453 454static void 455destroynode(dns_sdlznode_t *node) { 456 dns_rdatalist_t *list; 457 dns_rdata_t *rdata; 458 isc_buffer_t *b; 459 dns_sdlz_db_t *sdlz; 460 dns_db_t *db; 461 isc_mem_t *mctx; 462 463 sdlz = node->sdlz; 464 mctx = sdlz->common.mctx; 465 466 while (!ISC_LIST_EMPTY(node->lists)) { 467 list = ISC_LIST_HEAD(node->lists); 468 while (!ISC_LIST_EMPTY(list->rdata)) { 469 rdata = ISC_LIST_HEAD(list->rdata); 470 ISC_LIST_UNLINK(list->rdata, rdata, link); 471 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t)); 472 } 473 ISC_LIST_UNLINK(node->lists, list, link); 474 isc_mem_put(mctx, list, sizeof(dns_rdatalist_t)); 475 } 476 477 while (!ISC_LIST_EMPTY(node->buffers)) { 478 b = ISC_LIST_HEAD(node->buffers); 479 ISC_LIST_UNLINK(node->buffers, b, link); 480 isc_buffer_free(&b); 481 } 482 483 if (node->name != NULL) { 484 dns_name_free(node->name, mctx); 485 isc_mem_put(mctx, node->name, sizeof(dns_name_t)); 486 } 487 DESTROYLOCK(&node->lock); 488 node->magic = 0; 489 isc_mem_put(mctx, node, sizeof(dns_sdlznode_t)); 490 db = &sdlz->common; 491 detach(&db); 492} 493 494static isc_result_t 495findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create, 496 dns_dbnode_t **nodep) 497{ 498 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 499 dns_sdlznode_t *node = NULL; 500 isc_result_t result; 501 isc_buffer_t b; 502 char namestr[DNS_NAME_MAXTEXT + 1]; 503 isc_buffer_t b2; 504 char zonestr[DNS_NAME_MAXTEXT + 1]; 505 isc_boolean_t isorigin; 506 dns_sdlzauthorityfunc_t authority; 507 508 REQUIRE(VALID_SDLZDB(sdlz)); 509 REQUIRE(create == ISC_FALSE); 510 REQUIRE(nodep != NULL && *nodep == NULL); 511 512 UNUSED(name); 513 UNUSED(create); 514 515 isc_buffer_init(&b, namestr, sizeof(namestr)); 516 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) { 517 dns_name_t relname; 518 unsigned int labels; 519 520 labels = dns_name_countlabels(name) - 521 dns_name_countlabels(&db->origin); 522 dns_name_init(&relname, NULL); 523 dns_name_getlabelsequence(name, 0, labels, &relname); 524 result = dns_name_totext(&relname, ISC_TRUE, &b); 525 if (result != ISC_R_SUCCESS) 526 return (result); 527 } else { 528 result = dns_name_totext(name, ISC_TRUE, &b); 529 if (result != ISC_R_SUCCESS) 530 return (result); 531 } 532 isc_buffer_putuint8(&b, 0); 533 534 isc_buffer_init(&b2, zonestr, sizeof(zonestr)); 535 result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b2); 536 if (result != ISC_R_SUCCESS) 537 return (result); 538 isc_buffer_putuint8(&b2, 0); 539 540 result = createnode(sdlz, &node); 541 if (result != ISC_R_SUCCESS) 542 return (result); 543 544 isorigin = dns_name_equal(name, &sdlz->common.origin); 545 546 /* make sure strings are always lowercase */ 547 dns_sdlz_tolower(zonestr); 548 dns_sdlz_tolower(namestr); 549 550 MAYBE_LOCK(sdlz->dlzimp); 551 552 /* try to lookup the host (namestr) */ 553 result = sdlz->dlzimp->methods->lookup(zonestr, namestr, 554 sdlz->dlzimp->driverarg, 555 sdlz->dbdata, node); 556 557 /* 558 * if the host (namestr) was not found, try to lookup a 559 * "wildcard" host. 560 */ 561 if (result != ISC_R_SUCCESS) { 562 result = sdlz->dlzimp->methods->lookup(zonestr, "*", 563 sdlz->dlzimp->driverarg, 564 sdlz->dbdata, node); 565 } 566 567 MAYBE_UNLOCK(sdlz->dlzimp); 568 569 if (result != ISC_R_SUCCESS && !isorigin) { 570 destroynode(node); 571 return (result); 572 } 573 574 if (isorigin && sdlz->dlzimp->methods->authority != NULL) { 575 MAYBE_LOCK(sdlz->dlzimp); 576 authority = sdlz->dlzimp->methods->authority; 577 result = (*authority)(zonestr, sdlz->dlzimp->driverarg, 578 sdlz->dbdata, node); 579 MAYBE_UNLOCK(sdlz->dlzimp); 580 if (result != ISC_R_SUCCESS && 581 result != ISC_R_NOTIMPLEMENTED) { 582 destroynode(node); 583 return (result); 584 } 585 } 586 587 *nodep = node; 588 return (ISC_R_SUCCESS); 589} 590 591static isc_result_t 592findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options, 593 isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname, 594 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 595{ 596 UNUSED(db); 597 UNUSED(name); 598 UNUSED(options); 599 UNUSED(now); 600 UNUSED(nodep); 601 UNUSED(foundname); 602 UNUSED(rdataset); 603 UNUSED(sigrdataset); 604 605 return (ISC_R_NOTIMPLEMENTED); 606} 607 608static void 609attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) { 610 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 611 dns_sdlznode_t *node = (dns_sdlznode_t *)source; 612 613 REQUIRE(VALID_SDLZDB(sdlz)); 614 615 UNUSED(sdlz); 616 617 LOCK(&node->lock); 618 INSIST(node->references > 0); 619 node->references++; 620 INSIST(node->references != 0); /* Catch overflow. */ 621 UNLOCK(&node->lock); 622 623 *targetp = source; 624} 625 626static void 627detachnode(dns_db_t *db, dns_dbnode_t **targetp) { 628 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 629 dns_sdlznode_t *node; 630 isc_boolean_t need_destroy = ISC_FALSE; 631 632 REQUIRE(VALID_SDLZDB(sdlz)); 633 REQUIRE(targetp != NULL && *targetp != NULL); 634 635 UNUSED(sdlz); 636 637 node = (dns_sdlznode_t *)(*targetp); 638 639 LOCK(&node->lock); 640 INSIST(node->references > 0); 641 node->references--; 642 if (node->references == 0) 643 need_destroy = ISC_TRUE; 644 UNLOCK(&node->lock); 645 646 if (need_destroy) 647 destroynode(node); 648 649 *targetp = NULL; 650} 651 652static isc_result_t 653expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) { 654 UNUSED(db); 655 UNUSED(node); 656 UNUSED(now); 657 INSIST(0); 658 return (ISC_R_UNEXPECTED); 659} 660 661static void 662printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) { 663 UNUSED(db); 664 UNUSED(node); 665 UNUSED(out); 666 return; 667} 668 669static isc_result_t 670createiterator(dns_db_t *db, isc_boolean_t relative_names, 671 dns_dbiterator_t **iteratorp) 672{ 673 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 674 sdlz_dbiterator_t *sdlziter; 675 isc_result_t result; 676 isc_buffer_t b; 677 char zonestr[DNS_NAME_MAXTEXT + 1]; 678 679 REQUIRE(VALID_SDLZDB(sdlz)); 680 681 if (sdlz->dlzimp->methods->allnodes == NULL) 682 return (ISC_R_NOTIMPLEMENTED); 683 684 isc_buffer_init(&b, zonestr, sizeof(zonestr)); 685 result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b); 686 if (result != ISC_R_SUCCESS) 687 return (result); 688 isc_buffer_putuint8(&b, 0); 689 690 sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t)); 691 if (sdlziter == NULL) 692 return (ISC_R_NOMEMORY); 693 694 sdlziter->common.methods = &dbiterator_methods; 695 sdlziter->common.db = NULL; 696 dns_db_attach(db, &sdlziter->common.db); 697 sdlziter->common.relative_names = relative_names; 698 sdlziter->common.magic = DNS_DBITERATOR_MAGIC; 699 ISC_LIST_INIT(sdlziter->nodelist); 700 sdlziter->current = NULL; 701 sdlziter->origin = NULL; 702 703 /* make sure strings are always lowercase */ 704 dns_sdlz_tolower(zonestr); 705 706 MAYBE_LOCK(sdlz->dlzimp); 707 result = sdlz->dlzimp->methods->allnodes(zonestr, 708 sdlz->dlzimp->driverarg, 709 sdlz->dbdata, sdlziter); 710 MAYBE_UNLOCK(sdlz->dlzimp); 711 if (result != ISC_R_SUCCESS) { 712 dns_dbiterator_t *iter = &sdlziter->common; 713 dbiterator_destroy(&iter); 714 return (result); 715 } 716 717 if (sdlziter->origin != NULL) { 718 ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link); 719 ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link); 720 } 721 722 *iteratorp = (dns_dbiterator_t *)sdlziter; 723 724 return (ISC_R_SUCCESS); 725} 726 727static isc_result_t 728findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 729 dns_rdatatype_t type, dns_rdatatype_t covers, 730 isc_stdtime_t now, dns_rdataset_t *rdataset, 731 dns_rdataset_t *sigrdataset) 732{ 733 dns_rdatalist_t *list; 734 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node; 735 736 REQUIRE(VALID_SDLZNODE(node)); 737 738 UNUSED(db); 739 UNUSED(version); 740 UNUSED(covers); 741 UNUSED(now); 742 UNUSED(sigrdataset); 743 744 if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig) 745 return (ISC_R_NOTIMPLEMENTED); 746 747 list = ISC_LIST_HEAD(sdlznode->lists); 748 while (list != NULL) { 749 if (list->type == type) 750 break; 751 list = ISC_LIST_NEXT(list, link); 752 } 753 if (list == NULL) 754 return (ISC_R_NOTFOUND); 755 756 list_tordataset(list, db, node, rdataset); 757 758 return (ISC_R_SUCCESS); 759} 760 761static isc_result_t 762find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, 763 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, 764 dns_dbnode_t **nodep, dns_name_t *foundname, 765 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 766{ 767 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 768 dns_dbnode_t *node = NULL; 769 dns_fixedname_t fname; 770 dns_rdataset_t xrdataset; 771 dns_name_t *xname; 772 unsigned int nlabels, olabels; 773 isc_result_t result; 774 unsigned int i; 775 776 REQUIRE(VALID_SDLZDB(sdlz)); 777 REQUIRE(nodep == NULL || *nodep == NULL); 778 REQUIRE(version == NULL || version == (void *) &dummy); 779 780 UNUSED(options); 781 UNUSED(sdlz); 782 783 if (!dns_name_issubdomain(name, &db->origin)) 784 return (DNS_R_NXDOMAIN); 785 786 olabels = dns_name_countlabels(&db->origin); 787 nlabels = dns_name_countlabels(name); 788 789 dns_fixedname_init(&fname); 790 xname = dns_fixedname_name(&fname); 791 792 if (rdataset == NULL) { 793 dns_rdataset_init(&xrdataset); 794 rdataset = &xrdataset; 795 } 796 797 result = DNS_R_NXDOMAIN; 798 799 for (i = olabels; i <= nlabels; i++) { 800 /* 801 * Unless this is an explicit lookup at the origin, don't 802 * look at the origin. 803 */ 804 if (i == olabels && i != nlabels) 805 continue; 806 807 /* 808 * Look up the next label. 809 */ 810 dns_name_getlabelsequence(name, nlabels - i, i, xname); 811 result = findnode(db, xname, ISC_FALSE, &node); 812 if (result != ISC_R_SUCCESS) { 813 result = DNS_R_NXDOMAIN; 814 continue; 815 } 816 817 /* 818 * Look for a DNAME at the current label, unless this is 819 * the qname. 820 */ 821 if (i < nlabels) { 822 result = findrdataset(db, node, version, 823 dns_rdatatype_dname, 824 0, now, rdataset, sigrdataset); 825 if (result == ISC_R_SUCCESS) { 826 result = DNS_R_DNAME; 827 break; 828 } 829 } 830 831 /* 832 * Look for an NS at the current label, unless this is the 833 * origin or glue is ok. 834 */ 835 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) { 836 result = findrdataset(db, node, version, 837 dns_rdatatype_ns, 838 0, now, rdataset, sigrdataset); 839 if (result == ISC_R_SUCCESS) { 840 if (i == nlabels && type == dns_rdatatype_any) 841 { 842 result = DNS_R_ZONECUT; 843 dns_rdataset_disassociate(rdataset); 844 if (sigrdataset != NULL) 845 dns_rdataset_disassociate 846 (sigrdataset); 847 } else 848 result = DNS_R_DELEGATION; 849 break; 850 } 851 } 852 853 /* 854 * If the current name is not the qname, add another label 855 * and try again. 856 */ 857 if (i < nlabels) { 858 destroynode(node); 859 node = NULL; 860 continue; 861 } 862 863 /* 864 * If we're looking for ANY, we're done. 865 */ 866 if (type == dns_rdatatype_any) { 867 result = ISC_R_SUCCESS; 868 break; 869 } 870 871 /* 872 * Look for the qtype. 873 */ 874 result = findrdataset(db, node, version, type, 875 0, now, rdataset, sigrdataset); 876 if (result == ISC_R_SUCCESS) 877 break; 878 879 /* 880 * Look for a CNAME 881 */ 882 if (type != dns_rdatatype_cname) { 883 result = findrdataset(db, node, version, 884 dns_rdatatype_cname, 885 0, now, rdataset, sigrdataset); 886 if (result == ISC_R_SUCCESS) { 887 result = DNS_R_CNAME; 888 break; 889 } 890 } 891 892 result = DNS_R_NXRRSET; 893 break; 894 } 895 896 if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) 897 dns_rdataset_disassociate(rdataset); 898 899 if (foundname != NULL) { 900 isc_result_t xresult; 901 902 xresult = dns_name_copy(xname, foundname, NULL); 903 if (xresult != ISC_R_SUCCESS) { 904 if (node != NULL) 905 destroynode(node); 906 if (dns_rdataset_isassociated(rdataset)) 907 dns_rdataset_disassociate(rdataset); 908 return (DNS_R_BADDB); 909 } 910 } 911 912 if (nodep != NULL) 913 *nodep = node; 914 else if (node != NULL) 915 detachnode(db, &node); 916 917 return (result); 918} 919 920static isc_result_t 921allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 922 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) 923{ 924 sdlz_rdatasetiter_t *iterator; 925 926 REQUIRE(version == NULL || version == &dummy); 927 928 UNUSED(version); 929 UNUSED(now); 930 931 iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t)); 932 if (iterator == NULL) 933 return (ISC_R_NOMEMORY); 934 935 iterator->common.magic = DNS_RDATASETITER_MAGIC; 936 iterator->common.methods = &rdatasetiter_methods; 937 iterator->common.db = db; 938 iterator->common.node = NULL; 939 attachnode(db, node, &iterator->common.node); 940 iterator->common.version = version; 941 iterator->common.now = now; 942 943 *iteratorp = (dns_rdatasetiter_t *)iterator; 944 945 return (ISC_R_SUCCESS); 946} 947 948static isc_result_t 949addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 950 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, 951 dns_rdataset_t *addedrdataset) 952{ 953 UNUSED(db); 954 UNUSED(node); 955 UNUSED(version); 956 UNUSED(now); 957 UNUSED(rdataset); 958 UNUSED(options); 959 UNUSED(addedrdataset); 960 961 return (ISC_R_NOTIMPLEMENTED); 962} 963 964static isc_result_t 965subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 966 dns_rdataset_t *rdataset, unsigned int options, 967 dns_rdataset_t *newrdataset) 968{ 969 UNUSED(db); 970 UNUSED(node); 971 UNUSED(version); 972 UNUSED(rdataset); 973 UNUSED(options); 974 UNUSED(newrdataset); 975 976 return (ISC_R_NOTIMPLEMENTED); 977} 978 979static isc_result_t 980deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 981 dns_rdatatype_t type, dns_rdatatype_t covers) 982{ 983 UNUSED(db); 984 UNUSED(node); 985 UNUSED(version); 986 UNUSED(type); 987 UNUSED(covers); 988 989 return (ISC_R_NOTIMPLEMENTED); 990} 991 992static isc_boolean_t 993issecure(dns_db_t *db) { 994 UNUSED(db); 995 996 return (ISC_FALSE); 997} 998 999static unsigned int 1000nodecount(dns_db_t *db) { 1001 UNUSED(db); 1002 1003 return (0); 1004} 1005 1006static isc_boolean_t 1007ispersistent(dns_db_t *db) { 1008 UNUSED(db); 1009 return (ISC_TRUE); 1010} 1011 1012static void 1013overmem(dns_db_t *db, isc_boolean_t overmem) { 1014 UNUSED(db); 1015 UNUSED(overmem); 1016} 1017 1018static void 1019settask(dns_db_t *db, isc_task_t *task) { 1020 UNUSED(db); 1021 UNUSED(task); 1022} 1023 1024 1025static dns_dbmethods_t sdlzdb_methods = { 1026 attach, 1027 detach, 1028 beginload, 1029 endload, 1030 dump, 1031 currentversion, 1032 newversion, 1033 attachversion, 1034 closeversion, 1035 findnode, 1036 find, 1037 findzonecut, 1038 attachnode, 1039 detachnode, 1040 expirenode, 1041 printnode, 1042 createiterator, 1043 findrdataset, 1044 allrdatasets, 1045 addrdataset, 1046 subtractrdataset, 1047 deleterdataset, 1048 issecure, 1049 nodecount, 1050 ispersistent, 1051 overmem, 1052 settask, 1053 NULL, 1054}; 1055 1056/* 1057 * Database Iterator Methods. These methods were "borrowed" from the SDB 1058 * driver interface. See the SDB driver interface documentation for more info. 1059 */ 1060 1061static void 1062dbiterator_destroy(dns_dbiterator_t **iteratorp) { 1063 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp); 1064 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db; 1065 1066 while (!ISC_LIST_EMPTY(sdlziter->nodelist)) { 1067 dns_sdlznode_t *node; 1068 node = ISC_LIST_HEAD(sdlziter->nodelist); 1069 ISC_LIST_UNLINK(sdlziter->nodelist, node, link); 1070 destroynode(node); 1071 } 1072 1073 dns_db_detach(&sdlziter->common.db); 1074 isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t)); 1075 1076 *iteratorp = NULL; 1077} 1078 1079static isc_result_t 1080dbiterator_first(dns_dbiterator_t *iterator) { 1081 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1082 1083 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist); 1084 if (sdlziter->current == NULL) 1085 return (ISC_R_NOMORE); 1086 else 1087 return (ISC_R_SUCCESS); 1088} 1089 1090static isc_result_t 1091dbiterator_last(dns_dbiterator_t *iterator) { 1092 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1093 1094 sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist); 1095 if (sdlziter->current == NULL) 1096 return (ISC_R_NOMORE); 1097 else 1098 return (ISC_R_SUCCESS); 1099} 1100 1101static isc_result_t 1102dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) { 1103 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1104 1105 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist); 1106 while (sdlziter->current != NULL) 1107 if (dns_name_equal(sdlziter->current->name, name)) 1108 return (ISC_R_SUCCESS); 1109 return (ISC_R_NOTFOUND); 1110} 1111 1112static isc_result_t 1113dbiterator_prev(dns_dbiterator_t *iterator) { 1114 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1115 1116 sdlziter->current = ISC_LIST_PREV(sdlziter->current, link); 1117 if (sdlziter->current == NULL) 1118 return (ISC_R_NOMORE); 1119 else 1120 return (ISC_R_SUCCESS); 1121} 1122 1123static isc_result_t 1124dbiterator_next(dns_dbiterator_t *iterator) { 1125 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1126 1127 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link); 1128 if (sdlziter->current == NULL) 1129 return (ISC_R_NOMORE); 1130 else 1131 return (ISC_R_SUCCESS); 1132} 1133 1134static isc_result_t 1135dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, 1136 dns_name_t *name) 1137{ 1138 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1139 1140 attachnode(iterator->db, sdlziter->current, nodep); 1141 if (name != NULL) 1142 return (dns_name_copy(sdlziter->current->name, name, NULL)); 1143 return (ISC_R_SUCCESS); 1144} 1145 1146static isc_result_t 1147dbiterator_pause(dns_dbiterator_t *iterator) { 1148 UNUSED(iterator); 1149 return (ISC_R_SUCCESS); 1150} 1151 1152static isc_result_t 1153dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) { 1154 UNUSED(iterator); 1155 return (dns_name_copy(dns_rootname, name, NULL)); 1156} 1157 1158/* 1159 * Rdataset Methods. These methods were "borrowed" from the SDB driver 1160 * interface. See the SDB driver interface documentation for more info. 1161 */ 1162 1163static void 1164disassociate(dns_rdataset_t *rdataset) { 1165 dns_dbnode_t *node = rdataset->private5; 1166 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node; 1167 dns_db_t *db = (dns_db_t *) sdlznode->sdlz; 1168 1169 detachnode(db, &node); 1170 isc__rdatalist_disassociate(rdataset); 1171} 1172 1173static void 1174rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 1175 dns_dbnode_t *node = source->private5; 1176 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node; 1177 dns_db_t *db = (dns_db_t *) sdlznode->sdlz; 1178 dns_dbnode_t *tempdb = NULL; 1179 1180 isc__rdatalist_clone(source, target); 1181 attachnode(db, node, &tempdb); 1182 source->private5 = tempdb; 1183} 1184 1185static dns_rdatasetmethods_t rdataset_methods = { 1186 disassociate, 1187 isc__rdatalist_first, 1188 isc__rdatalist_next, 1189 isc__rdatalist_current, 1190 rdataset_clone, 1191 isc__rdatalist_count, 1192 isc__rdatalist_addnoqname, 1193 isc__rdatalist_getnoqname, 1194 NULL, 1195 NULL, 1196 NULL 1197}; 1198 1199static void 1200list_tordataset(dns_rdatalist_t *rdatalist, 1201 dns_db_t *db, dns_dbnode_t *node, 1202 dns_rdataset_t *rdataset) 1203{ 1204 /* 1205 * The sdlz rdataset is an rdatalist with some additions. 1206 * - private1 & private2 are used by the rdatalist. 1207 * - private3 & private 4 are unused. 1208 * - private5 is the node. 1209 */ 1210 1211 /* This should never fail. */ 1212 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == 1213 ISC_R_SUCCESS); 1214 1215 rdataset->methods = &rdataset_methods; 1216 dns_db_attachnode(db, node, &rdataset->private5); 1217} 1218 1219/* 1220 * SDLZ core methods. This is the core of the new DLZ functionality. 1221 */ 1222 1223/*% 1224 * Build a 'bind' database driver structure to be returned by 1225 * either the find zone or the allow zone transfer method. 1226 * This method is only available in this source file, it is 1227 * not made available anywhere else. 1228 */ 1229 1230static isc_result_t 1231dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata, 1232 dns_name_t *name, dns_rdataclass_t rdclass, dns_db_t **dbp) 1233{ 1234 isc_result_t result; 1235 dns_sdlz_db_t *sdlzdb; 1236 dns_sdlzimplementation_t *imp; 1237 1238 /* check that things are as we expect */ 1239 REQUIRE(dbp != NULL && *dbp == NULL); 1240 REQUIRE(name != NULL); 1241 1242 imp = (dns_sdlzimplementation_t *) driverarg; 1243 1244 /* allocate and zero memory for driver structure */ 1245 sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t)); 1246 if (sdlzdb == NULL) 1247 return (ISC_R_NOMEMORY); 1248 memset(sdlzdb, 0, sizeof(dns_sdlz_db_t)); 1249 1250 /* initialize and set origin */ 1251 dns_name_init(&sdlzdb->common.origin, NULL); 1252 result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin); 1253 if (result != ISC_R_SUCCESS) 1254 goto mem_cleanup; 1255 1256 /* initialize the reference count mutex */ 1257 result = isc_mutex_init(&sdlzdb->refcnt_lock); 1258 if (result != ISC_R_SUCCESS) 1259 goto name_cleanup; 1260 1261 /* set the rest of the database structure attributes */ 1262 sdlzdb->dlzimp = imp; 1263 sdlzdb->common.methods = &sdlzdb_methods; 1264 sdlzdb->common.attributes = 0; 1265 sdlzdb->common.rdclass = rdclass; 1266 sdlzdb->common.mctx = NULL; 1267 sdlzdb->dbdata = dbdata; 1268 sdlzdb->references = 1; 1269 1270 /* attach to the memory context */ 1271 isc_mem_attach(mctx, &sdlzdb->common.mctx); 1272 1273 /* mark structure as valid */ 1274 sdlzdb->common.magic = DNS_DB_MAGIC; 1275 sdlzdb->common.impmagic = SDLZDB_MAGIC; 1276 *dbp = (dns_db_t *) sdlzdb; 1277 1278 return (result); 1279 1280 /* 1281 * reference count mutex could not be initialized, clean up 1282 * name memory 1283 */ 1284 name_cleanup: 1285 dns_name_free(&sdlzdb->common.origin, mctx); 1286 mem_cleanup: 1287 isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t)); 1288 return (result); 1289} 1290 1291static isc_result_t 1292dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx, 1293 dns_rdataclass_t rdclass, dns_name_t *name, 1294 isc_sockaddr_t *clientaddr, dns_db_t **dbp) 1295{ 1296 isc_buffer_t b; 1297 isc_buffer_t b2; 1298 char namestr[DNS_NAME_MAXTEXT + 1]; 1299 char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255") 1300 + 1]; 1301 isc_netaddr_t netaddr; 1302 isc_result_t result; 1303 dns_sdlzimplementation_t *imp; 1304 1305 /* 1306 * Perform checks to make sure data is as we expect it to be. 1307 */ 1308 REQUIRE(driverarg != NULL); 1309 REQUIRE(name != NULL); 1310 REQUIRE(clientaddr != NULL); 1311 REQUIRE(dbp != NULL && *dbp == NULL); 1312 1313 imp = (dns_sdlzimplementation_t *) driverarg; 1314 1315 /* Convert DNS name to ascii text */ 1316 isc_buffer_init(&b, namestr, sizeof(namestr)); 1317 result = dns_name_totext(name, ISC_TRUE, &b); 1318 if (result != ISC_R_SUCCESS) 1319 return (result); 1320 isc_buffer_putuint8(&b, 0); 1321 1322 /* convert client address to ascii text */ 1323 isc_buffer_init(&b2, clientstr, sizeof(clientstr)); 1324 isc_netaddr_fromsockaddr(&netaddr, clientaddr); 1325 result = isc_netaddr_totext(&netaddr, &b2); 1326 if (result != ISC_R_SUCCESS) 1327 return (result); 1328 isc_buffer_putuint8(&b2, 0); 1329 1330 /* make sure strings are always lowercase */ 1331 dns_sdlz_tolower(namestr); 1332 dns_sdlz_tolower(clientstr); 1333 1334 /* Call SDLZ driver's find zone method */ 1335 if (imp->methods->allowzonexfr != NULL) { 1336 MAYBE_LOCK(imp); 1337 result = imp->methods->allowzonexfr(imp->driverarg, dbdata, 1338 namestr, clientstr); 1339 MAYBE_UNLOCK(imp); 1340 /* 1341 * if zone is supported and transfers allowed build a 'bind' 1342 * database driver 1343 */ 1344 if (result == ISC_R_SUCCESS) 1345 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, 1346 name, rdclass, dbp); 1347 return (result); 1348 } 1349 1350 return (ISC_R_NOTIMPLEMENTED); 1351} 1352 1353static isc_result_t 1354dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc, 1355 char *argv[], void *driverarg, void **dbdata) 1356{ 1357 dns_sdlzimplementation_t *imp; 1358 isc_result_t result = ISC_R_NOTFOUND; 1359 1360 /* Write debugging message to log */ 1361 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 1362 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), 1363 "Loading SDLZ driver."); 1364 1365 /* 1366 * Performs checks to make sure data is as we expect it to be. 1367 */ 1368 REQUIRE(driverarg != NULL); 1369 REQUIRE(dlzname != NULL); 1370 REQUIRE(dbdata != NULL); 1371 UNUSED(mctx); 1372 1373 imp = driverarg; 1374 1375 /* If the create method exists, call it. */ 1376 if (imp->methods->create != NULL) { 1377 MAYBE_LOCK(imp); 1378 result = imp->methods->create(dlzname, argc, argv, 1379 imp->driverarg, dbdata); 1380 MAYBE_UNLOCK(imp); 1381 } 1382 1383 /* Write debugging message to log */ 1384 if (result == ISC_R_SUCCESS) { 1385 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 1386 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), 1387 "SDLZ driver loaded successfully."); 1388 } else { 1389 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 1390 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, 1391 "SDLZ driver failed to load."); 1392 } 1393 1394 return (result); 1395} 1396 1397static void 1398dns_sdlzdestroy(void *driverdata, void **dbdata) 1399{ 1400 1401 dns_sdlzimplementation_t *imp; 1402 1403 /* Write debugging message to log */ 1404 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 1405 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), 1406 "Unloading SDLZ driver."); 1407 1408 imp = driverdata; 1409 1410 /* If the destroy method exists, call it. */ 1411 if (imp->methods->destroy != NULL) { 1412 MAYBE_LOCK(imp); 1413 imp->methods->destroy(imp->driverarg, dbdata); 1414 MAYBE_UNLOCK(imp); 1415 } 1416} 1417 1418static isc_result_t 1419dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx, 1420 dns_rdataclass_t rdclass, dns_name_t *name, dns_db_t **dbp) 1421{ 1422 isc_buffer_t b; 1423 char namestr[DNS_NAME_MAXTEXT + 1]; 1424 isc_result_t result; 1425 dns_sdlzimplementation_t *imp; 1426 1427 /* 1428 * Perform checks to make sure data is as we expect it to be. 1429 */ 1430 REQUIRE(driverarg != NULL); 1431 REQUIRE(name != NULL); 1432 REQUIRE(dbp != NULL && *dbp == NULL); 1433 1434 imp = (dns_sdlzimplementation_t *) driverarg; 1435 1436 /* Convert DNS name to ascii text */ 1437 isc_buffer_init(&b, namestr, sizeof(namestr)); 1438 result = dns_name_totext(name, ISC_TRUE, &b); 1439 if (result != ISC_R_SUCCESS) 1440 return (result); 1441 isc_buffer_putuint8(&b, 0); 1442 1443 /* make sure strings are always lowercase */ 1444 dns_sdlz_tolower(namestr); 1445 1446 /* Call SDLZ driver's find zone method */ 1447 MAYBE_LOCK(imp); 1448 result = imp->methods->findzone(imp->driverarg, dbdata, namestr); 1449 MAYBE_UNLOCK(imp); 1450 1451 /* 1452 * if zone is supported build a 'bind' database driver 1453 * structure to return 1454 */ 1455 if (result == ISC_R_SUCCESS) 1456 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name, 1457 rdclass, dbp); 1458 1459 return (result); 1460} 1461 1462static dns_dlzmethods_t sdlzmethods = { 1463 dns_sdlzcreate, 1464 dns_sdlzdestroy, 1465 dns_sdlzfindzone, 1466 dns_sdlzallowzonexfr 1467}; 1468 1469/* 1470 * Public functions. 1471 */ 1472 1473isc_result_t 1474dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl, 1475 const char *data) 1476{ 1477 dns_rdatalist_t *rdatalist; 1478 dns_rdata_t *rdata; 1479 dns_rdatatype_t typeval; 1480 isc_consttextregion_t r; 1481 isc_buffer_t b; 1482 isc_buffer_t *rdatabuf = NULL; 1483 isc_lex_t *lex; 1484 isc_result_t result; 1485 unsigned int size; 1486 isc_mem_t *mctx; 1487 dns_name_t *origin; 1488 1489 REQUIRE(VALID_SDLZLOOKUP(lookup)); 1490 REQUIRE(type != NULL); 1491 REQUIRE(data != NULL); 1492 1493 mctx = lookup->sdlz->common.mctx; 1494 1495 r.base = type; 1496 r.length = strlen(type); 1497 result = dns_rdatatype_fromtext(&typeval, (void *) &r); 1498 if (result != ISC_R_SUCCESS) 1499 return (result); 1500 1501 rdatalist = ISC_LIST_HEAD(lookup->lists); 1502 while (rdatalist != NULL) { 1503 if (rdatalist->type == typeval) 1504 break; 1505 rdatalist = ISC_LIST_NEXT(rdatalist, link); 1506 } 1507 1508 if (rdatalist == NULL) { 1509 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t)); 1510 if (rdatalist == NULL) 1511 return (ISC_R_NOMEMORY); 1512 rdatalist->rdclass = lookup->sdlz->common.rdclass; 1513 rdatalist->type = typeval; 1514 rdatalist->covers = 0; 1515 rdatalist->ttl = ttl; 1516 ISC_LIST_INIT(rdatalist->rdata); 1517 ISC_LINK_INIT(rdatalist, link); 1518 ISC_LIST_APPEND(lookup->lists, rdatalist, link); 1519 } else 1520 if (rdatalist->ttl != ttl) 1521 return (DNS_R_BADTTL); 1522 1523 rdata = isc_mem_get(mctx, sizeof(dns_rdata_t)); 1524 if (rdata == NULL) 1525 return (ISC_R_NOMEMORY); 1526 dns_rdata_init(rdata); 1527 1528 if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) 1529 origin = &lookup->sdlz->common.origin; 1530 else 1531 origin = dns_rootname; 1532 1533 lex = NULL; 1534 result = isc_lex_create(mctx, 64, &lex); 1535 if (result != ISC_R_SUCCESS) 1536 goto failure; 1537 1538 size = initial_size(data); 1539 do { 1540 isc_buffer_init(&b, data, strlen(data)); 1541 isc_buffer_add(&b, strlen(data)); 1542 1543 result = isc_lex_openbuffer(lex, &b); 1544 if (result != ISC_R_SUCCESS) 1545 goto failure; 1546 1547 rdatabuf = NULL; 1548 result = isc_buffer_allocate(mctx, &rdatabuf, size); 1549 if (result != ISC_R_SUCCESS) 1550 goto failure; 1551 1552 result = dns_rdata_fromtext(rdata, rdatalist->rdclass, 1553 rdatalist->type, lex, 1554 origin, ISC_FALSE, 1555 mctx, rdatabuf, 1556 &lookup->callbacks); 1557 if (result != ISC_R_SUCCESS) 1558 isc_buffer_free(&rdatabuf); 1559 size *= 2; 1560 } while (result == ISC_R_NOSPACE); 1561 1562 if (result != ISC_R_SUCCESS) 1563 goto failure; 1564 1565 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 1566 ISC_LIST_APPEND(lookup->buffers, rdatabuf, link); 1567 1568 if (lex != NULL) 1569 isc_lex_destroy(&lex); 1570 1571 return (ISC_R_SUCCESS); 1572 1573 failure: 1574 if (rdatabuf != NULL) 1575 isc_buffer_free(&rdatabuf); 1576 if (lex != NULL) 1577 isc_lex_destroy(&lex); 1578 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t)); 1579 1580 return (result); 1581} 1582 1583isc_result_t 1584dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name, 1585 const char *type, dns_ttl_t ttl, const char *data) 1586{ 1587 dns_name_t *newname, *origin; 1588 dns_fixedname_t fnewname; 1589 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db; 1590 dns_sdlznode_t *sdlznode; 1591 isc_mem_t *mctx = sdlz->common.mctx; 1592 isc_buffer_t b; 1593 isc_result_t result; 1594 1595 dns_fixedname_init(&fnewname); 1596 newname = dns_fixedname_name(&fnewname); 1597 1598 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) 1599 origin = &sdlz->common.origin; 1600 else 1601 origin = dns_rootname; 1602 isc_buffer_init(&b, name, strlen(name)); 1603 isc_buffer_add(&b, strlen(name)); 1604 1605 result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL); 1606 if (result != ISC_R_SUCCESS) 1607 return (result); 1608 1609 if (allnodes->common.relative_names) { 1610 /* All names are relative to the root */ 1611 unsigned int nlabels = dns_name_countlabels(newname); 1612 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname); 1613 } 1614 1615 sdlznode = ISC_LIST_HEAD(allnodes->nodelist); 1616 if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) { 1617 sdlznode = NULL; 1618 result = createnode(sdlz, &sdlznode); 1619 if (result != ISC_R_SUCCESS) 1620 return (result); 1621 sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t)); 1622 if (sdlznode->name == NULL) { 1623 destroynode(sdlznode); 1624 return (ISC_R_NOMEMORY); 1625 } 1626 dns_name_init(sdlznode->name, NULL); 1627 result = dns_name_dup(newname, mctx, sdlznode->name); 1628 if (result != ISC_R_SUCCESS) { 1629 isc_mem_put(mctx, sdlznode->name, sizeof(dns_name_t)); 1630 destroynode(sdlznode); 1631 return (result); 1632 } 1633 ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link); 1634 if (allnodes->origin == NULL && 1635 dns_name_equal(newname, &sdlz->common.origin)) 1636 allnodes->origin = sdlznode; 1637 } 1638 return (dns_sdlz_putrr(sdlznode, type, ttl, data)); 1639 1640} 1641 1642isc_result_t 1643dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname, 1644 isc_uint32_t serial) 1645{ 1646 char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7]; 1647 int n; 1648 1649 REQUIRE(mname != NULL); 1650 REQUIRE(rname != NULL); 1651 1652 n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u", 1653 mname, rname, serial, 1654 SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY, 1655 SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM); 1656 if (n >= (int)sizeof(str) || n < 0) 1657 return (ISC_R_NOSPACE); 1658 return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str)); 1659} 1660 1661isc_result_t 1662dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods, 1663 void *driverarg, unsigned int flags, isc_mem_t *mctx, 1664 dns_sdlzimplementation_t **sdlzimp) 1665{ 1666 1667 dns_sdlzimplementation_t *imp; 1668 isc_result_t result; 1669 1670 /* 1671 * Performs checks to make sure data is as we expect it to be. 1672 */ 1673 REQUIRE(drivername != NULL); 1674 REQUIRE(methods != NULL); 1675 REQUIRE(methods->findzone != NULL); 1676 REQUIRE(methods->lookup != NULL); 1677 REQUIRE(mctx != NULL); 1678 REQUIRE(sdlzimp != NULL && *sdlzimp == NULL); 1679 REQUIRE((flags & ~(DNS_SDLZFLAG_RELATIVEOWNER | 1680 DNS_SDLZFLAG_RELATIVERDATA | 1681 DNS_SDLZFLAG_THREADSAFE)) == 0); 1682 1683 /* Write debugging message to log */ 1684 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 1685 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), 1686 "Registering SDLZ driver '%s'", drivername); 1687 1688 /* 1689 * Allocate memory for a sdlz_implementation object. Error if 1690 * we cannot. 1691 */ 1692 imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t)); 1693 if (imp == NULL) 1694 return (ISC_R_NOMEMORY); 1695 1696 /* Make sure memory region is set to all 0's */ 1697 memset(imp, 0, sizeof(dns_sdlzimplementation_t)); 1698 1699 /* Store the data passed into this method */ 1700 imp->methods = methods; 1701 imp->driverarg = driverarg; 1702 imp->flags = flags; 1703 imp->mctx = NULL; 1704 1705 /* attach the new sdlz_implementation object to a memory context */ 1706 isc_mem_attach(mctx, &imp->mctx); 1707 1708 /* 1709 * initialize the driver lock, error if we cannot 1710 * (used if a driver does not support multiple threads) 1711 */ 1712 result = isc_mutex_init(&imp->driverlock); 1713 if (result != ISC_R_SUCCESS) { 1714 UNEXPECTED_ERROR(__FILE__, __LINE__, 1715 "isc_mutex_init() failed: %s", 1716 isc_result_totext(result)); 1717 goto cleanup_mctx; 1718 } 1719 1720 imp->dlz_imp = NULL; 1721 1722 /* 1723 * register the DLZ driver. Pass in our "extra" sdlz information as 1724 * a driverarg. (that's why we stored the passed in driver arg in our 1725 * sdlz_implementation structure) Also, store the dlz_implementation 1726 * structure in our sdlz_implementation. 1727 */ 1728 result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx, 1729 &imp->dlz_imp); 1730 1731 /* if registration fails, cleanup and get outta here. */ 1732 if (result != ISC_R_SUCCESS) 1733 goto cleanup_mutex; 1734 1735 *sdlzimp = imp; 1736 1737 return (ISC_R_SUCCESS); 1738 1739 cleanup_mutex: 1740 /* destroy the driver lock, we don't need it anymore */ 1741 DESTROYLOCK(&imp->driverlock); 1742 1743 cleanup_mctx: 1744 /* 1745 * return the memory back to the available memory pool and 1746 * remove it from the memory context. 1747 */ 1748 isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t)); 1749 isc_mem_detach(&mctx); 1750 return (result); 1751} 1752 1753void 1754dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) { 1755 dns_sdlzimplementation_t *imp; 1756 isc_mem_t *mctx; 1757 1758 /* Write debugging message to log */ 1759 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 1760 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), 1761 "Unregistering SDLZ driver."); 1762 1763 /* 1764 * Performs checks to make sure data is as we expect it to be. 1765 */ 1766 REQUIRE(sdlzimp != NULL && *sdlzimp != NULL); 1767 1768 imp = *sdlzimp; 1769 1770 /* Unregister the DLZ driver implementation */ 1771 dns_dlzunregister(&imp->dlz_imp); 1772 1773 /* destroy the driver lock, we don't need it anymore */ 1774 DESTROYLOCK(&imp->driverlock); 1775 1776 mctx = imp->mctx; 1777 1778 /* 1779 * return the memory back to the available memory pool and 1780 * remove it from the memory context. 1781 */ 1782 isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t)); 1783 isc_mem_detach(&mctx); 1784 1785 *sdlzimp = NULL; 1786} 1787