/* * Called when bind is shutting down */ static void dlopen_dlz_destroy(void *driverarg, void *dbdata) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_mem_t *mctx; UNUSED(driverarg); if (cd->dlz_destroy) { MAYBE_LOCK(cd); cd->dlz_destroy(cd->dbdata); MAYBE_UNLOCK(cd); } if (cd->dl_path) isc_mem_free(cd->mctx, cd->dl_path); if (cd->dlzname) isc_mem_free(cd->mctx, cd->dlzname); #ifdef HAVE_DLCLOSE if (cd->dl_handle) dlclose(cd->dl_handle); #endif (void) isc_mutex_destroy(&cd->lock); mctx = cd->mctx; isc_mem_put(mctx, cd, sizeof(*cd)); isc_mem_destroy(&mctx); }
/* * Called when bind is shutting down */ static void dlopen_dlz_destroy(void *driverarg, void *dbdata) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_mem_t *mctx; UNUSED(driverarg); if (cd->dlz_destroy) { MAYBE_LOCK(cd); cd->dlz_destroy(cd->dbdata); MAYBE_UNLOCK(cd); } if (cd->dl_path) isc_mem_free(cd->mctx, cd->dl_path); if (cd->dlzname) isc_mem_free(cd->mctx, cd->dlzname); if (cd->dl_handle) FreeLibrary(cd->dl_handle); DESTROYLOCK(&cd->lock); mctx = cd->mctx; isc_mem_put(mctx, cd, sizeof(*cd)); isc_mem_destroy(&mctx); }
static isc_result_t dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); MAYBE_LOCK(cd); result = cd->dlz_findzonedb(cd->dbdata, name); MAYBE_UNLOCK(cd); return (result); }
static isc_result_t dlopen_dlz_lookup(const char *zone, const char *name, void *driverarg, void *dbdata, dns_sdlzlookup_t *lookup) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); MAYBE_LOCK(cd); result = cd->dlz_lookup(zone, name, cd->dbdata, lookup); MAYBE_UNLOCK(cd); return (result); }
static isc_result_t dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name, dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); MAYBE_LOCK(cd); result = cd->dlz_findzonedb(cd->dbdata, name, methods, clientinfo); MAYBE_UNLOCK(cd); return (result); }
/* * Called to end a transaction */ static void dlopen_dlz_closeversion(const char *zone, isc_boolean_t commit, void *driverarg, void *dbdata, void **versionp) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; UNUSED(driverarg); if (cd->dlz_newversion == NULL) { *versionp = NULL; return; } MAYBE_LOCK(cd); cd->dlz_closeversion(zone, commit, cd->dbdata, versionp); MAYBE_UNLOCK(cd); }
/* * Called to start a transaction */ static isc_result_t dlopen_dlz_newversion(const char *zone, void *driverarg, void *dbdata, void **versionp) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_newversion == NULL) return (ISC_R_NOTIMPLEMENTED); MAYBE_LOCK(cd); result = cd->dlz_newversion(zone, cd->dbdata, versionp); MAYBE_UNLOCK(cd); return (result); }
/* delete a rdataset */ static isc_result_t dlopen_dlz_delrdataset(const char *name, const char *type, void *driverarg, void *dbdata, void *version) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_delrdataset == NULL) return (ISC_R_NOTIMPLEMENTED); MAYBE_LOCK(cd); result = cd->dlz_delrdataset(name, type, cd->dbdata, version); MAYBE_UNLOCK(cd); return (result); }
static isc_result_t dlopen_dlz_authority(const char *zone, void *driverarg, void *dbdata, dns_sdlzlookup_t *lookup) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_authority == NULL) { return (ISC_R_NOTIMPLEMENTED); } MAYBE_LOCK(cd); result = cd->dlz_authority(zone, cd->dbdata, lookup); MAYBE_UNLOCK(cd); return (result); }
/* * Called on startup to configure any writeable zones */ static isc_result_t dlopen_dlz_configure(dns_view_t *view, void *driverarg, void *dbdata) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_configure == NULL) return (ISC_R_SUCCESS); MAYBE_LOCK(cd); cd->in_configure = ISC_TRUE; result = cd->dlz_configure(view, cd->dbdata); cd->in_configure = ISC_FALSE; MAYBE_UNLOCK(cd); return (result); }
static isc_result_t dlopen_dlz_allnodes(const char *zone, void *driverarg, void *dbdata, dns_sdlzallnodes_t *allnodes) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_allnodes == NULL) { return (ISC_R_NOPERM); } MAYBE_LOCK(cd); result = cd->dlz_allnodes(zone, cd->dbdata, allnodes); MAYBE_UNLOCK(cd); return (result); }
static isc_result_t dlopen_dlz_allowzonexfr(void *driverarg, void *dbdata, const char *name, const char *client) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; UNUSED(driverarg); if (cd->dlz_allowzonexfr == NULL) { return (ISC_R_NOPERM); } MAYBE_LOCK(cd); result = cd->dlz_allowzonexfr(cd->dbdata, name, client); MAYBE_UNLOCK(cd); return (result); }
/* * Check for authority to change a name */ static isc_boolean_t dlopen_dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr, const char *type, const char *key, isc_uint32_t keydatalen, unsigned char *keydata, void *driverarg, void *dbdata) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_boolean_t ret; UNUSED(driverarg); if (cd->dlz_ssumatch == NULL) return (ISC_FALSE); MAYBE_LOCK(cd); ret = cd->dlz_ssumatch(signer, name, tcpaddr, type, key, keydatalen, keydata, cd->dbdata); MAYBE_UNLOCK(cd); return (ret); }
/* * Called at startup for each dlopen zone in named.conf */ static isc_result_t dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[], void *driverarg, void **dbdata) { dlopen_data_t *cd; isc_mem_t *mctx = NULL; isc_result_t result = ISC_R_FAILURE; int dlopen_flags = 0; UNUSED(driverarg); if (argc < 2) { dlopen_log(ISC_LOG_ERROR, "dlz_dlopen driver for '%s' needs a path to " "the shared library", dlzname); return (ISC_R_FAILURE); } result = isc_mem_create(0, 0, &mctx); if (result != ISC_R_SUCCESS) return (result); cd = isc_mem_get(mctx, sizeof(*cd)); if (cd == NULL) { isc_mem_destroy(&mctx); return (ISC_R_NOMEMORY); } memset(cd, 0, sizeof(*cd)); cd->mctx = mctx; cd->dl_path = isc_mem_strdup(cd->mctx, argv[1]); if (cd->dl_path == NULL) { result = ISC_R_NOMEMORY; goto failed; } cd->dlzname = isc_mem_strdup(cd->mctx, dlzname); if (cd->dlzname == NULL) { result = ISC_R_NOMEMORY; goto failed; } /* Initialize the lock */ result = isc_mutex_init(&cd->lock); if (result != ISC_R_SUCCESS) goto failed; /* Open the library */ dlopen_flags = RTLD_NOW|RTLD_GLOBAL; #ifdef RTLD_DEEPBIND /* * If RTLD_DEEPBIND is available then use it. This can avoid * issues with a module using a different version of a system * library than one that bind9 uses. For example, bind9 may link * to MIT kerberos, but the module may use Heimdal. If we don't * use RTLD_DEEPBIND then we could end up with Heimdal functions * calling MIT functions, which leads to bizarre results (usually * a segfault). */ dlopen_flags |= RTLD_DEEPBIND; #endif cd->dl_handle = dlopen(cd->dl_path, dlopen_flags); if (cd->dl_handle == NULL) { dlopen_log(ISC_LOG_ERROR, "dlz_dlopen failed to open library '%s' - %s", cd->dl_path, dlerror()); result = ISC_R_FAILURE; goto failed; } /* Find the symbols */ cd->dlz_version = (dlz_dlopen_version_t *) dl_load_symbol(cd, "dlz_version", ISC_TRUE); cd->dlz_create = (dlz_dlopen_create_t *) dl_load_symbol(cd, "dlz_create", ISC_TRUE); cd->dlz_lookup = (dlz_dlopen_lookup_t *) dl_load_symbol(cd, "dlz_lookup", ISC_TRUE); cd->dlz_findzonedb = (dlz_dlopen_findzonedb_t *) dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE); if (cd->dlz_create == NULL || cd->dlz_version == NULL || cd->dlz_lookup == NULL || cd->dlz_findzonedb == NULL) { /* We're missing a required symbol */ result = ISC_R_FAILURE; goto failed; } cd->dlz_allowzonexfr = (dlz_dlopen_allowzonexfr_t *) dl_load_symbol(cd, "dlz_allowzonexfr", ISC_FALSE); cd->dlz_allnodes = (dlz_dlopen_allnodes_t *) dl_load_symbol(cd, "dlz_allnodes", ISC_TF(cd->dlz_allowzonexfr != NULL)); cd->dlz_authority = (dlz_dlopen_authority_t *) dl_load_symbol(cd, "dlz_authority", ISC_FALSE); cd->dlz_newversion = (dlz_dlopen_newversion_t *) dl_load_symbol(cd, "dlz_newversion", ISC_FALSE); cd->dlz_closeversion = (dlz_dlopen_closeversion_t *) dl_load_symbol(cd, "dlz_closeversion", ISC_TF(cd->dlz_newversion != NULL)); cd->dlz_configure = (dlz_dlopen_configure_t *) dl_load_symbol(cd, "dlz_configure", ISC_FALSE); cd->dlz_ssumatch = (dlz_dlopen_ssumatch_t *) dl_load_symbol(cd, "dlz_ssumatch", ISC_FALSE); cd->dlz_addrdataset = (dlz_dlopen_addrdataset_t *) dl_load_symbol(cd, "dlz_addrdataset", ISC_FALSE); cd->dlz_subrdataset = (dlz_dlopen_subrdataset_t *) dl_load_symbol(cd, "dlz_subrdataset", ISC_FALSE); cd->dlz_delrdataset = (dlz_dlopen_delrdataset_t *) dl_load_symbol(cd, "dlz_delrdataset", ISC_FALSE); cd->dlz_destroy = (dlz_dlopen_destroy_t *) dl_load_symbol(cd, "dlz_destroy", ISC_FALSE); /* Check the version of the API is the same */ cd->version = cd->dlz_version(&cd->flags); if (cd->version < (DLZ_DLOPEN_VERSION - DLZ_DLOPEN_AGE) || cd->version > DLZ_DLOPEN_VERSION) { dlopen_log(ISC_LOG_ERROR, "dlz_dlopen: %s: incorrect driver API version %d, " "requires %d", cd->dl_path, cd->version, DLZ_DLOPEN_VERSION); result = ISC_R_FAILURE; goto failed; } /* * Call the library's create function. Note that this is an * extended version of dlz create, with the addition of * named function pointers for helper functions that the * driver will need. This avoids the need for the backend to * link the BIND9 libraries */ MAYBE_LOCK(cd); result = cd->dlz_create(dlzname, argc-1, argv+1, &cd->dbdata, "log", dlopen_log, "putrr", dns_sdlz_putrr, "putnamedrr", dns_sdlz_putnamedrr, "writeable_zone", dns_dlz_writeablezone, NULL); MAYBE_UNLOCK(cd); if (result != ISC_R_SUCCESS) goto failed; *dbdata = cd; return (ISC_R_SUCCESS); failed: dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname); if (cd->dl_path != NULL) isc_mem_free(mctx, cd->dl_path); if (cd->dlzname != NULL) isc_mem_free(mctx, cd->dlzname); if (dlopen_flags != 0) (void) isc_mutex_destroy(&cd->lock); #ifdef HAVE_DLCLOSE if (cd->dl_handle) dlclose(cd->dl_handle); #endif isc_mem_put(mctx, cd, sizeof(*cd)); isc_mem_destroy(&mctx); return (result); }
/* * Called at startup for each dlopen zone in named.conf */ static isc_result_t dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[], void *driverarg, void **dbdata) { dlopen_data_t *cd; isc_mem_t *mctx = NULL; isc_result_t result = ISC_R_FAILURE; isc_boolean_t triedload = ISC_FALSE; UNUSED(driverarg); if (argc < 2) { dlopen_log(ISC_LOG_ERROR, "dlz_dlopen driver for '%s' needs a path to " "the shared library", dlzname); return (ISC_R_FAILURE); } isc_mem_create(0, 0, &mctx); cd = isc_mem_get(mctx, sizeof(*cd)); if (cd == NULL) { isc_mem_destroy(&mctx); return (ISC_R_NOMEMORY); } memset(cd, 0, sizeof(*cd)); cd->mctx = mctx; cd->dl_path = isc_mem_strdup(cd->mctx, argv[1]); if (cd->dl_path == NULL) { goto failed; } cd->dlzname = isc_mem_strdup(cd->mctx, dlzname); if (cd->dlzname == NULL) { goto failed; } triedload = ISC_TRUE; /* Initialize the lock */ isc_mutex_init(&cd->lock); /* Open the library */ cd->dl_handle = LoadLibraryA(cd->dl_path); if (cd->dl_handle == NULL) { unsigned int error = GetLastError(); dlopen_log(ISC_LOG_ERROR, "dlz_dlopen failed to open library '%s' - %u", cd->dl_path, error); goto failed; } /* Find the symbols */ cd->dlz_version = (dlz_dlopen_version_t *) dl_load_symbol(cd, "dlz_version", ISC_TRUE); cd->dlz_create = (dlz_dlopen_create_t *) dl_load_symbol(cd, "dlz_create", ISC_TRUE); cd->dlz_lookup = (dlz_dlopen_lookup_t *) dl_load_symbol(cd, "dlz_lookup", ISC_TRUE); cd->dlz_findzonedb = (dlz_dlopen_findzonedb_t *) dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE); if (cd->dlz_create == NULL || cd->dlz_lookup == NULL || cd->dlz_findzonedb == NULL) { /* We're missing a required symbol */ goto failed; } cd->dlz_allowzonexfr = (dlz_dlopen_allowzonexfr_t *) dl_load_symbol(cd, "dlz_allowzonexfr", ISC_FALSE); cd->dlz_allnodes = (dlz_dlopen_allnodes_t *) dl_load_symbol(cd, "dlz_allnodes", ISC_TF(cd->dlz_allowzonexfr != NULL)); cd->dlz_authority = (dlz_dlopen_authority_t *) dl_load_symbol(cd, "dlz_authority", ISC_FALSE); cd->dlz_newversion = (dlz_dlopen_newversion_t *) dl_load_symbol(cd, "dlz_newversion", ISC_FALSE); cd->dlz_closeversion = (dlz_dlopen_closeversion_t *) dl_load_symbol(cd, "dlz_closeversion", ISC_TF(cd->dlz_newversion != NULL)); cd->dlz_configure = (dlz_dlopen_configure_t *) dl_load_symbol(cd, "dlz_configure", ISC_FALSE); cd->dlz_ssumatch = (dlz_dlopen_ssumatch_t *) dl_load_symbol(cd, "dlz_ssumatch", ISC_FALSE); cd->dlz_addrdataset = (dlz_dlopen_addrdataset_t *) dl_load_symbol(cd, "dlz_addrdataset", ISC_FALSE); cd->dlz_subrdataset = (dlz_dlopen_subrdataset_t *) dl_load_symbol(cd, "dlz_subrdataset", ISC_FALSE); cd->dlz_delrdataset = (dlz_dlopen_delrdataset_t *) dl_load_symbol(cd, "dlz_delrdataset", ISC_FALSE); /* Check the version of the API is the same */ cd->version = cd->dlz_version(&cd->flags); if (cd->version != DLZ_DLOPEN_VERSION) { dlopen_log(ISC_LOG_ERROR, "dlz_dlopen: incorrect version %d " "should be %d in '%s'", cd->version, DLZ_DLOPEN_VERSION, cd->dl_path); goto failed; } /* * Call the library's create function. Note that this is an * extended version of dlz create, with the addition of * named function pointers for helper functions that the * driver will need. This avoids the need for the backend to * link the BIND9 libraries */ MAYBE_LOCK(cd); result = cd->dlz_create(dlzname, argc-1, argv+1, &cd->dbdata, "log", dlopen_log, "putrr", dns_sdlz_putrr, "putnamedrr", dns_sdlz_putnamedrr, "writeable_zone", dns_dlz_writeablezone, NULL); MAYBE_UNLOCK(cd); if (result != ISC_R_SUCCESS) goto failed; *dbdata = cd; return (ISC_R_SUCCESS); failed: dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname); if (cd->dl_path) isc_mem_free(mctx, cd->dl_path); if (cd->dlzname) isc_mem_free(mctx, cd->dlzname); if (triedload) (void) isc_mutex_destroy(&cd->lock); if (cd->dl_handle) FreeLibrary(cd->dl_handle); isc_mem_put(mctx, cd, sizeof(*cd)); isc_mem_destroy(&mctx); return (result); }