1225305Sdougb/* 2254402Serwin * Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC") 3225305Sdougb * 4225305Sdougb * Permission to use, copy, modify, and/or distribute this software for any 5225305Sdougb * purpose with or without fee is hereby granted, provided that the above 6225305Sdougb * copyright notice and this permission notice appear in all copies. 7225305Sdougb * 8225305Sdougb * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9225305Sdougb * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10225305Sdougb * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11225305Sdougb * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12225305Sdougb * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13225305Sdougb * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14225305Sdougb * PERFORMANCE OF THIS SOFTWARE. 15225305Sdougb */ 16225305Sdougb 17254897Serwin/* $Id$ */ 18225305Sdougb 19225305Sdougb#include <config.h> 20225305Sdougb 21225305Sdougb#include <stdio.h> 22225305Sdougb#include <string.h> 23225305Sdougb#include <stdlib.h> 24225305Sdougb#include <dlfcn.h> 25225305Sdougb 26225305Sdougb#include <dns/log.h> 27225305Sdougb#include <dns/result.h> 28225305Sdougb#include <dns/dlz_dlopen.h> 29225305Sdougb 30225305Sdougb#include <isc/mem.h> 31225305Sdougb#include <isc/print.h> 32225305Sdougb#include <isc/result.h> 33225305Sdougb#include <isc/util.h> 34225305Sdougb 35225305Sdougb#include <named/globals.h> 36225305Sdougb 37225305Sdougb#include <dlz/dlz_dlopen_driver.h> 38225305Sdougb 39225305Sdougb#ifdef ISC_DLZ_DLOPEN 40225305Sdougbstatic dns_sdlzimplementation_t *dlz_dlopen = NULL; 41225305Sdougb 42225305Sdougb 43225305Sdougbtypedef struct dlopen_data { 44225305Sdougb isc_mem_t *mctx; 45225305Sdougb char *dl_path; 46225305Sdougb char *dlzname; 47225305Sdougb void *dl_handle; 48225305Sdougb void *dbdata; 49225305Sdougb unsigned int flags; 50225305Sdougb isc_mutex_t lock; 51225305Sdougb int version; 52225305Sdougb isc_boolean_t in_configure; 53225305Sdougb 54225305Sdougb dlz_dlopen_version_t *dlz_version; 55225305Sdougb dlz_dlopen_create_t *dlz_create; 56225305Sdougb dlz_dlopen_findzonedb_t *dlz_findzonedb; 57225305Sdougb dlz_dlopen_lookup_t *dlz_lookup; 58225305Sdougb dlz_dlopen_authority_t *dlz_authority; 59225305Sdougb dlz_dlopen_allnodes_t *dlz_allnodes; 60225305Sdougb dlz_dlopen_allowzonexfr_t *dlz_allowzonexfr; 61225305Sdougb dlz_dlopen_newversion_t *dlz_newversion; 62225305Sdougb dlz_dlopen_closeversion_t *dlz_closeversion; 63225305Sdougb dlz_dlopen_configure_t *dlz_configure; 64225305Sdougb dlz_dlopen_ssumatch_t *dlz_ssumatch; 65225305Sdougb dlz_dlopen_addrdataset_t *dlz_addrdataset; 66225305Sdougb dlz_dlopen_subrdataset_t *dlz_subrdataset; 67225305Sdougb dlz_dlopen_delrdataset_t *dlz_delrdataset; 68225305Sdougb dlz_dlopen_destroy_t *dlz_destroy; 69225305Sdougb} dlopen_data_t; 70225305Sdougb 71225305Sdougb/* Modules can choose whether they are lock-safe or not. */ 72225305Sdougb#define MAYBE_LOCK(cd) \ 73225305Sdougb do { \ 74225305Sdougb if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \ 75225305Sdougb cd->in_configure == ISC_FALSE) \ 76225305Sdougb LOCK(&cd->lock); \ 77225305Sdougb } while (0) 78225305Sdougb 79225305Sdougb#define MAYBE_UNLOCK(cd) \ 80225305Sdougb do { \ 81225305Sdougb if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \ 82225305Sdougb cd->in_configure == ISC_FALSE) \ 83225305Sdougb UNLOCK(&cd->lock); \ 84225305Sdougb } while (0) 85225305Sdougb 86225305Sdougb/* 87225305Sdougb * Log a message at the given level. 88225305Sdougb */ 89225305Sdougbstatic void dlopen_log(int level, const char *fmt, ...) 90225305Sdougb{ 91225305Sdougb va_list ap; 92225305Sdougb va_start(ap, fmt); 93225305Sdougb isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, 94225305Sdougb DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(level), 95225305Sdougb fmt, ap); 96225305Sdougb va_end(ap); 97225305Sdougb} 98225305Sdougb 99225305Sdougb/* 100225305Sdougb * SDLZ methods 101225305Sdougb */ 102225305Sdougb 103225305Sdougbstatic isc_result_t 104225305Sdougbdlopen_dlz_allnodes(const char *zone, void *driverarg, void *dbdata, 105225305Sdougb dns_sdlzallnodes_t *allnodes) 106225305Sdougb{ 107225305Sdougb dlopen_data_t *cd = (dlopen_data_t *) dbdata; 108225305Sdougb isc_result_t result; 109225305Sdougb 110225305Sdougb 111225305Sdougb UNUSED(driverarg); 112225305Sdougb 113225305Sdougb if (cd->dlz_allnodes == NULL) { 114225305Sdougb return (ISC_R_NOPERM); 115225305Sdougb } 116225305Sdougb 117225305Sdougb MAYBE_LOCK(cd); 118225305Sdougb result = cd->dlz_allnodes(zone, cd->dbdata, allnodes); 119225305Sdougb MAYBE_UNLOCK(cd); 120225305Sdougb return (result); 121225305Sdougb} 122225305Sdougb 123225305Sdougb 124225305Sdougbstatic isc_result_t 125225305Sdougbdlopen_dlz_allowzonexfr(void *driverarg, void *dbdata, const char *name, 126225305Sdougb const char *client) 127225305Sdougb{ 128225305Sdougb dlopen_data_t *cd = (dlopen_data_t *) dbdata; 129225305Sdougb isc_result_t result; 130225305Sdougb 131225305Sdougb UNUSED(driverarg); 132225305Sdougb 133225305Sdougb 134225305Sdougb if (cd->dlz_allowzonexfr == NULL) { 135225305Sdougb return (ISC_R_NOPERM); 136225305Sdougb } 137225305Sdougb 138225305Sdougb MAYBE_LOCK(cd); 139225305Sdougb result = cd->dlz_allowzonexfr(cd->dbdata, name, client); 140225305Sdougb MAYBE_UNLOCK(cd); 141225305Sdougb return (result); 142225305Sdougb} 143225305Sdougb 144225305Sdougbstatic isc_result_t 145225305Sdougbdlopen_dlz_authority(const char *zone, void *driverarg, void *dbdata, 146254897Serwin dns_sdlzlookup_t *lookup) 147225305Sdougb{ 148225305Sdougb dlopen_data_t *cd = (dlopen_data_t *) dbdata; 149225305Sdougb isc_result_t result; 150225305Sdougb 151225305Sdougb UNUSED(driverarg); 152225305Sdougb 153225305Sdougb if (cd->dlz_authority == NULL) { 154225305Sdougb return (ISC_R_NOTIMPLEMENTED); 155225305Sdougb } 156225305Sdougb 157225305Sdougb MAYBE_LOCK(cd); 158225305Sdougb result = cd->dlz_authority(zone, cd->dbdata, lookup); 159225305Sdougb MAYBE_UNLOCK(cd); 160225305Sdougb return (result); 161225305Sdougb} 162225305Sdougb 163225305Sdougbstatic isc_result_t 164225305Sdougbdlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name) 165225305Sdougb{ 166225305Sdougb dlopen_data_t *cd = (dlopen_data_t *) dbdata; 167225305Sdougb isc_result_t result; 168225305Sdougb 169225305Sdougb UNUSED(driverarg); 170225305Sdougb 171225305Sdougb MAYBE_LOCK(cd); 172225305Sdougb result = cd->dlz_findzonedb(cd->dbdata, name); 173225305Sdougb MAYBE_UNLOCK(cd); 174225305Sdougb return (result); 175225305Sdougb} 176225305Sdougb 177225305Sdougb 178225305Sdougbstatic isc_result_t 179225305Sdougbdlopen_dlz_lookup(const char *zone, const char *name, void *driverarg, 180254897Serwin void *dbdata, dns_sdlzlookup_t *lookup, 181254897Serwin dns_clientinfomethods_t *methods, 182254897Serwin dns_clientinfo_t *clientinfo) 183225305Sdougb{ 184225305Sdougb dlopen_data_t *cd = (dlopen_data_t *) dbdata; 185225305Sdougb isc_result_t result; 186225305Sdougb 187225305Sdougb UNUSED(driverarg); 188225305Sdougb 189225305Sdougb MAYBE_LOCK(cd); 190254897Serwin result = cd->dlz_lookup(zone, name, cd->dbdata, lookup, 191254897Serwin methods, clientinfo); 192225305Sdougb MAYBE_UNLOCK(cd); 193225305Sdougb return (result); 194225305Sdougb} 195225305Sdougb 196225305Sdougb/* 197225305Sdougb * Load a symbol from the library 198225305Sdougb */ 199225305Sdougbstatic void * 200225305Sdougbdl_load_symbol(dlopen_data_t *cd, const char *symbol, isc_boolean_t mandatory) { 201225305Sdougb void *ptr = dlsym(cd->dl_handle, symbol); 202225305Sdougb if (ptr == NULL && mandatory) { 203225305Sdougb dlopen_log(ISC_LOG_ERROR, 204225305Sdougb "dlz_dlopen: library '%s' is missing " 205225305Sdougb "required symbol '%s'", cd->dl_path, symbol); 206225305Sdougb } 207225305Sdougb return (ptr); 208225305Sdougb} 209225305Sdougb 210225305Sdougb/* 211225305Sdougb * Called at startup for each dlopen zone in named.conf 212225305Sdougb */ 213225305Sdougbstatic isc_result_t 214225305Sdougbdlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[], 215225305Sdougb void *driverarg, void **dbdata) 216225305Sdougb{ 217225305Sdougb dlopen_data_t *cd; 218225305Sdougb isc_mem_t *mctx = NULL; 219225305Sdougb isc_result_t result = ISC_R_FAILURE; 220225305Sdougb int dlopen_flags = 0; 221225305Sdougb 222225305Sdougb UNUSED(driverarg); 223225305Sdougb 224225305Sdougb if (argc < 2) { 225225305Sdougb dlopen_log(ISC_LOG_ERROR, 226225305Sdougb "dlz_dlopen driver for '%s' needs a path to " 227225305Sdougb "the shared library", dlzname); 228225305Sdougb return (ISC_R_FAILURE); 229225305Sdougb } 230225305Sdougb 231254402Serwin result = isc_mem_create(0, 0, &mctx); 232254402Serwin if (result != ISC_R_SUCCESS) 233254402Serwin return (result); 234225305Sdougb 235225305Sdougb cd = isc_mem_get(mctx, sizeof(*cd)); 236225305Sdougb if (cd == NULL) { 237225305Sdougb isc_mem_destroy(&mctx); 238225305Sdougb return (ISC_R_NOMEMORY); 239225305Sdougb } 240225305Sdougb memset(cd, 0, sizeof(*cd)); 241225305Sdougb 242225305Sdougb cd->mctx = mctx; 243225305Sdougb 244225305Sdougb cd->dl_path = isc_mem_strdup(cd->mctx, argv[1]); 245225305Sdougb if (cd->dl_path == NULL) { 246225305Sdougb goto failed; 247225305Sdougb } 248225305Sdougb 249225305Sdougb cd->dlzname = isc_mem_strdup(cd->mctx, dlzname); 250225305Sdougb if (cd->dlzname == NULL) { 251225305Sdougb goto failed; 252225305Sdougb } 253225305Sdougb 254225305Sdougb /* Initialize the lock */ 255254402Serwin result = isc_mutex_init(&cd->lock); 256254402Serwin if (result != ISC_R_SUCCESS) 257254402Serwin goto failed; 258225305Sdougb 259225305Sdougb /* Open the library */ 260236374Sdougb dlopen_flags = RTLD_NOW|RTLD_GLOBAL; 261225305Sdougb 262225305Sdougb#ifdef RTLD_DEEPBIND 263225305Sdougb /* 264225305Sdougb * If RTLD_DEEPBIND is available then use it. This can avoid 265225305Sdougb * issues with a module using a different version of a system 266225305Sdougb * library than one that bind9 uses. For example, bind9 may link 267225305Sdougb * to MIT kerberos, but the module may use Heimdal. If we don't 268225305Sdougb * use RTLD_DEEPBIND then we could end up with Heimdal functions 269225305Sdougb * calling MIT functions, which leads to bizarre results (usually 270225305Sdougb * a segfault). 271225305Sdougb */ 272225305Sdougb dlopen_flags |= RTLD_DEEPBIND; 273225305Sdougb#endif 274225305Sdougb 275225305Sdougb cd->dl_handle = dlopen(cd->dl_path, dlopen_flags); 276225305Sdougb if (cd->dl_handle == NULL) { 277225305Sdougb dlopen_log(ISC_LOG_ERROR, 278225305Sdougb "dlz_dlopen failed to open library '%s' - %s", 279225305Sdougb cd->dl_path, dlerror()); 280225305Sdougb goto failed; 281225305Sdougb } 282225305Sdougb 283225305Sdougb /* Find the symbols */ 284225305Sdougb cd->dlz_version = (dlz_dlopen_version_t *) 285225305Sdougb dl_load_symbol(cd, "dlz_version", ISC_TRUE); 286225305Sdougb cd->dlz_create = (dlz_dlopen_create_t *) 287225305Sdougb dl_load_symbol(cd, "dlz_create", ISC_TRUE); 288225305Sdougb cd->dlz_lookup = (dlz_dlopen_lookup_t *) 289225305Sdougb dl_load_symbol(cd, "dlz_lookup", ISC_TRUE); 290225305Sdougb cd->dlz_findzonedb = (dlz_dlopen_findzonedb_t *) 291225305Sdougb dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE); 292225305Sdougb 293225305Sdougb if (cd->dlz_create == NULL || 294225305Sdougb cd->dlz_lookup == NULL || 295225305Sdougb cd->dlz_findzonedb == NULL) 296225305Sdougb { 297225305Sdougb /* We're missing a required symbol */ 298225305Sdougb goto failed; 299225305Sdougb } 300225305Sdougb 301225305Sdougb cd->dlz_allowzonexfr = (dlz_dlopen_allowzonexfr_t *) 302225305Sdougb dl_load_symbol(cd, "dlz_allowzonexfr", ISC_FALSE); 303225305Sdougb cd->dlz_allnodes = (dlz_dlopen_allnodes_t *) 304225305Sdougb dl_load_symbol(cd, "dlz_allnodes", 305225305Sdougb ISC_TF(cd->dlz_allowzonexfr != NULL)); 306225305Sdougb cd->dlz_authority = (dlz_dlopen_authority_t *) 307225305Sdougb dl_load_symbol(cd, "dlz_authority", ISC_FALSE); 308225305Sdougb cd->dlz_newversion = (dlz_dlopen_newversion_t *) 309225305Sdougb dl_load_symbol(cd, "dlz_newversion", ISC_FALSE); 310225305Sdougb cd->dlz_closeversion = (dlz_dlopen_closeversion_t *) 311225305Sdougb dl_load_symbol(cd, "dlz_closeversion", 312225305Sdougb ISC_TF(cd->dlz_newversion != NULL)); 313225305Sdougb cd->dlz_configure = (dlz_dlopen_configure_t *) 314225305Sdougb dl_load_symbol(cd, "dlz_configure", ISC_FALSE); 315225305Sdougb cd->dlz_ssumatch = (dlz_dlopen_ssumatch_t *) 316225305Sdougb dl_load_symbol(cd, "dlz_ssumatch", ISC_FALSE); 317225305Sdougb cd->dlz_addrdataset = (dlz_dlopen_addrdataset_t *) 318225305Sdougb dl_load_symbol(cd, "dlz_addrdataset", ISC_FALSE); 319225305Sdougb cd->dlz_subrdataset = (dlz_dlopen_subrdataset_t *) 320225305Sdougb dl_load_symbol(cd, "dlz_subrdataset", ISC_FALSE); 321225305Sdougb cd->dlz_delrdataset = (dlz_dlopen_delrdataset_t *) 322225305Sdougb dl_load_symbol(cd, "dlz_delrdataset", ISC_FALSE); 323234010Sdougb cd->dlz_destroy = (dlz_dlopen_destroy_t *) 324234010Sdougb dl_load_symbol(cd, "dlz_destroy", ISC_FALSE); 325225305Sdougb 326225305Sdougb /* Check the version of the API is the same */ 327225305Sdougb cd->version = cd->dlz_version(&cd->flags); 328225305Sdougb if (cd->version != DLZ_DLOPEN_VERSION) { 329225305Sdougb dlopen_log(ISC_LOG_ERROR, 330225305Sdougb "dlz_dlopen: incorrect version %d " 331225305Sdougb "should be %d in '%s'", 332225305Sdougb cd->version, DLZ_DLOPEN_VERSION, cd->dl_path); 333225305Sdougb goto failed; 334225305Sdougb } 335225305Sdougb 336225305Sdougb /* 337225305Sdougb * Call the library's create function. Note that this is an 338225305Sdougb * extended version of dlz create, with the addition of 339225305Sdougb * named function pointers for helper functions that the 340225305Sdougb * driver will need. This avoids the need for the backend to 341225305Sdougb * link the BIND9 libraries 342225305Sdougb */ 343225305Sdougb MAYBE_LOCK(cd); 344225305Sdougb result = cd->dlz_create(dlzname, argc-1, argv+1, 345225305Sdougb &cd->dbdata, 346225305Sdougb "log", dlopen_log, 347225305Sdougb "putrr", dns_sdlz_putrr, 348225305Sdougb "putnamedrr", dns_sdlz_putnamedrr, 349225305Sdougb "writeable_zone", dns_dlz_writeablezone, 350225305Sdougb NULL); 351225305Sdougb MAYBE_UNLOCK(cd); 352225305Sdougb if (result != ISC_R_SUCCESS) 353225305Sdougb goto failed; 354225305Sdougb 355225305Sdougb *dbdata = cd; 356225305Sdougb 357225305Sdougb return (ISC_R_SUCCESS); 358225305Sdougb 359225305Sdougbfailed: 360225305Sdougb dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname); 361254402Serwin if (cd->dl_path != NULL) 362225305Sdougb isc_mem_free(mctx, cd->dl_path); 363254402Serwin if (cd->dlzname != NULL) 364225305Sdougb isc_mem_free(mctx, cd->dlzname); 365254402Serwin if (dlopen_flags != 0) 366225305Sdougb (void) isc_mutex_destroy(&cd->lock); 367225305Sdougb#ifdef HAVE_DLCLOSE 368225305Sdougb if (cd->dl_handle) 369225305Sdougb dlclose(cd->dl_handle); 370225305Sdougb#endif 371225305Sdougb isc_mem_put(mctx, cd, sizeof(*cd)); 372225305Sdougb isc_mem_destroy(&mctx); 373225305Sdougb return (result); 374225305Sdougb} 375225305Sdougb 376225305Sdougb 377225305Sdougb/* 378225305Sdougb * Called when bind is shutting down 379225305Sdougb */ 380225305Sdougbstatic void 381225305Sdougbdlopen_dlz_destroy(void *driverarg, void *dbdata) { 382225305Sdougb dlopen_data_t *cd = (dlopen_data_t *) dbdata; 383225305Sdougb isc_mem_t *mctx; 384225305Sdougb 385225305Sdougb UNUSED(driverarg); 386225305Sdougb 387225305Sdougb if (cd->dlz_destroy) { 388225305Sdougb MAYBE_LOCK(cd); 389225305Sdougb cd->dlz_destroy(cd->dbdata); 390225305Sdougb MAYBE_UNLOCK(cd); 391225305Sdougb } 392225305Sdougb 393225305Sdougb if (cd->dl_path) 394225305Sdougb isc_mem_free(cd->mctx, cd->dl_path); 395225305Sdougb if (cd->dlzname) 396225305Sdougb isc_mem_free(cd->mctx, cd->dlzname); 397225305Sdougb 398225305Sdougb#ifdef HAVE_DLCLOSE 399225305Sdougb if (cd->dl_handle) 400225305Sdougb dlclose(cd->dl_handle); 401225305Sdougb#endif 402225305Sdougb 403225305Sdougb (void) isc_mutex_destroy(&cd->lock); 404225305Sdougb 405225305Sdougb mctx = cd->mctx; 406225305Sdougb isc_mem_put(mctx, cd, sizeof(*cd)); 407225305Sdougb isc_mem_destroy(&mctx); 408225305Sdougb} 409225305Sdougb 410225305Sdougb/* 411225305Sdougb * Called to start a transaction 412225305Sdougb */ 413225305Sdougbstatic isc_result_t 414225305Sdougbdlopen_dlz_newversion(const char *zone, void *driverarg, void *dbdata, 415225305Sdougb void **versionp) 416225305Sdougb{ 417225305Sdougb dlopen_data_t *cd = (dlopen_data_t *) dbdata; 418225305Sdougb isc_result_t result; 419225305Sdougb 420225305Sdougb UNUSED(driverarg); 421225305Sdougb 422225305Sdougb if (cd->dlz_newversion == NULL) 423225305Sdougb return (ISC_R_NOTIMPLEMENTED); 424225305Sdougb 425225305Sdougb MAYBE_LOCK(cd); 426225305Sdougb result = cd->dlz_newversion(zone, cd->dbdata, versionp); 427225305Sdougb MAYBE_UNLOCK(cd); 428225305Sdougb return (result); 429225305Sdougb} 430225305Sdougb 431225305Sdougb/* 432225305Sdougb * Called to end a transaction 433225305Sdougb */ 434225305Sdougbstatic void 435225305Sdougbdlopen_dlz_closeversion(const char *zone, isc_boolean_t commit, 436225305Sdougb void *driverarg, void *dbdata, void **versionp) 437225305Sdougb{ 438225305Sdougb dlopen_data_t *cd = (dlopen_data_t *) dbdata; 439225305Sdougb 440225305Sdougb UNUSED(driverarg); 441225305Sdougb 442225305Sdougb if (cd->dlz_newversion == NULL) { 443225305Sdougb *versionp = NULL; 444225305Sdougb return; 445225305Sdougb } 446225305Sdougb 447225305Sdougb MAYBE_LOCK(cd); 448225305Sdougb cd->dlz_closeversion(zone, commit, cd->dbdata, versionp); 449225305Sdougb MAYBE_UNLOCK(cd); 450225305Sdougb} 451225305Sdougb 452225305Sdougb/* 453225305Sdougb * Called on startup to configure any writeable zones 454225305Sdougb */ 455225305Sdougbstatic isc_result_t 456225305Sdougbdlopen_dlz_configure(dns_view_t *view, void *driverarg, void *dbdata) { 457225305Sdougb dlopen_data_t *cd = (dlopen_data_t *) dbdata; 458225305Sdougb isc_result_t result; 459225305Sdougb 460225305Sdougb UNUSED(driverarg); 461225305Sdougb 462225305Sdougb if (cd->dlz_configure == NULL) 463225305Sdougb return (ISC_R_SUCCESS); 464225305Sdougb 465225305Sdougb MAYBE_LOCK(cd); 466225305Sdougb cd->in_configure = ISC_TRUE; 467225305Sdougb result = cd->dlz_configure(view, cd->dbdata); 468225305Sdougb cd->in_configure = ISC_FALSE; 469225305Sdougb MAYBE_UNLOCK(cd); 470225305Sdougb 471225305Sdougb return (result); 472225305Sdougb} 473225305Sdougb 474225305Sdougb 475225305Sdougb/* 476225305Sdougb * Check for authority to change a name 477225305Sdougb */ 478225305Sdougbstatic isc_boolean_t 479225305Sdougbdlopen_dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr, 480225305Sdougb const char *type, const char *key, isc_uint32_t keydatalen, 481225305Sdougb unsigned char *keydata, void *driverarg, void *dbdata) 482225305Sdougb{ 483225305Sdougb dlopen_data_t *cd = (dlopen_data_t *) dbdata; 484225305Sdougb isc_boolean_t ret; 485225305Sdougb 486225305Sdougb UNUSED(driverarg); 487225305Sdougb 488225305Sdougb if (cd->dlz_ssumatch == NULL) 489225305Sdougb return (ISC_FALSE); 490225305Sdougb 491225305Sdougb MAYBE_LOCK(cd); 492225305Sdougb ret = cd->dlz_ssumatch(signer, name, tcpaddr, type, key, keydatalen, 493225305Sdougb keydata, cd->dbdata); 494225305Sdougb MAYBE_UNLOCK(cd); 495225305Sdougb 496225305Sdougb return (ret); 497225305Sdougb} 498225305Sdougb 499225305Sdougb 500225305Sdougb/* 501225305Sdougb * Add an rdataset 502225305Sdougb */ 503225305Sdougbstatic isc_result_t 504225305Sdougbdlopen_dlz_addrdataset(const char *name, const char *rdatastr, 505225305Sdougb void *driverarg, void *dbdata, void *version) 506225305Sdougb{ 507225305Sdougb dlopen_data_t *cd = (dlopen_data_t *) dbdata; 508225305Sdougb isc_result_t result; 509225305Sdougb 510225305Sdougb UNUSED(driverarg); 511225305Sdougb 512225305Sdougb if (cd->dlz_addrdataset == NULL) 513225305Sdougb return (ISC_R_NOTIMPLEMENTED); 514225305Sdougb 515225305Sdougb MAYBE_LOCK(cd); 516225305Sdougb result = cd->dlz_addrdataset(name, rdatastr, cd->dbdata, version); 517225305Sdougb MAYBE_UNLOCK(cd); 518225305Sdougb 519225305Sdougb return (result); 520225305Sdougb} 521225305Sdougb 522225305Sdougb/* 523225305Sdougb * Subtract an rdataset 524225305Sdougb */ 525225305Sdougbstatic isc_result_t 526225305Sdougbdlopen_dlz_subrdataset(const char *name, const char *rdatastr, 527225305Sdougb void *driverarg, void *dbdata, void *version) 528225305Sdougb{ 529225305Sdougb dlopen_data_t *cd = (dlopen_data_t *) dbdata; 530225305Sdougb isc_result_t result; 531225305Sdougb 532225305Sdougb UNUSED(driverarg); 533225305Sdougb 534225305Sdougb if (cd->dlz_subrdataset == NULL) 535225305Sdougb return (ISC_R_NOTIMPLEMENTED); 536225305Sdougb 537225305Sdougb MAYBE_LOCK(cd); 538225305Sdougb result = cd->dlz_subrdataset(name, rdatastr, cd->dbdata, version); 539225305Sdougb MAYBE_UNLOCK(cd); 540225305Sdougb 541225305Sdougb return (result); 542225305Sdougb} 543225305Sdougb 544225305Sdougb/* 545225305Sdougb delete a rdataset 546225305Sdougb */ 547225305Sdougbstatic isc_result_t 548225305Sdougbdlopen_dlz_delrdataset(const char *name, const char *type, 549225305Sdougb void *driverarg, void *dbdata, void *version) 550225305Sdougb{ 551225305Sdougb dlopen_data_t *cd = (dlopen_data_t *) dbdata; 552225305Sdougb isc_result_t result; 553225305Sdougb 554225305Sdougb UNUSED(driverarg); 555225305Sdougb 556225305Sdougb if (cd->dlz_delrdataset == NULL) 557225305Sdougb return (ISC_R_NOTIMPLEMENTED); 558225305Sdougb 559225305Sdougb MAYBE_LOCK(cd); 560225305Sdougb result = cd->dlz_delrdataset(name, type, cd->dbdata, version); 561225305Sdougb MAYBE_UNLOCK(cd); 562225305Sdougb 563225305Sdougb return (result); 564225305Sdougb} 565225305Sdougb 566225305Sdougb 567225305Sdougbstatic dns_sdlzmethods_t dlz_dlopen_methods = { 568225305Sdougb dlopen_dlz_create, 569225305Sdougb dlopen_dlz_destroy, 570225305Sdougb dlopen_dlz_findzonedb, 571225305Sdougb dlopen_dlz_lookup, 572225305Sdougb dlopen_dlz_authority, 573225305Sdougb dlopen_dlz_allnodes, 574225305Sdougb dlopen_dlz_allowzonexfr, 575225305Sdougb dlopen_dlz_newversion, 576225305Sdougb dlopen_dlz_closeversion, 577225305Sdougb dlopen_dlz_configure, 578225305Sdougb dlopen_dlz_ssumatch, 579225305Sdougb dlopen_dlz_addrdataset, 580225305Sdougb dlopen_dlz_subrdataset, 581225305Sdougb dlopen_dlz_delrdataset 582225305Sdougb}; 583225305Sdougb#endif 584225305Sdougb 585225305Sdougb/* 586225305Sdougb * Register driver with BIND 587225305Sdougb */ 588225305Sdougbisc_result_t 589225305Sdougbdlz_dlopen_init(isc_mem_t *mctx) { 590225305Sdougb#ifndef ISC_DLZ_DLOPEN 591225305Sdougb UNUSED(mctx); 592225305Sdougb return (ISC_R_NOTIMPLEMENTED); 593225305Sdougb#else 594225305Sdougb isc_result_t result; 595225305Sdougb 596225305Sdougb dlopen_log(2, "Registering DLZ_dlopen driver"); 597225305Sdougb 598225305Sdougb result = dns_sdlzregister("dlopen", &dlz_dlopen_methods, NULL, 599225305Sdougb DNS_SDLZFLAG_RELATIVEOWNER | 600225305Sdougb DNS_SDLZFLAG_THREADSAFE, 601225305Sdougb mctx, &dlz_dlopen); 602225305Sdougb 603225305Sdougb if (result != ISC_R_SUCCESS) { 604225305Sdougb UNEXPECTED_ERROR(__FILE__, __LINE__, 605225305Sdougb "dns_sdlzregister() failed: %s", 606225305Sdougb isc_result_totext(result)); 607225305Sdougb result = ISC_R_UNEXPECTED; 608225305Sdougb } 609225305Sdougb 610225305Sdougb return (result); 611225305Sdougb#endif 612225305Sdougb} 613225305Sdougb 614225305Sdougb 615225305Sdougb/* 616225305Sdougb * Unregister the driver 617225305Sdougb */ 618225305Sdougbvoid 619225305Sdougbdlz_dlopen_clear(void) { 620225305Sdougb#ifdef ISC_DLZ_DLOPEN 621225305Sdougb dlopen_log(2, "Unregistering DLZ_dlopen driver"); 622225305Sdougb if (dlz_dlopen != NULL) 623225305Sdougb dns_sdlzunregister(&dlz_dlopen); 624225305Sdougb#endif 625225305Sdougb} 626