/*
* Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
*
* 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 STICHTING NLNET
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* STICHTING NLNET 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.
*
* 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 ROB BUTLER
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* ROB BUTLER 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.
*/
/*
* Copyright (C) 1999-2001, 2016 Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/.
*/
#ifdef DLZ_BDB
#include <config.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dlz/dlz_bdbhpt_driver.h>
#include <db.h>
/* should the bdb driver use threads. */
#ifdef ISC_PLATFORM_USETHREADS
#else
#define bdbhpt_threads 0
#endif
/* bdbhpt database names */
/* This structure contains all the Berkeley DB handles
* for this instance of the bdbhpt driver.
*/
typedef struct bdbhpt_instance {
typedef struct bdbhpt_parsed_data {
char *host;
char *type;
int ttl;
char *data;
/* forward reference */
static isc_result_t
/*%
* Reverses a string in place.
*/
{
return str;
{
}
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
/*%
* String should be formated 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 */
/* verify we found a space */
return ISC_R_FAILURE;
/* make sure it is safe to increment pointer */
return ISC_R_FAILURE;
/* save pointer to host */
/* find space after host and change it to a '\0' */
/* verify we found a space */
return ISC_R_FAILURE;
/* change the space to a null (string terminator) */
tmp[0] = '\0';
/* make sure it is safe to increment pointer */
return ISC_R_FAILURE;
/* save pointer to ttl string */
/* find space after ttl and change it to a '\0' */
/* verify we found a space */
return ISC_R_FAILURE;
/* change the space to a null (string terminator) */
tmp[0] = '\0';
/* make sure it is safe to increment pointer */
return ISC_R_FAILURE;
/* save pointer to dns type */
/* find space after type and change it to a '\0' */
/* verify we found a space */
return ISC_R_FAILURE;
/* change the space to a null (string terminator) */
tmp[0] = '\0';
/* make sure it is safe to increment pointer */
return ISC_R_FAILURE;
/* save pointer to remainder of DNS data */
/* convert ttl string to integer */
"bdbhpt driver ttl must be a postive number");
return ISC_R_FAILURE;
}
/* if we get this far everything should have worked. */
return ISC_R_SUCCESS;
}
/*
* DLZ methods
*/
static isc_result_t
const char *client)
{
/* check to see if we are authoritative for the zone first. */
if (result != ISC_R_SUCCESS)
return (ISC_R_NOTFOUND);
goto xfr_cleanup;
}
goto xfr_cleanup;
}
case DB_NOTFOUND:
break;
case 0:
break;
default:
}
/* free any memory duplicate string in the key field */
/* free any memory allocated to the data field. */
return result;
}
/*%
* 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).
*/
static isc_result_t
{
int xfr_flags;
int dns_flags;
int bdbhptres;
return (ISC_R_NOMEMORY);
/* get a cursor to loop through dns_xfr table */
goto allnodes_cleanup;
}
/* get a cursor to loop through dns_data table */
goto allnodes_cleanup;
}
/* loop through xfr table for specified zone. */
xfr_flags)) == 0) {
/* +1 to allow for space between zone and host names */
/* +1 to allow for null term at end of string. */
goto allnodes_cleanup;
/*
* construct search key for dns_data.
* zone_name(a space)host_name
*/
&dns_data,
dns_flags)) == 0) {
/* +1 to allow for null term at end of string. */
goto allnodes_cleanup;
/* copy data to tmp string, and append null term. */
/* split string into dns data parts. */
goto allnodes_cleanup;
if (result != ISC_R_SUCCESS)
goto allnodes_cleanup;
} /* end inner while loop */
/* clean up memory */
if (tmp_zone_host != NULL) {
}
} /* end outer while loop */
/* free any memory */
if (tmp_zone_host != NULL)
/* get rid of cursors */
if (xfr_cursor != NULL)
if (dns_cursor != NULL)
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
/* close databases */
/* close environment */
/* cleanup memory */
/* save mctx for later */
/* return, and detach the memory */
}
}
static isc_result_t
{
return (ISC_R_NOMEMORY);
/*
* reverse string to take advantage of BDB locality of reference
* if we need futher lookups because the zone doesn't match the
* first time.
*/
case DB_NOTFOUND:
break;
case 0:
break;
default:
}
/* free any memory duplicate string in the key field */
/* free any memory allocated to the data field. */
return result;
}
static isc_result_t
{
int bdbhptres;
int flags;
/* allocate mem for key */
return ISC_R_NOMEMORY;
/* get a cursor to loop through data */
goto lookup_cleanup;
}
flags)) == 0) {
flags = DB_NEXT_DUP;
goto lookup_cleanup;
goto lookup_cleanup;
if (result != ISC_R_SUCCESS)
goto lookup_cleanup;
} /* end while loop */
/* get rid of cursor */
if (data_cursor != NULL)
return result;
}
/*% Initializes, sets flags and then opens Berkeley databases. */
static isc_result_t
int result;
/* Initialize the database. */
"bdbhpt could not initialize %s database. "
"bdbhpt error: %s",
return ISC_R_FAILURE;
}
/* set database flags. */
"bdbhpt could not set flags for %s database. "
"bdbhpt error: %s",
return ISC_R_FAILURE;
}
/* open the database. */
DB_RDONLY | bdbhpt_threads, 0)) != 0) {
"bdbhpt could not open %s database in %s. "
"bdbhpt error: %s",
return ISC_R_FAILURE;
}
return ISC_R_SUCCESS;
}
static isc_result_t
{
int bdbhptres;
int bdbFlags = 0;
/* verify we have 4 arg's passed to the driver */
if (argc != 4) {
"bdbhpt driver requires at least "
"3 command line args.");
return (ISC_R_FAILURE);
}
switch((char) *argv[1]) {
/*
* Transactional mode. Highest safety - lowest speed.
*/
case 'T':
case 't':
"bdbhpt driver using transactional mode.");
break;
/*
* Concurrent mode. Lower safety (no rollback) -
* higher speed.
*/
case 'C':
case 'c':
"bdbhpt driver using concurrent mode.");
break;
/*
* Private mode. No inter-process communication & no locking.
* Lowest saftey - highest speed.
*/
case 'P':
case 'p':
"bdbhpt driver using private mode.");
break;
default:
"bdbhpt driver requires the operating mode "
"be set to P or C or T. You specified '%s'",
argv[1]);
return (ISC_R_FAILURE);
}
/* allocate and zero memory for driver structure */
"Could not allocate memory for "
"database instance object.");
return (ISC_R_NOMEMORY);
}
/* attach to the memory context */
/*
* create bdbhpt environment
* Basically bdbhpt allocates and assigns memory to db->dbenv
*/
if (bdbhptres != 0) {
"bdbhpt environment could not be created. "
"bdbhpt error: %s",
goto init_cleanup;
}
/* open bdbhpt environment */
if (bdbhptres != 0) {
"bdbhpt environment at '%s' could not be opened."
" bdbhpt error: %s",
goto init_cleanup;
}
/* open dlz_data database. */
if (result != ISC_R_SUCCESS)
goto init_cleanup;
/* open dlz_xfr database. */
if (result != ISC_R_SUCCESS)
goto init_cleanup;
/* open dlz_zone database. */
if (result != ISC_R_SUCCESS)
goto init_cleanup;
/* open dlz_client database. */
if (result != ISC_R_SUCCESS)
goto init_cleanup;
return(ISC_R_SUCCESS);
return result;
}
static void
{
}
/*
* bdbhpt_authority not needed as authority data is returned by lookup
*/
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
/*%
* Wrapper around dns_sdlzregister().
*/
dlz_bdbhpt_init(void) {
/*
* Write debugging message to log
*/
"Registering DLZ bdbhpt driver.");
ns_g_mctx, &dlz_bdbhpt);
if (result != ISC_R_SUCCESS) {
"dns_sdlzregister() failed: %s",
}
return result;
}
/*%
* Wrapper around dns_sdlzunregister().
*/
void
dlz_bdbhpt_clear(void) {
/*
* Write debugging message to log
*/
"Unregistering DLZ bdbhpt driver.");
if (dlz_bdbhpt != NULL)
}
#endif