sdlz.c revision 205292
1/* 2 * Portions Copyright (C) 2005-2010 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.18.50.3.8.2 2010/02/25 10:57:12 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, unsigned int options, dns_dbiterator_t **iteratorp) 671{ 672 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 673 sdlz_dbiterator_t *sdlziter; 674 isc_result_t result; 675 isc_buffer_t b; 676 char zonestr[DNS_NAME_MAXTEXT + 1]; 677 678 REQUIRE(VALID_SDLZDB(sdlz)); 679 680 if (sdlz->dlzimp->methods->allnodes == NULL) 681 return (ISC_R_NOTIMPLEMENTED); 682 683 if ((options & DNS_DB_NSEC3ONLY) != 0 || 684 (options & DNS_DB_NONSEC3) != 0) 685 return (ISC_R_NOTIMPLEMENTED); 686 687 isc_buffer_init(&b, zonestr, sizeof(zonestr)); 688 result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b); 689 if (result != ISC_R_SUCCESS) 690 return (result); 691 isc_buffer_putuint8(&b, 0); 692 693 sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t)); 694 if (sdlziter == NULL) 695 return (ISC_R_NOMEMORY); 696 697 sdlziter->common.methods = &dbiterator_methods; 698 sdlziter->common.db = NULL; 699 dns_db_attach(db, &sdlziter->common.db); 700 sdlziter->common.relative_names = ISC_TF(options & DNS_DB_RELATIVENAMES); 701 sdlziter->common.magic = DNS_DBITERATOR_MAGIC; 702 ISC_LIST_INIT(sdlziter->nodelist); 703 sdlziter->current = NULL; 704 sdlziter->origin = NULL; 705 706 /* make sure strings are always lowercase */ 707 dns_sdlz_tolower(zonestr); 708 709 MAYBE_LOCK(sdlz->dlzimp); 710 result = sdlz->dlzimp->methods->allnodes(zonestr, 711 sdlz->dlzimp->driverarg, 712 sdlz->dbdata, sdlziter); 713 MAYBE_UNLOCK(sdlz->dlzimp); 714 if (result != ISC_R_SUCCESS) { 715 dns_dbiterator_t *iter = &sdlziter->common; 716 dbiterator_destroy(&iter); 717 return (result); 718 } 719 720 if (sdlziter->origin != NULL) { 721 ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link); 722 ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link); 723 } 724 725 *iteratorp = (dns_dbiterator_t *)sdlziter; 726 727 return (ISC_R_SUCCESS); 728} 729 730static isc_result_t 731findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 732 dns_rdatatype_t type, dns_rdatatype_t covers, 733 isc_stdtime_t now, dns_rdataset_t *rdataset, 734 dns_rdataset_t *sigrdataset) 735{ 736 dns_rdatalist_t *list; 737 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node; 738 739 REQUIRE(VALID_SDLZNODE(node)); 740 741 UNUSED(db); 742 UNUSED(version); 743 UNUSED(covers); 744 UNUSED(now); 745 UNUSED(sigrdataset); 746 747 if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig) 748 return (ISC_R_NOTIMPLEMENTED); 749 750 list = ISC_LIST_HEAD(sdlznode->lists); 751 while (list != NULL) { 752 if (list->type == type) 753 break; 754 list = ISC_LIST_NEXT(list, link); 755 } 756 if (list == NULL) 757 return (ISC_R_NOTFOUND); 758 759 list_tordataset(list, db, node, rdataset); 760 761 return (ISC_R_SUCCESS); 762} 763 764static isc_result_t 765find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, 766 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, 767 dns_dbnode_t **nodep, dns_name_t *foundname, 768 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 769{ 770 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 771 dns_dbnode_t *node = NULL; 772 dns_fixedname_t fname; 773 dns_rdataset_t xrdataset; 774 dns_name_t *xname; 775 unsigned int nlabels, olabels; 776 isc_result_t result; 777 unsigned int i; 778 779 REQUIRE(VALID_SDLZDB(sdlz)); 780 REQUIRE(nodep == NULL || *nodep == NULL); 781 REQUIRE(version == NULL || version == (void *) &dummy); 782 783 UNUSED(options); 784 UNUSED(sdlz); 785 786 if (!dns_name_issubdomain(name, &db->origin)) 787 return (DNS_R_NXDOMAIN); 788 789 olabels = dns_name_countlabels(&db->origin); 790 nlabels = dns_name_countlabels(name); 791 792 dns_fixedname_init(&fname); 793 xname = dns_fixedname_name(&fname); 794 795 if (rdataset == NULL) { 796 dns_rdataset_init(&xrdataset); 797 rdataset = &xrdataset; 798 } 799 800 result = DNS_R_NXDOMAIN; 801 802 for (i = olabels; i <= nlabels; i++) { 803 /* 804 * Unless this is an explicit lookup at the origin, don't 805 * look at the origin. 806 */ 807 if (i == olabels && i != nlabels) 808 continue; 809 810 /* 811 * Look up the next label. 812 */ 813 dns_name_getlabelsequence(name, nlabels - i, i, xname); 814 result = findnode(db, xname, ISC_FALSE, &node); 815 if (result != ISC_R_SUCCESS) { 816 result = DNS_R_NXDOMAIN; 817 continue; 818 } 819 820 /* 821 * Look for a DNAME at the current label, unless this is 822 * the qname. 823 */ 824 if (i < nlabels) { 825 result = findrdataset(db, node, version, 826 dns_rdatatype_dname, 827 0, now, rdataset, sigrdataset); 828 if (result == ISC_R_SUCCESS) { 829 result = DNS_R_DNAME; 830 break; 831 } 832 } 833 834 /* 835 * Look for an NS at the current label, unless this is the 836 * origin or glue is ok. 837 */ 838 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) { 839 result = findrdataset(db, node, version, 840 dns_rdatatype_ns, 841 0, now, rdataset, sigrdataset); 842 if (result == ISC_R_SUCCESS) { 843 if (i == nlabels && type == dns_rdatatype_any) 844 { 845 result = DNS_R_ZONECUT; 846 dns_rdataset_disassociate(rdataset); 847 if (sigrdataset != NULL && 848 dns_rdataset_isassociated 849 (sigrdataset)) { 850 dns_rdataset_disassociate 851 (sigrdataset); 852 } 853 } else 854 result = DNS_R_DELEGATION; 855 break; 856 } 857 } 858 859 /* 860 * If the current name is not the qname, add another label 861 * and try again. 862 */ 863 if (i < nlabels) { 864 destroynode(node); 865 node = NULL; 866 continue; 867 } 868 869 /* 870 * If we're looking for ANY, we're done. 871 */ 872 if (type == dns_rdatatype_any) { 873 result = ISC_R_SUCCESS; 874 break; 875 } 876 877 /* 878 * Look for the qtype. 879 */ 880 result = findrdataset(db, node, version, type, 881 0, now, rdataset, sigrdataset); 882 if (result == ISC_R_SUCCESS) 883 break; 884 885 /* 886 * Look for a CNAME 887 */ 888 if (type != dns_rdatatype_cname) { 889 result = findrdataset(db, node, version, 890 dns_rdatatype_cname, 891 0, now, rdataset, sigrdataset); 892 if (result == ISC_R_SUCCESS) { 893 result = DNS_R_CNAME; 894 break; 895 } 896 } 897 898 result = DNS_R_NXRRSET; 899 break; 900 } 901 902 if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) 903 dns_rdataset_disassociate(rdataset); 904 905 if (foundname != NULL) { 906 isc_result_t xresult; 907 908 xresult = dns_name_copy(xname, foundname, NULL); 909 if (xresult != ISC_R_SUCCESS) { 910 if (node != NULL) 911 destroynode(node); 912 if (dns_rdataset_isassociated(rdataset)) 913 dns_rdataset_disassociate(rdataset); 914 return (DNS_R_BADDB); 915 } 916 } 917 918 if (nodep != NULL) 919 *nodep = node; 920 else if (node != NULL) 921 detachnode(db, &node); 922 923 return (result); 924} 925 926static isc_result_t 927allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 928 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) 929{ 930 sdlz_rdatasetiter_t *iterator; 931 932 REQUIRE(version == NULL || version == &dummy); 933 934 UNUSED(version); 935 UNUSED(now); 936 937 iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t)); 938 if (iterator == NULL) 939 return (ISC_R_NOMEMORY); 940 941 iterator->common.magic = DNS_RDATASETITER_MAGIC; 942 iterator->common.methods = &rdatasetiter_methods; 943 iterator->common.db = db; 944 iterator->common.node = NULL; 945 attachnode(db, node, &iterator->common.node); 946 iterator->common.version = version; 947 iterator->common.now = now; 948 949 *iteratorp = (dns_rdatasetiter_t *)iterator; 950 951 return (ISC_R_SUCCESS); 952} 953 954static isc_result_t 955addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 956 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, 957 dns_rdataset_t *addedrdataset) 958{ 959 UNUSED(db); 960 UNUSED(node); 961 UNUSED(version); 962 UNUSED(now); 963 UNUSED(rdataset); 964 UNUSED(options); 965 UNUSED(addedrdataset); 966 967 return (ISC_R_NOTIMPLEMENTED); 968} 969 970static isc_result_t 971subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 972 dns_rdataset_t *rdataset, unsigned int options, 973 dns_rdataset_t *newrdataset) 974{ 975 UNUSED(db); 976 UNUSED(node); 977 UNUSED(version); 978 UNUSED(rdataset); 979 UNUSED(options); 980 UNUSED(newrdataset); 981 982 return (ISC_R_NOTIMPLEMENTED); 983} 984 985static isc_result_t 986deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 987 dns_rdatatype_t type, dns_rdatatype_t covers) 988{ 989 UNUSED(db); 990 UNUSED(node); 991 UNUSED(version); 992 UNUSED(type); 993 UNUSED(covers); 994 995 return (ISC_R_NOTIMPLEMENTED); 996} 997 998static isc_boolean_t 999issecure(dns_db_t *db) { 1000 UNUSED(db); 1001 1002 return (ISC_FALSE); 1003} 1004 1005static unsigned int 1006nodecount(dns_db_t *db) { 1007 UNUSED(db); 1008 1009 return (0); 1010} 1011 1012static isc_boolean_t 1013ispersistent(dns_db_t *db) { 1014 UNUSED(db); 1015 return (ISC_TRUE); 1016} 1017 1018static void 1019overmem(dns_db_t *db, isc_boolean_t overmem) { 1020 UNUSED(db); 1021 UNUSED(overmem); 1022} 1023 1024static void 1025settask(dns_db_t *db, isc_task_t *task) { 1026 UNUSED(db); 1027 UNUSED(task); 1028} 1029 1030 1031static dns_dbmethods_t sdlzdb_methods = { 1032 attach, 1033 detach, 1034 beginload, 1035 endload, 1036 dump, 1037 currentversion, 1038 newversion, 1039 attachversion, 1040 closeversion, 1041 findnode, 1042 find, 1043 findzonecut, 1044 attachnode, 1045 detachnode, 1046 expirenode, 1047 printnode, 1048 createiterator, 1049 findrdataset, 1050 allrdatasets, 1051 addrdataset, 1052 subtractrdataset, 1053 deleterdataset, 1054 issecure, 1055 nodecount, 1056 ispersistent, 1057 overmem, 1058 settask, 1059 NULL, 1060 NULL, 1061 NULL, 1062 NULL, 1063 NULL, 1064 NULL, 1065 NULL, 1066 NULL, 1067 NULL 1068}; 1069 1070/* 1071 * Database Iterator Methods. These methods were "borrowed" from the SDB 1072 * driver interface. See the SDB driver interface documentation for more info. 1073 */ 1074 1075static void 1076dbiterator_destroy(dns_dbiterator_t **iteratorp) { 1077 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp); 1078 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db; 1079 1080 while (!ISC_LIST_EMPTY(sdlziter->nodelist)) { 1081 dns_sdlznode_t *node; 1082 node = ISC_LIST_HEAD(sdlziter->nodelist); 1083 ISC_LIST_UNLINK(sdlziter->nodelist, node, link); 1084 destroynode(node); 1085 } 1086 1087 dns_db_detach(&sdlziter->common.db); 1088 isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t)); 1089 1090 *iteratorp = NULL; 1091} 1092 1093static isc_result_t 1094dbiterator_first(dns_dbiterator_t *iterator) { 1095 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1096 1097 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist); 1098 if (sdlziter->current == NULL) 1099 return (ISC_R_NOMORE); 1100 else 1101 return (ISC_R_SUCCESS); 1102} 1103 1104static isc_result_t 1105dbiterator_last(dns_dbiterator_t *iterator) { 1106 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1107 1108 sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist); 1109 if (sdlziter->current == NULL) 1110 return (ISC_R_NOMORE); 1111 else 1112 return (ISC_R_SUCCESS); 1113} 1114 1115static isc_result_t 1116dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) { 1117 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1118 1119 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist); 1120 while (sdlziter->current != NULL) { 1121 if (dns_name_equal(sdlziter->current->name, name)) 1122 return (ISC_R_SUCCESS); 1123 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link); 1124 } 1125 return (ISC_R_NOTFOUND); 1126} 1127 1128static isc_result_t 1129dbiterator_prev(dns_dbiterator_t *iterator) { 1130 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1131 1132 sdlziter->current = ISC_LIST_PREV(sdlziter->current, link); 1133 if (sdlziter->current == NULL) 1134 return (ISC_R_NOMORE); 1135 else 1136 return (ISC_R_SUCCESS); 1137} 1138 1139static isc_result_t 1140dbiterator_next(dns_dbiterator_t *iterator) { 1141 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1142 1143 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link); 1144 if (sdlziter->current == NULL) 1145 return (ISC_R_NOMORE); 1146 else 1147 return (ISC_R_SUCCESS); 1148} 1149 1150static isc_result_t 1151dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, 1152 dns_name_t *name) 1153{ 1154 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1155 1156 attachnode(iterator->db, sdlziter->current, nodep); 1157 if (name != NULL) 1158 return (dns_name_copy(sdlziter->current->name, name, NULL)); 1159 return (ISC_R_SUCCESS); 1160} 1161 1162static isc_result_t 1163dbiterator_pause(dns_dbiterator_t *iterator) { 1164 UNUSED(iterator); 1165 return (ISC_R_SUCCESS); 1166} 1167 1168static isc_result_t 1169dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) { 1170 UNUSED(iterator); 1171 return (dns_name_copy(dns_rootname, name, NULL)); 1172} 1173 1174/* 1175 * Rdataset Methods. These methods were "borrowed" from the SDB driver 1176 * interface. See the SDB driver interface documentation for more info. 1177 */ 1178 1179static void 1180disassociate(dns_rdataset_t *rdataset) { 1181 dns_dbnode_t *node = rdataset->private5; 1182 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node; 1183 dns_db_t *db = (dns_db_t *) sdlznode->sdlz; 1184 1185 detachnode(db, &node); 1186 isc__rdatalist_disassociate(rdataset); 1187} 1188 1189static void 1190rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) { 1191 dns_dbnode_t *node = source->private5; 1192 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node; 1193 dns_db_t *db = (dns_db_t *) sdlznode->sdlz; 1194 dns_dbnode_t *tempdb = NULL; 1195 1196 isc__rdatalist_clone(source, target); 1197 attachnode(db, node, &tempdb); 1198 source->private5 = tempdb; 1199} 1200 1201static dns_rdatasetmethods_t rdataset_methods = { 1202 disassociate, 1203 isc__rdatalist_first, 1204 isc__rdatalist_next, 1205 isc__rdatalist_current, 1206 rdataset_clone, 1207 isc__rdatalist_count, 1208 isc__rdatalist_addnoqname, 1209 isc__rdatalist_getnoqname, 1210 NULL, 1211 NULL, 1212 NULL, 1213 NULL, 1214 NULL, 1215 NULL, 1216 NULL 1217}; 1218 1219static void 1220list_tordataset(dns_rdatalist_t *rdatalist, 1221 dns_db_t *db, dns_dbnode_t *node, 1222 dns_rdataset_t *rdataset) 1223{ 1224 /* 1225 * The sdlz rdataset is an rdatalist with some additions. 1226 * - private1 & private2 are used by the rdatalist. 1227 * - private3 & private 4 are unused. 1228 * - private5 is the node. 1229 */ 1230 1231 /* This should never fail. */ 1232 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == 1233 ISC_R_SUCCESS); 1234 1235 rdataset->methods = &rdataset_methods; 1236 dns_db_attachnode(db, node, &rdataset->private5); 1237} 1238 1239/* 1240 * SDLZ core methods. This is the core of the new DLZ functionality. 1241 */ 1242 1243/*% 1244 * Build a 'bind' database driver structure to be returned by 1245 * either the find zone or the allow zone transfer method. 1246 * This method is only available in this source file, it is 1247 * not made available anywhere else. 1248 */ 1249 1250static isc_result_t 1251dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata, 1252 dns_name_t *name, dns_rdataclass_t rdclass, dns_db_t **dbp) 1253{ 1254 isc_result_t result; 1255 dns_sdlz_db_t *sdlzdb; 1256 dns_sdlzimplementation_t *imp; 1257 1258 /* check that things are as we expect */ 1259 REQUIRE(dbp != NULL && *dbp == NULL); 1260 REQUIRE(name != NULL); 1261 1262 imp = (dns_sdlzimplementation_t *) driverarg; 1263 1264 /* allocate and zero memory for driver structure */ 1265 sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t)); 1266 if (sdlzdb == NULL) 1267 return (ISC_R_NOMEMORY); 1268 memset(sdlzdb, 0, sizeof(dns_sdlz_db_t)); 1269 1270 /* initialize and set origin */ 1271 dns_name_init(&sdlzdb->common.origin, NULL); 1272 result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin); 1273 if (result != ISC_R_SUCCESS) 1274 goto mem_cleanup; 1275 1276 /* initialize the reference count mutex */ 1277 result = isc_mutex_init(&sdlzdb->refcnt_lock); 1278 if (result != ISC_R_SUCCESS) 1279 goto name_cleanup; 1280 1281 /* set the rest of the database structure attributes */ 1282 sdlzdb->dlzimp = imp; 1283 sdlzdb->common.methods = &sdlzdb_methods; 1284 sdlzdb->common.attributes = 0; 1285 sdlzdb->common.rdclass = rdclass; 1286 sdlzdb->common.mctx = NULL; 1287 sdlzdb->dbdata = dbdata; 1288 sdlzdb->references = 1; 1289 1290 /* attach to the memory context */ 1291 isc_mem_attach(mctx, &sdlzdb->common.mctx); 1292 1293 /* mark structure as valid */ 1294 sdlzdb->common.magic = DNS_DB_MAGIC; 1295 sdlzdb->common.impmagic = SDLZDB_MAGIC; 1296 *dbp = (dns_db_t *) sdlzdb; 1297 1298 return (result); 1299 1300 /* 1301 * reference count mutex could not be initialized, clean up 1302 * name memory 1303 */ 1304 name_cleanup: 1305 dns_name_free(&sdlzdb->common.origin, mctx); 1306 mem_cleanup: 1307 isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t)); 1308 return (result); 1309} 1310 1311static isc_result_t 1312dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx, 1313 dns_rdataclass_t rdclass, dns_name_t *name, 1314 isc_sockaddr_t *clientaddr, dns_db_t **dbp) 1315{ 1316 isc_buffer_t b; 1317 isc_buffer_t b2; 1318 char namestr[DNS_NAME_MAXTEXT + 1]; 1319 char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255") 1320 + 1]; 1321 isc_netaddr_t netaddr; 1322 isc_result_t result; 1323 dns_sdlzimplementation_t *imp; 1324 1325 /* 1326 * Perform checks to make sure data is as we expect it to be. 1327 */ 1328 REQUIRE(driverarg != NULL); 1329 REQUIRE(name != NULL); 1330 REQUIRE(clientaddr != NULL); 1331 REQUIRE(dbp != NULL && *dbp == NULL); 1332 1333 imp = (dns_sdlzimplementation_t *) driverarg; 1334 1335 /* Convert DNS name to ascii text */ 1336 isc_buffer_init(&b, namestr, sizeof(namestr)); 1337 result = dns_name_totext(name, ISC_TRUE, &b); 1338 if (result != ISC_R_SUCCESS) 1339 return (result); 1340 isc_buffer_putuint8(&b, 0); 1341 1342 /* convert client address to ascii text */ 1343 isc_buffer_init(&b2, clientstr, sizeof(clientstr)); 1344 isc_netaddr_fromsockaddr(&netaddr, clientaddr); 1345 result = isc_netaddr_totext(&netaddr, &b2); 1346 if (result != ISC_R_SUCCESS) 1347 return (result); 1348 isc_buffer_putuint8(&b2, 0); 1349 1350 /* make sure strings are always lowercase */ 1351 dns_sdlz_tolower(namestr); 1352 dns_sdlz_tolower(clientstr); 1353 1354 /* Call SDLZ driver's find zone method */ 1355 if (imp->methods->allowzonexfr != NULL) { 1356 MAYBE_LOCK(imp); 1357 result = imp->methods->allowzonexfr(imp->driverarg, dbdata, 1358 namestr, clientstr); 1359 MAYBE_UNLOCK(imp); 1360 /* 1361 * if zone is supported and transfers allowed build a 'bind' 1362 * database driver 1363 */ 1364 if (result == ISC_R_SUCCESS) 1365 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, 1366 name, rdclass, dbp); 1367 return (result); 1368 } 1369 1370 return (ISC_R_NOTIMPLEMENTED); 1371} 1372 1373static isc_result_t 1374dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc, 1375 char *argv[], void *driverarg, void **dbdata) 1376{ 1377 dns_sdlzimplementation_t *imp; 1378 isc_result_t result = ISC_R_NOTFOUND; 1379 1380 /* Write debugging message to log */ 1381 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 1382 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), 1383 "Loading SDLZ driver."); 1384 1385 /* 1386 * Performs checks to make sure data is as we expect it to be. 1387 */ 1388 REQUIRE(driverarg != NULL); 1389 REQUIRE(dlzname != NULL); 1390 REQUIRE(dbdata != NULL); 1391 UNUSED(mctx); 1392 1393 imp = driverarg; 1394 1395 /* If the create method exists, call it. */ 1396 if (imp->methods->create != NULL) { 1397 MAYBE_LOCK(imp); 1398 result = imp->methods->create(dlzname, argc, argv, 1399 imp->driverarg, dbdata); 1400 MAYBE_UNLOCK(imp); 1401 } 1402 1403 /* Write debugging message to log */ 1404 if (result == ISC_R_SUCCESS) { 1405 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 1406 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), 1407 "SDLZ driver loaded successfully."); 1408 } else { 1409 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 1410 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, 1411 "SDLZ driver failed to load."); 1412 } 1413 1414 return (result); 1415} 1416 1417static void 1418dns_sdlzdestroy(void *driverdata, void **dbdata) 1419{ 1420 1421 dns_sdlzimplementation_t *imp; 1422 1423 /* Write debugging message to log */ 1424 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 1425 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), 1426 "Unloading SDLZ driver."); 1427 1428 imp = driverdata; 1429 1430 /* If the destroy method exists, call it. */ 1431 if (imp->methods->destroy != NULL) { 1432 MAYBE_LOCK(imp); 1433 imp->methods->destroy(imp->driverarg, dbdata); 1434 MAYBE_UNLOCK(imp); 1435 } 1436} 1437 1438static isc_result_t 1439dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx, 1440 dns_rdataclass_t rdclass, dns_name_t *name, dns_db_t **dbp) 1441{ 1442 isc_buffer_t b; 1443 char namestr[DNS_NAME_MAXTEXT + 1]; 1444 isc_result_t result; 1445 dns_sdlzimplementation_t *imp; 1446 1447 /* 1448 * Perform checks to make sure data is as we expect it to be. 1449 */ 1450 REQUIRE(driverarg != NULL); 1451 REQUIRE(name != NULL); 1452 REQUIRE(dbp != NULL && *dbp == NULL); 1453 1454 imp = (dns_sdlzimplementation_t *) driverarg; 1455 1456 /* Convert DNS name to ascii text */ 1457 isc_buffer_init(&b, namestr, sizeof(namestr)); 1458 result = dns_name_totext(name, ISC_TRUE, &b); 1459 if (result != ISC_R_SUCCESS) 1460 return (result); 1461 isc_buffer_putuint8(&b, 0); 1462 1463 /* make sure strings are always lowercase */ 1464 dns_sdlz_tolower(namestr); 1465 1466 /* Call SDLZ driver's find zone method */ 1467 MAYBE_LOCK(imp); 1468 result = imp->methods->findzone(imp->driverarg, dbdata, namestr); 1469 MAYBE_UNLOCK(imp); 1470 1471 /* 1472 * if zone is supported build a 'bind' database driver 1473 * structure to return 1474 */ 1475 if (result == ISC_R_SUCCESS) 1476 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name, 1477 rdclass, dbp); 1478 1479 return (result); 1480} 1481 1482static dns_dlzmethods_t sdlzmethods = { 1483 dns_sdlzcreate, 1484 dns_sdlzdestroy, 1485 dns_sdlzfindzone, 1486 dns_sdlzallowzonexfr 1487}; 1488 1489/* 1490 * Public functions. 1491 */ 1492 1493isc_result_t 1494dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl, 1495 const char *data) 1496{ 1497 dns_rdatalist_t *rdatalist; 1498 dns_rdata_t *rdata; 1499 dns_rdatatype_t typeval; 1500 isc_consttextregion_t r; 1501 isc_buffer_t b; 1502 isc_buffer_t *rdatabuf = NULL; 1503 isc_lex_t *lex; 1504 isc_result_t result; 1505 unsigned int size; 1506 isc_mem_t *mctx; 1507 dns_name_t *origin; 1508 1509 REQUIRE(VALID_SDLZLOOKUP(lookup)); 1510 REQUIRE(type != NULL); 1511 REQUIRE(data != NULL); 1512 1513 mctx = lookup->sdlz->common.mctx; 1514 1515 r.base = type; 1516 r.length = strlen(type); 1517 result = dns_rdatatype_fromtext(&typeval, (void *) &r); 1518 if (result != ISC_R_SUCCESS) 1519 return (result); 1520 1521 rdatalist = ISC_LIST_HEAD(lookup->lists); 1522 while (rdatalist != NULL) { 1523 if (rdatalist->type == typeval) 1524 break; 1525 rdatalist = ISC_LIST_NEXT(rdatalist, link); 1526 } 1527 1528 if (rdatalist == NULL) { 1529 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t)); 1530 if (rdatalist == NULL) 1531 return (ISC_R_NOMEMORY); 1532 rdatalist->rdclass = lookup->sdlz->common.rdclass; 1533 rdatalist->type = typeval; 1534 rdatalist->covers = 0; 1535 rdatalist->ttl = ttl; 1536 ISC_LIST_INIT(rdatalist->rdata); 1537 ISC_LINK_INIT(rdatalist, link); 1538 ISC_LIST_APPEND(lookup->lists, rdatalist, link); 1539 } else 1540 if (rdatalist->ttl != ttl) 1541 return (DNS_R_BADTTL); 1542 1543 rdata = isc_mem_get(mctx, sizeof(dns_rdata_t)); 1544 if (rdata == NULL) 1545 return (ISC_R_NOMEMORY); 1546 dns_rdata_init(rdata); 1547 1548 if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) 1549 origin = &lookup->sdlz->common.origin; 1550 else 1551 origin = dns_rootname; 1552 1553 lex = NULL; 1554 result = isc_lex_create(mctx, 64, &lex); 1555 if (result != ISC_R_SUCCESS) 1556 goto failure; 1557 1558 size = initial_size(data); 1559 do { 1560 isc_buffer_init(&b, data, strlen(data)); 1561 isc_buffer_add(&b, strlen(data)); 1562 1563 result = isc_lex_openbuffer(lex, &b); 1564 if (result != ISC_R_SUCCESS) 1565 goto failure; 1566 1567 rdatabuf = NULL; 1568 result = isc_buffer_allocate(mctx, &rdatabuf, size); 1569 if (result != ISC_R_SUCCESS) 1570 goto failure; 1571 1572 result = dns_rdata_fromtext(rdata, rdatalist->rdclass, 1573 rdatalist->type, lex, 1574 origin, ISC_FALSE, 1575 mctx, rdatabuf, 1576 &lookup->callbacks); 1577 if (result != ISC_R_SUCCESS) 1578 isc_buffer_free(&rdatabuf); 1579 size *= 2; 1580 } while (result == ISC_R_NOSPACE); 1581 1582 if (result != ISC_R_SUCCESS) 1583 goto failure; 1584 1585 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 1586 ISC_LIST_APPEND(lookup->buffers, rdatabuf, link); 1587 1588 if (lex != NULL) 1589 isc_lex_destroy(&lex); 1590 1591 return (ISC_R_SUCCESS); 1592 1593 failure: 1594 if (rdatabuf != NULL) 1595 isc_buffer_free(&rdatabuf); 1596 if (lex != NULL) 1597 isc_lex_destroy(&lex); 1598 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t)); 1599 1600 return (result); 1601} 1602 1603isc_result_t 1604dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name, 1605 const char *type, dns_ttl_t ttl, const char *data) 1606{ 1607 dns_name_t *newname, *origin; 1608 dns_fixedname_t fnewname; 1609 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db; 1610 dns_sdlznode_t *sdlznode; 1611 isc_mem_t *mctx = sdlz->common.mctx; 1612 isc_buffer_t b; 1613 isc_result_t result; 1614 1615 dns_fixedname_init(&fnewname); 1616 newname = dns_fixedname_name(&fnewname); 1617 1618 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) 1619 origin = &sdlz->common.origin; 1620 else 1621 origin = dns_rootname; 1622 isc_buffer_init(&b, name, strlen(name)); 1623 isc_buffer_add(&b, strlen(name)); 1624 1625 result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL); 1626 if (result != ISC_R_SUCCESS) 1627 return (result); 1628 1629 if (allnodes->common.relative_names) { 1630 /* All names are relative to the root */ 1631 unsigned int nlabels = dns_name_countlabels(newname); 1632 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname); 1633 } 1634 1635 sdlznode = ISC_LIST_HEAD(allnodes->nodelist); 1636 if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) { 1637 sdlznode = NULL; 1638 result = createnode(sdlz, &sdlznode); 1639 if (result != ISC_R_SUCCESS) 1640 return (result); 1641 sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t)); 1642 if (sdlznode->name == NULL) { 1643 destroynode(sdlznode); 1644 return (ISC_R_NOMEMORY); 1645 } 1646 dns_name_init(sdlznode->name, NULL); 1647 result = dns_name_dup(newname, mctx, sdlznode->name); 1648 if (result != ISC_R_SUCCESS) { 1649 isc_mem_put(mctx, sdlznode->name, sizeof(dns_name_t)); 1650 destroynode(sdlznode); 1651 return (result); 1652 } 1653 ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link); 1654 if (allnodes->origin == NULL && 1655 dns_name_equal(newname, &sdlz->common.origin)) 1656 allnodes->origin = sdlznode; 1657 } 1658 return (dns_sdlz_putrr(sdlznode, type, ttl, data)); 1659 1660} 1661 1662isc_result_t 1663dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname, 1664 isc_uint32_t serial) 1665{ 1666 char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7]; 1667 int n; 1668 1669 REQUIRE(mname != NULL); 1670 REQUIRE(rname != NULL); 1671 1672 n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u", 1673 mname, rname, serial, 1674 SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY, 1675 SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM); 1676 if (n >= (int)sizeof(str) || n < 0) 1677 return (ISC_R_NOSPACE); 1678 return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str)); 1679} 1680 1681isc_result_t 1682dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods, 1683 void *driverarg, unsigned int flags, isc_mem_t *mctx, 1684 dns_sdlzimplementation_t **sdlzimp) 1685{ 1686 1687 dns_sdlzimplementation_t *imp; 1688 isc_result_t result; 1689 1690 /* 1691 * Performs checks to make sure data is as we expect it to be. 1692 */ 1693 REQUIRE(drivername != NULL); 1694 REQUIRE(methods != NULL); 1695 REQUIRE(methods->findzone != NULL); 1696 REQUIRE(methods->lookup != NULL); 1697 REQUIRE(mctx != NULL); 1698 REQUIRE(sdlzimp != NULL && *sdlzimp == NULL); 1699 REQUIRE((flags & ~(DNS_SDLZFLAG_RELATIVEOWNER | 1700 DNS_SDLZFLAG_RELATIVERDATA | 1701 DNS_SDLZFLAG_THREADSAFE)) == 0); 1702 1703 /* Write debugging message to log */ 1704 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 1705 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), 1706 "Registering SDLZ driver '%s'", drivername); 1707 1708 /* 1709 * Allocate memory for a sdlz_implementation object. Error if 1710 * we cannot. 1711 */ 1712 imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t)); 1713 if (imp == NULL) 1714 return (ISC_R_NOMEMORY); 1715 1716 /* Make sure memory region is set to all 0's */ 1717 memset(imp, 0, sizeof(dns_sdlzimplementation_t)); 1718 1719 /* Store the data passed into this method */ 1720 imp->methods = methods; 1721 imp->driverarg = driverarg; 1722 imp->flags = flags; 1723 imp->mctx = NULL; 1724 1725 /* attach the new sdlz_implementation object to a memory context */ 1726 isc_mem_attach(mctx, &imp->mctx); 1727 1728 /* 1729 * initialize the driver lock, error if we cannot 1730 * (used if a driver does not support multiple threads) 1731 */ 1732 result = isc_mutex_init(&imp->driverlock); 1733 if (result != ISC_R_SUCCESS) { 1734 UNEXPECTED_ERROR(__FILE__, __LINE__, 1735 "isc_mutex_init() failed: %s", 1736 isc_result_totext(result)); 1737 goto cleanup_mctx; 1738 } 1739 1740 imp->dlz_imp = NULL; 1741 1742 /* 1743 * register the DLZ driver. Pass in our "extra" sdlz information as 1744 * a driverarg. (that's why we stored the passed in driver arg in our 1745 * sdlz_implementation structure) Also, store the dlz_implementation 1746 * structure in our sdlz_implementation. 1747 */ 1748 result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx, 1749 &imp->dlz_imp); 1750 1751 /* if registration fails, cleanup and get outta here. */ 1752 if (result != ISC_R_SUCCESS) 1753 goto cleanup_mutex; 1754 1755 *sdlzimp = imp; 1756 1757 return (ISC_R_SUCCESS); 1758 1759 cleanup_mutex: 1760 /* destroy the driver lock, we don't need it anymore */ 1761 DESTROYLOCK(&imp->driverlock); 1762 1763 cleanup_mctx: 1764 /* 1765 * return the memory back to the available memory pool and 1766 * remove it from the memory context. 1767 */ 1768 isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t)); 1769 isc_mem_detach(&mctx); 1770 return (result); 1771} 1772 1773void 1774dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) { 1775 dns_sdlzimplementation_t *imp; 1776 isc_mem_t *mctx; 1777 1778 /* Write debugging message to log */ 1779 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 1780 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), 1781 "Unregistering SDLZ driver."); 1782 1783 /* 1784 * Performs checks to make sure data is as we expect it to be. 1785 */ 1786 REQUIRE(sdlzimp != NULL && *sdlzimp != NULL); 1787 1788 imp = *sdlzimp; 1789 1790 /* Unregister the DLZ driver implementation */ 1791 dns_dlzunregister(&imp->dlz_imp); 1792 1793 /* destroy the driver lock, we don't need it anymore */ 1794 DESTROYLOCK(&imp->driverlock); 1795 1796 mctx = imp->mctx; 1797 1798 /* 1799 * return the memory back to the available memory pool and 1800 * remove it from the memory context. 1801 */ 1802 isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t)); 1803 isc_mem_detach(&mctx); 1804 1805 *sdlzimp = NULL; 1806} 1807