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