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