diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 07:24:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 07:24:22 +0000 |
commit | 45d6379135504814ab723b57f0eb8be23393a51d (patch) | |
tree | d4f2ec4acca824a8446387a758b0ce4238a4dffa /contrib/dlz/modules/bdbhpt/dlz_bdbhpt_dynamic.c | |
parent | Initial commit. (diff) | |
download | bind9-upstream.tar.xz bind9-upstream.zip |
Adding upstream version 1:9.16.44.upstream/1%9.16.44upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | contrib/dlz/modules/bdbhpt/dlz_bdbhpt_dynamic.c | 837 |
1 files changed, 837 insertions, 0 deletions
diff --git a/contrib/dlz/modules/bdbhpt/dlz_bdbhpt_dynamic.c b/contrib/dlz/modules/bdbhpt/dlz_bdbhpt_dynamic.c new file mode 100644 index 0000000..e84f866 --- /dev/null +++ b/contrib/dlz/modules/bdbhpt/dlz_bdbhpt_dynamic.c @@ -0,0 +1,837 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 and ISC + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + */ + +/* + * Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl. + * + * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was + * conceived and contributed by Rob Butler. + * + * Permission to use, copy, modify, and distribute this software for any purpose + * with or without fee is hereby granted, provided that the above copyright + * notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This is simply a merge of Andrew Tridgell's dlz_example.c and the + * original bdb_bdbhpt_driver.c + * + * This provides the externally loadable bdbhpt DLZ driver, without + * update support + * + */ + +#include <db.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "dlz_minimal.h" + +/* should the bdb driver use threads. */ +#define bdbhpt_threads DB_THREAD + +/* bdbhpt database names */ +#define dlz_data "dns_data" +#define dlz_zone "dns_zone" +#define dlz_xfr "dns_xfr" +#define dlz_client "dns_client" + +#define dlz_bdbhpt_dynamic_version "0.1" + +/* + * This structure contains all our DB handles and helper functions we + * inherit from the dlz_dlopen driver + * + */ +typedef struct bdbhpt_instance { + DB_ENV *dbenv; /* bdbhpt environment */ + DB *data; /* dns_data database handle */ + DB *zone; /* zone database handle */ + DB *xfr; /* zone xfr database handle */ + DB *client; /* client database handle */ + + /* Helper functions from the dlz_dlopen driver */ + log_t *log; + dns_sdlz_putrr_t *putrr; + dns_sdlz_putnamedrr_t *putnamedrr; + dns_dlz_writeablezone_t *writeable_zone; +} bdbhpt_instance_t; + +typedef struct bdbhpt_parsed_data { + char *host; + char *type; + int ttl; + char *data; +} bdbhpt_parsed_data_t; + +static void +b9_add_helper(struct bdbhpt_instance *db, const char *helper_name, void *ptr); + +/*% + * Reverses a string in place. + */ +static char * +bdbhpt_strrev(char *str) { + char *p1, *p2; + + if (!str || !*str) { + return (str); + } + for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2) { + *p1 ^= *p2; + *p2 ^= *p1; + *p1 ^= *p2; + } + return (str); +} + +/*% + * Parses the DBT from the Berkeley DB into a parsed_data record + * The parsed_data record should be allocated before and passed into the + * bdbhpt_parse_data function. The char (type & data) fields should not + * be "free"d as that memory is part of the DBT data field. It will be + * "free"d when the DBT is freed. + */ + +static isc_result_t +bdbhpt_parse_data(log_t *log, char *in, bdbhpt_parsed_data_t *pd) { + char *endp, *ttlStr; + char *tmp = in; + char *lastchar = (char *)&tmp[strlen(tmp)]; + + /*% + * String should be formatted as: + * replication_id + * (a space) + * host_name + * (a space) + * ttl + * (a space) + * type + * (a space) + * remaining data + * + * examples: + * + * 9191 host 10 A 127.0.0.1 + * server1_212 host 10 A 127.0.0.2 + * {xxxx-xxxx-xxxx-xxxx-xxxx} host 10 MX 20 mail.example.com + */ + + /* + * we don't need the replication id, so don't + * bother saving a pointer to it. + */ + + /* find space after replication id */ + tmp = strchr(tmp, ' '); + /* verify we found a space */ + if (tmp == NULL) { + return (ISC_R_FAILURE); + } + /* make sure it is safe to increment pointer */ + if (++tmp > lastchar) { + return (ISC_R_FAILURE); + } + + /* save pointer to host */ + pd->host = tmp; + + /* find space after host and change it to a '\0' */ + tmp = strchr(tmp, ' '); + /* verify we found a space */ + if (tmp == NULL) { + return (ISC_R_FAILURE); + } + /* change the space to a null (string terminator) */ + tmp[0] = '\0'; + /* make sure it is safe to increment pointer */ + if (++tmp > lastchar) { + return (ISC_R_FAILURE); + } + + /* save pointer to ttl string */ + ttlStr = tmp; + + /* find space after ttl and change it to a '\0' */ + tmp = strchr(tmp, ' '); + /* verify we found a space */ + if (tmp == NULL) { + return (ISC_R_FAILURE); + } + /* change the space to a null (string terminator) */ + tmp[0] = '\0'; + /* make sure it is safe to increment pointer */ + if (++tmp > lastchar) { + return (ISC_R_FAILURE); + } + + /* save pointer to dns type */ + pd->type = tmp; + + /* find space after type and change it to a '\0' */ + tmp = strchr(tmp, ' '); + /* verify we found a space */ + if (tmp == NULL) { + return (ISC_R_FAILURE); + } + /* change the space to a null (string terminator) */ + tmp[0] = '\0'; + /* make sure it is safe to increment pointer */ + if (++tmp > lastchar) { + return (ISC_R_FAILURE); + } + + /* save pointer to remainder of DNS data */ + pd->data = tmp; + + /* convert ttl string to integer */ + pd->ttl = strtol(ttlStr, &endp, 10); + if (*endp != '\0' || pd->ttl < 0) { + log(ISC_LOG_ERROR, "bdbhpt_dynamic: " + "ttl must be a positive number"); + return (ISC_R_FAILURE); + } + + /* if we get this far everything should have worked. */ + return (ISC_R_SUCCESS); +} + +/* + * See if a zone transfer is allowed + */ +isc_result_t +dlz_allowzonexfr(void *dbdata, const char *name, const char *client) { + isc_result_t result; + bdbhpt_instance_t *db = (bdbhpt_instance_t *)dbdata; + DBT key, data; + + /* check to see if we are authoritative for the zone first. */ +#if DLZ_DLOPEN_VERSION >= 3 + result = dlz_findzonedb(dbdata, name, NULL, NULL); +#else /* if DLZ_DLOPEN_VERSION >= 3 */ + result = dlz_findzonedb(dbdata, name); +#endif /* if DLZ_DLOPEN_VERSION >= 3 */ + if (result != ISC_R_SUCCESS) { + return (ISC_R_NOTFOUND); + } + + memset(&key, 0, sizeof(DBT)); + key.flags = DB_DBT_MALLOC; + key.data = strdup(name); + if (key.data == NULL) { + result = ISC_R_NOMEMORY; + goto xfr_cleanup; + } + key.size = strlen(key.data); + + memset(&data, 0, sizeof(DBT)); + data.flags = DB_DBT_MALLOC; + data.data = strdup(client); + if (data.data == NULL) { + result = ISC_R_NOMEMORY; + goto xfr_cleanup; + } + data.size = strlen(data.data); + + switch (db->client->get(db->client, NULL, &key, &data, DB_GET_BOTH)) { + case DB_NOTFOUND: + result = ISC_R_NOTFOUND; + break; + case 0: + result = ISC_R_SUCCESS; + break; + default: + result = ISC_R_FAILURE; + } + +xfr_cleanup: + /* free any memory duplicate string in the key field */ + if (key.data != NULL) { + free(key.data); + } + + /* free any memory allocated to the data field. */ + if (data.data != NULL) { + free(data.data); + } + + return (result); +} + +/*% + * Perform a zone transfer + * + * BDB does not allow a secondary index on a database that allows + * duplicates. We have a few options: + * + * 1) kill speed by having lookup method use a secondary db which + * is associated to the primary DB with the DNS data. Then have + * another secondary db for zone transfer which also points to + * the dns_data primary. NO - The point of this driver is + * lookup performance. + * + * 2) Blow up database size by storing DNS data twice. Once for + * the lookup (dns_data) database, and a second time for the zone + * transfer (dns_xfr) database. NO - That would probably require + * a larger cache to provide good performance. Also, that would + * make the DB larger on disk potentially slowing it as well. + * + * 3) Loop through the dns_xfr database with a cursor to get + * all the different hosts in a zone. Then use the zone & host + * together to lookup the data in the dns_data database. YES - + * This may slow down zone xfr's a little, but that's ok they + * don't happen as often and don't need to be as fast. We can + * also use this table when deleting a zone (The BDB driver + * is read only - the delete would be used during replication + * updates by a separate process). + */ +isc_result_t +dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes) { + isc_result_t result = ISC_R_NOTFOUND; + bdbhpt_instance_t *db = (bdbhpt_instance_t *)dbdata; + DBC *xfr_cursor = NULL; + DBC *dns_cursor = NULL; + DBT xfr_key, xfr_data, dns_key, dns_data; + int xfr_flags; + int dns_flags; + int bdbhptres; + bdbhpt_parsed_data_t pd; + char *tmp = NULL, *tmp_zone, *tmp_zone_host = NULL; + + memset(&xfr_key, 0, sizeof(DBT)); + memset(&xfr_data, 0, sizeof(DBT)); + memset(&dns_key, 0, sizeof(DBT)); + memset(&dns_data, 0, sizeof(DBT)); + + xfr_key.data = tmp_zone = strdup(zone); + if (xfr_key.data == NULL) { + return (ISC_R_NOMEMORY); + } + + xfr_key.size = strlen(xfr_key.data); + + /* get a cursor to loop through dns_xfr table */ + if (db->xfr->cursor(db->xfr, NULL, &xfr_cursor, 0) != 0) { + result = ISC_R_FAILURE; + goto allnodes_cleanup; + } + + /* get a cursor to loop through dns_data table */ + if (db->data->cursor(db->data, NULL, &dns_cursor, 0) != 0) { + result = ISC_R_FAILURE; + goto allnodes_cleanup; + } + + xfr_flags = DB_SET; + + /* loop through xfr table for specified zone. */ + while ((bdbhptres = xfr_cursor->c_get(xfr_cursor, &xfr_key, &xfr_data, + xfr_flags)) == 0) + { + xfr_flags = DB_NEXT_DUP; + + /* +1 to allow for space between zone and host names */ + dns_key.size = xfr_data.size + xfr_key.size + 1; + + /* +1 to allow for null term at end of string. */ + dns_key.data = tmp_zone_host = malloc(dns_key.size + 1); + if (dns_key.data == NULL) { + goto allnodes_cleanup; + } + + /* + * construct search key for dns_data. + * zone_name(a space)host_name + */ + strcpy(dns_key.data, zone); + strcat(dns_key.data, " "); + strncat(dns_key.data, xfr_data.data, xfr_data.size); + + dns_flags = DB_SET; + + while ((bdbhptres = dns_cursor->c_get(dns_cursor, &dns_key, + &dns_data, dns_flags)) == + 0) + { + dns_flags = DB_NEXT_DUP; + + /* +1 to allow for null term at end of string. */ + tmp = realloc(tmp, dns_data.size + 1); + if (tmp == NULL) { + goto allnodes_cleanup; + } + + /* copy data to tmp string, and append null term. */ + strncpy(tmp, dns_data.data, dns_data.size); + tmp[dns_data.size] = '\0'; + + /* split string into dns data parts. */ + if (bdbhpt_parse_data(db->log, tmp, &pd) != + ISC_R_SUCCESS) + { + goto allnodes_cleanup; + } + result = db->putnamedrr(allnodes, pd.host, pd.type, + pd.ttl, pd.data); + if (result != ISC_R_SUCCESS) { + goto allnodes_cleanup; + } + } /* end inner while loop */ + + /* clean up memory */ + if (tmp_zone_host != NULL) { + free(tmp_zone_host); + tmp_zone_host = NULL; + } + } /* end outer while loop */ + +allnodes_cleanup: + /* free any memory */ + if (tmp != NULL) { + free(tmp); + } + + if (tmp_zone_host != NULL) { + free(tmp_zone_host); + } + + if (tmp_zone != NULL) { + free(tmp_zone); + } + + /* get rid of cursors */ + if (xfr_cursor != NULL) { + xfr_cursor->c_close(xfr_cursor); + } + + if (dns_cursor != NULL) { + dns_cursor->c_close(dns_cursor); + } + + return (result); +} + +/*% + * Performs bdbhpt cleanup. + * Used by bdbhpt_create if there is an error starting up. + * Used by bdbhpt_destroy when the driver is shutting down. + */ +static void +bdbhpt_cleanup(bdbhpt_instance_t *db) { + /* close databases */ + if (db->data != NULL) { + db->data->close(db->data, 0); + } + if (db->xfr != NULL) { + db->xfr->close(db->xfr, 0); + } + if (db->zone != NULL) { + db->zone->close(db->zone, 0); + } + if (db->client != NULL) { + db->client->close(db->client, 0); + } + + /* close environment */ + if (db->dbenv != NULL) { + db->dbenv->close(db->dbenv, 0); + } +} + +/* + * See if we handle a given zone + */ +#if DLZ_DLOPEN_VERSION < 3 +isc_result_t +dlz_findzonedb(void *dbdata, const char *name) +#else /* if DLZ_DLOPEN_VERSION < 3 */ +isc_result_t +dlz_findzonedb(void *dbdata, const char *name, dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo) +#endif /* if DLZ_DLOPEN_VERSION < 3 */ +{ + isc_result_t result; + bdbhpt_instance_t *db = (bdbhpt_instance_t *)dbdata; + DBT key, data; + + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + data.flags = DB_DBT_MALLOC; + +#if DLZ_DLOPEN_VERSION >= 3 + UNUSED(methods); + UNUSED(clientinfo); +#endif /* if DLZ_DLOPEN_VERSION >= 3 */ + + key.data = strdup(name); + + if (key.data == NULL) { + return (ISC_R_NOMEMORY); + } + + /* + * reverse string to take advantage of BDB locality of reference + * if we need further lookups because the zone doesn't match the + * first time. + */ + key.data = bdbhpt_strrev(key.data); + key.size = strlen(key.data); + + switch (db->zone->get(db->zone, NULL, &key, &data, 0)) { + case DB_NOTFOUND: + result = ISC_R_NOTFOUND; + break; + case 0: + result = ISC_R_SUCCESS; + break; + default: + result = ISC_R_FAILURE; + } + + /* free any memory duplicate string in the key field */ + if (key.data != NULL) { + free(key.data); + } + + /* free any memory allocated to the data field. */ + if (data.data != NULL) { + free(data.data); + } + + return (result); +} + +/* + * Look up one record in the database. + * + */ +#if DLZ_DLOPEN_VERSION == 1 +isc_result_t +dlz_lookup(const char *zone, const char *name, void *dbdata, + dns_sdlzlookup_t *lookup) +#else /* if DLZ_DLOPEN_VERSION == 1 */ +isc_result_t +dlz_lookup(const char *zone, const char *name, void *dbdata, + dns_sdlzlookup_t *lookup, dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo) +#endif /* if DLZ_DLOPEN_VERSION == 1 */ +{ + isc_result_t result = ISC_R_NOTFOUND; + bdbhpt_instance_t *db = (bdbhpt_instance_t *)dbdata; + DBC *data_cursor = NULL; + DBT key, data; + int bdbhptres; + int flags; + + bdbhpt_parsed_data_t pd; + char *tmp = NULL; + char *keyStr = NULL; + +#if DLZ_DLOPEN_VERSION >= 2 + UNUSED(methods); + UNUSED(clientinfo); +#endif /* if DLZ_DLOPEN_VERSION >= 2 */ + + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + + key.size = strlen(zone) + strlen(name) + 1; + + /* allocate mem for key */ + key.data = keyStr = malloc((key.size + 1) * sizeof(char)); + + if (keyStr == NULL) { + return (ISC_R_NOMEMORY); + } + + strcpy(keyStr, zone); + strcat(keyStr, " "); + strcat(keyStr, name); + + /* get a cursor to loop through data */ + if (db->data->cursor(db->data, NULL, &data_cursor, 0) != 0) { + result = ISC_R_FAILURE; + goto lookup_cleanup; + } + + result = ISC_R_NOTFOUND; + + flags = DB_SET; + while ((bdbhptres = data_cursor->c_get(data_cursor, &key, &data, + flags)) == 0) + { + flags = DB_NEXT_DUP; + tmp = realloc(tmp, data.size + 1); + if (tmp == NULL) { + goto lookup_cleanup; + } + + strncpy(tmp, data.data, data.size); + tmp[data.size] = '\0'; + + if (bdbhpt_parse_data(db->log, tmp, &pd) != ISC_R_SUCCESS) { + goto lookup_cleanup; + } + + result = db->putrr(lookup, pd.type, pd.ttl, pd.data); + if (result != ISC_R_SUCCESS) { + goto lookup_cleanup; + } + } /* end while loop */ + +lookup_cleanup: + /* get rid of cursor */ + if (data_cursor != NULL) { + data_cursor->c_close(data_cursor); + } + + free(keyStr); + if (tmp != NULL) { + free(tmp); + } + + return (result); +} + +/*% + * Initialises, sets flags and then opens Berkeley databases. + */ +static isc_result_t +bdbhpt_opendb(log_t *log, DB_ENV *db_env, DBTYPE db_type, DB **db, + const char *db_name, char *db_file, int flags) { + int result; + + /* Initialise the database. */ + if ((result = db_create(db, db_env, 0)) != 0) { + log(ISC_LOG_ERROR, + "bdbhpt_dynamic: could not initialize %s database. " + "BerkeleyDB error: %s", + db_name, db_strerror(result)); + return (ISC_R_FAILURE); + } + + /* set database flags. */ + if ((result = (*db)->set_flags(*db, flags)) != 0) { + log(ISC_LOG_ERROR, + "bdbhpt_dynamic: could not set flags for %s database. " + "BerkeleyDB error: %s", + db_name, db_strerror(result)); + return (ISC_R_FAILURE); + } + + /* open the database. */ + if ((result = (*db)->open(*db, NULL, db_file, db_name, db_type, + DB_RDONLY | bdbhpt_threads, 0)) != 0) + { + log(ISC_LOG_ERROR, + "bdbhpt_dynamic: could not open %s database in %s. " + "BerkeleyDB error: %s", + db_name, db_file, db_strerror(result)); + return (ISC_R_FAILURE); + } + + return (ISC_R_SUCCESS); +} + +/* + * Called to initialize the driver + */ +isc_result_t +dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata, + ...) { + isc_result_t result; + int bdbhptres; + int bdbFlags = 0; + bdbhpt_instance_t *db = NULL; + + const char *helper_name; + va_list ap; + + UNUSED(dlzname); + + /* Allocate memory for our db structures and helper functions */ + db = calloc(1, sizeof(struct bdbhpt_instance)); + if (db == NULL) { + return (ISC_R_NOMEMORY); + } + + /* Fill in the helper functions */ + va_start(ap, dbdata); + while ((helper_name = va_arg(ap, const char *)) != NULL) { + b9_add_helper(db, helper_name, va_arg(ap, void *)); + } + va_end(ap); + + /* verify we have 4 arg's passed to the driver */ + if (argc != 4) { + db->log(ISC_LOG_ERROR, + "bdbhpt_dynamic: please supply 3 command line args. " + "You supplied: %s", + argc); + return (ISC_R_FAILURE); + } + + switch ((char)*argv[1]) { + /* + * Transactional mode. Highest safety - lowest speed. + */ + case 'T': + case 't': + bdbFlags = DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_LOG | + DB_INIT_TXN; + db->log(ISC_LOG_INFO, "bdbhpt_dynamic: using transactional " + "mode."); + break; + + /* + * Concurrent mode. Lower safety (no rollback) - + * higher speed. + */ + case 'C': + case 'c': + bdbFlags = DB_INIT_CDB | DB_INIT_MPOOL; + db->log(ISC_LOG_INFO, "bdbhpt_dynamic: using concurrent mode."); + break; + + /* + * Private mode. No inter-process communication & no locking. + * Lowest safety - highest speed. + */ + case 'P': + case 'p': + bdbFlags = DB_PRIVATE | DB_INIT_MPOOL; + db->log(ISC_LOG_INFO, "bdbhpt_dynamic: using private mode."); + break; + default: + db->log(ISC_LOG_ERROR, + "bdbhpt_dynamic: " + "operating mode must be set to P or C or T. " + "You specified '%s'", + argv[1]); + return (ISC_R_FAILURE); + } + + /* + * create bdbhpt environment + * Basically bdbhpt allocates and assigns memory to db->dbenv + */ + bdbhptres = db_env_create(&db->dbenv, 0); + if (bdbhptres != 0) { + db->log(ISC_LOG_ERROR, + "bdbhpt_dynamic: db environment could not be created. " + "BerkeleyDB error: %s", + db_strerror(bdbhptres)); + result = ISC_R_FAILURE; + goto init_cleanup; + } + + /* open bdbhpt environment */ + bdbhptres = db->dbenv->open(db->dbenv, argv[2], + bdbFlags | bdbhpt_threads | DB_CREATE, 0); + if (bdbhptres != 0) { + db->log(ISC_LOG_ERROR, + "bdbhpt_dynamic: " + "db environment at '%s' could not be opened. " + "BerkeleyDB error: %s", + argv[2], db_strerror(bdbhptres)); + result = ISC_R_FAILURE; + goto init_cleanup; + } + + /* open dlz_data database. */ + result = bdbhpt_opendb(db->log, db->dbenv, DB_UNKNOWN, &db->data, + dlz_data, argv[3], DB_DUP | DB_DUPSORT); + if (result != ISC_R_SUCCESS) { + goto init_cleanup; + } + + /* open dlz_xfr database. */ + result = bdbhpt_opendb(db->log, db->dbenv, DB_UNKNOWN, &db->xfr, + dlz_xfr, argv[3], DB_DUP | DB_DUPSORT); + if (result != ISC_R_SUCCESS) { + goto init_cleanup; + } + + /* open dlz_zone database. */ + result = bdbhpt_opendb(db->log, db->dbenv, DB_UNKNOWN, &db->zone, + dlz_zone, argv[3], 0); + if (result != ISC_R_SUCCESS) { + goto init_cleanup; + } + + /* open dlz_client database. */ + result = bdbhpt_opendb(db->log, db->dbenv, DB_UNKNOWN, &db->client, + dlz_client, argv[3], DB_DUP | DB_DUPSORT); + if (result != ISC_R_SUCCESS) { + goto init_cleanup; + } + + *dbdata = db; + + db->log(ISC_LOG_INFO, "bdbhpt_dynamic: version %s, started", + dlz_bdbhpt_dynamic_version); + return (ISC_R_SUCCESS); + +init_cleanup: + bdbhpt_cleanup(db); + return (result); +} + +/* + * Shut down the backend + */ +void +dlz_destroy(void *dbdata) { + struct bdbhpt_instance *db = (struct bdbhpt_instance *)dbdata; + + db->log(ISC_LOG_INFO, "dlz_bdbhpt_dynamic (%s): shutting down", + dlz_bdbhpt_dynamic_version); + bdbhpt_cleanup((bdbhpt_instance_t *)dbdata); + free(db); +} + +/* + * Return the version of the API + */ +int +dlz_version(unsigned int *flags) { + UNUSED(flags); + return (DLZ_DLOPEN_VERSION); +} + +/* + * Register a helper function from the bind9 dlz_dlopen driver + */ +static void +b9_add_helper(struct bdbhpt_instance *db, const char *helper_name, void *ptr) { + if (strcmp(helper_name, "log") == 0) { + db->log = (log_t *)ptr; + } + if (strcmp(helper_name, "putrr") == 0) { + db->putrr = (dns_sdlz_putrr_t *)ptr; + } + if (strcmp(helper_name, "putnamedrr") == 0) { + db->putnamedrr = (dns_sdlz_putnamedrr_t *)ptr; + } + if (strcmp(helper_name, "writeable_zone") == 0) { + db->writeable_zone = (dns_dlz_writeablezone_t *)ptr; + } +} |