sdlz.c revision ab381c1e22e0ed732170428937d20d13146d863a
/*
* Portions Copyright (C) 2005-2009 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-2001 Internet Software Consortium.
*
* 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 ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC 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) 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.
*/
/* $Id: sdlz.c,v 1.20 2009/04/21 23:48:04 tbox Exp $ */
/*! \file */
#include <config.h>
#include <string.h>
#include <dns/callbacks.h>
#include <dns/dbiterator.h>
#include <dns/fixedname.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
#include <dns/rdatasetiter.h>
#include <dns/rdatatype.h>
#include "rdatalist_p.h"
/*
* Private Types
*/
struct dns_sdlzimplementation {
const dns_sdlzmethods_t *methods;
void *driverarg;
unsigned int flags;
};
struct dns_sdlz_db {
/* Unlocked */
void *dbdata;
/* Locked */
unsigned int references;
};
struct dns_sdlzlookup {
/* Unlocked */
unsigned int magic;
/* Locked */
unsigned int references;
};
typedef struct dns_sdlzlookup dns_sdlznode_t;
struct dns_sdlzallnodes {
};
typedef dns_sdlzallnodes_t sdlz_dbiterator_t;
typedef struct sdlz_rdatasetiter {
/*
* Note that "impmagic" is not the first four bytes of the struct, so
* ISC_MAGIC_VALID cannot be used.
*/
/* These values are taken from RFC 1537 */
/* This is a reasonable value */
static int dummy;
#ifdef __COVERITY__
#else
#define MAYBE_LOCK(imp) \
do { \
if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
} while (0)
#define MAYBE_UNLOCK(imp) \
do { \
if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
} while (0)
#endif
/*
* Forward references. Try to keep these to a minimum.
*/
dns_name_t *name);
dns_name_t *name);
dns_name_t *name);
static dns_dbiteratormethods_t dbiterator_methods = {
};
/*
* Utility functions
*/
/*% Converts the input string to lowercase, in place. */
static void
dns_sdlz_tolower(char *str) {
unsigned int i;
for (i = 0; i < len; i++) {
str[i] += 32;
}
}
static inline unsigned int
initial_size(const char *data) {
}
/*
* Rdataset Iterator Methods. These methods were "borrowed" from the SDB
* driver interface. See the SDB driver interface documentation for more info.
*/
static void
(sdlz_rdatasetiter_t *)(*iteratorp);
sizeof(sdlz_rdatasetiter_t));
}
static isc_result_t
return (ISC_R_NOMORE);
return (ISC_R_SUCCESS);
}
static isc_result_t
return (ISC_R_NOMORE);
else
return (ISC_R_SUCCESS);
}
static void
rdataset);
}
static dns_rdatasetitermethods_t rdatasetiter_methods = {
};
/*
* DB routines. These methods were "borrowed" from the SDB driver interface.
* See the SDB driver interface documentation for more info.
*/
static void
sdlz->references++;
}
static void
}
static void
sdlz->references--;
if (sdlz->references == 0)
if (need_destroy)
}
static isc_result_t
return (ISC_R_NOTIMPLEMENTED);
}
static isc_result_t
return (ISC_R_NOTIMPLEMENTED);
}
static isc_result_t
{
return (ISC_R_NOTIMPLEMENTED);
}
static void
return;
}
static isc_result_t
return (ISC_R_NOTIMPLEMENTED);
}
static void
{
}
static void
}
static isc_result_t
return (ISC_R_NOMEMORY);
if (result != ISC_R_SUCCESS) {
"isc_mutex_init() failed: %s",
return (ISC_R_UNEXPECTED);
}
return (ISC_R_SUCCESS);
}
static void
isc_buffer_t *b;
}
}
isc_buffer_free(&b);
}
}
}
static isc_result_t
{
isc_buffer_t b;
unsigned int labels;
if (result != ISC_R_SUCCESS)
return (result);
} else {
if (result != ISC_R_SUCCESS)
return (result);
}
isc_buffer_putuint8(&b, 0);
if (result != ISC_R_SUCCESS)
return (result);
isc_buffer_putuint8(&b2, 0);
if (result != ISC_R_SUCCESS)
return (result);
/* make sure strings are always lowercase */
/* try to lookup the host (namestr) */
/*
* if the host (namestr) was not found, try to lookup a
* "wildcard" host.
*/
if (result != ISC_R_SUCCESS) {
}
return (result);
}
if (result != ISC_R_SUCCESS &&
result != ISC_R_NOTIMPLEMENTED) {
return (result);
}
}
return (ISC_R_SUCCESS);
}
static isc_result_t
{
return (ISC_R_NOTIMPLEMENTED);
}
static void
node->references++;
}
static void
node->references--;
if (node->references == 0)
if (need_destroy)
}
static isc_result_t
INSIST(0);
return (ISC_R_UNEXPECTED);
}
static void
return;
}
static isc_result_t
{
isc_buffer_t b;
return (ISC_R_NOTIMPLEMENTED);
if ((options & DNS_DB_NSEC3ONLY) != 0 ||
(options & DNS_DB_NONSEC3) != 0)
return (ISC_R_NOTIMPLEMENTED);
if (result != ISC_R_SUCCESS)
return (result);
isc_buffer_putuint8(&b, 0);
return (ISC_R_NOMEMORY);
/* make sure strings are always lowercase */
if (result != ISC_R_SUCCESS) {
return (result);
}
}
return (ISC_R_SUCCESS);
}
static isc_result_t
{
return (ISC_R_NOTIMPLEMENTED);
break;
}
return (ISC_R_NOTFOUND);
return (ISC_R_SUCCESS);
}
static isc_result_t
{
unsigned int i;
return (DNS_R_NXDOMAIN);
}
/*
* Unless this is an explicit lookup at the origin, don't
* look at the origin.
*/
continue;
/*
* Look up the next label.
*/
if (result != ISC_R_SUCCESS) {
continue;
}
/*
* Look for a DNAME at the current label, unless this is
* the qname.
*/
if (i < nlabels) {
if (result == ISC_R_SUCCESS) {
break;
}
}
/*
* Look for an NS at the current label, unless this is the
* origin or glue is ok.
*/
if (result == ISC_R_SUCCESS) {
{
if (sigrdataset != NULL &&
(sigrdataset)) {
(sigrdataset);
}
} else
break;
}
}
/*
* If the current name is not the qname, add another label
* and try again.
*/
if (i < nlabels) {
continue;
}
/*
* If we're looking for ANY, we're done.
*/
if (type == dns_rdatatype_any) {
break;
}
/*
* Look for the qtype.
*/
if (result == ISC_R_SUCCESS)
break;
/*
* Look for a CNAME
*/
if (type != dns_rdatatype_cname) {
if (result == ISC_R_SUCCESS) {
break;
}
}
break;
}
if (xresult != ISC_R_SUCCESS) {
return (DNS_R_BADDB);
}
}
return (result);
}
static isc_result_t
{
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
}
static isc_result_t
{
return (ISC_R_NOTIMPLEMENTED);
}
static isc_result_t
{
return (ISC_R_NOTIMPLEMENTED);
}
static isc_result_t
{
return (ISC_R_NOTIMPLEMENTED);
}
static isc_boolean_t
return (ISC_FALSE);
}
static unsigned int
return (0);
}
static isc_boolean_t
return (ISC_TRUE);
}
static void
}
static void
}
static dns_dbmethods_t sdlzdb_methods = {
dump,
find,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
/*
* Database Iterator Methods. These methods were "borrowed" from the SDB
* driver interface. See the SDB driver interface documentation for more info.
*/
static void
}
}
static isc_result_t
return (ISC_R_NOMORE);
else
return (ISC_R_SUCCESS);
}
static isc_result_t
return (ISC_R_NOMORE);
else
return (ISC_R_SUCCESS);
}
static isc_result_t
return (ISC_R_SUCCESS);
return (ISC_R_NOTFOUND);
}
static isc_result_t
return (ISC_R_NOMORE);
else
return (ISC_R_SUCCESS);
}
static isc_result_t
return (ISC_R_NOMORE);
else
return (ISC_R_SUCCESS);
}
static isc_result_t
{
return (ISC_R_SUCCESS);
}
static isc_result_t
return (ISC_R_SUCCESS);
}
static isc_result_t
}
/*
* Rdataset Methods. These methods were "borrowed" from the SDB driver
* interface. See the SDB driver interface documentation for more info.
*/
static void
}
static void
}
static dns_rdatasetmethods_t rdataset_methods = {
NULL,
NULL,
NULL,
NULL,
};
static void
{
/*
* The sdlz rdataset is an rdatalist with some additions.
* - private1 & private2 are used by the rdatalist.
* - private3 & private 4 are unused.
* - private5 is the node.
*/
/* This should never fail. */
}
/*
* SDLZ core methods. This is the core of the new DLZ functionality.
*/
/*%
* Build a 'bind' database driver structure to be returned by
* either the find zone or the allow zone transfer method.
* This method is only available in this source file, it is
* not made available anywhere else.
*/
static isc_result_t
{
/* check that things are as we expect */
/* allocate and zero memory for driver structure */
return (ISC_R_NOMEMORY);
/* initialize and set origin */
if (result != ISC_R_SUCCESS)
goto mem_cleanup;
/* initialize the reference count mutex */
if (result != ISC_R_SUCCESS)
goto name_cleanup;
/* set the rest of the database structure attributes */
/* attach to the memory context */
/* mark structure as valid */
return (result);
/*
* reference count mutex could not be initialized, clean up
* name memory
*/
return (result);
}
static isc_result_t
{
isc_buffer_t b;
char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")
+ 1];
/*
* Perform checks to make sure data is as we expect it to be.
*/
/* Convert DNS name to ascii text */
if (result != ISC_R_SUCCESS)
return (result);
isc_buffer_putuint8(&b, 0);
/* convert client address to ascii text */
if (result != ISC_R_SUCCESS)
return (result);
isc_buffer_putuint8(&b2, 0);
/* make sure strings are always lowercase */
/* Call SDLZ driver's find zone method */
/*
* if zone is supported and transfers allowed build a 'bind'
* database driver
*/
if (result == ISC_R_SUCCESS)
return (result);
}
return (ISC_R_NOTIMPLEMENTED);
}
static isc_result_t
{
/* Write debugging message to log */
"Loading SDLZ driver.");
/*
* Performs checks to make sure data is as we expect it to be.
*/
/* If the create method exists, call it. */
}
/* Write debugging message to log */
if (result == ISC_R_SUCCESS) {
"SDLZ driver loaded successfully.");
} else {
"SDLZ driver failed to load.");
}
return (result);
}
static void
{
/* Write debugging message to log */
"Unloading SDLZ driver.");
imp = driverdata;
/* If the destroy method exists, call it. */
}
}
static isc_result_t
{
isc_buffer_t b;
/*
* Perform checks to make sure data is as we expect it to be.
*/
/* Convert DNS name to ascii text */
if (result != ISC_R_SUCCESS)
return (result);
isc_buffer_putuint8(&b, 0);
/* make sure strings are always lowercase */
/* Call SDLZ driver's find zone method */
/*
* if zone is supported build a 'bind' database driver
* structure to return
*/
if (result == ISC_R_SUCCESS)
return (result);
}
static dns_dlzmethods_t sdlzmethods = {
};
/*
* Public functions.
*/
const char *data)
{
isc_buffer_t b;
unsigned int size;
if (result != ISC_R_SUCCESS)
return (result);
break;
}
return (ISC_R_NOMEMORY);
} else
return (DNS_R_BADTTL);
return (ISC_R_NOMEMORY);
else
if (result != ISC_R_SUCCESS)
goto failure;
do {
if (result != ISC_R_SUCCESS)
goto failure;
if (result != ISC_R_SUCCESS)
goto failure;
if (result != ISC_R_SUCCESS)
size *= 2;
} while (result == ISC_R_NOSPACE);
if (result != ISC_R_SUCCESS)
goto failure;
return (ISC_R_SUCCESS);
return (result);
}
{
isc_buffer_t b;
else
if (result != ISC_R_SUCCESS)
return (result);
/* All names are relative to the root */
}
if (result != ISC_R_SUCCESS)
return (result);
return (ISC_R_NOMEMORY);
}
if (result != ISC_R_SUCCESS) {
return (result);
}
}
}
{
int n;
if (n >= (int)sizeof(str) || n < 0)
return (ISC_R_NOSPACE);
}
{
/*
* Performs checks to make sure data is as we expect it to be.
*/
DNS_SDLZFLAG_THREADSAFE)) == 0);
/* Write debugging message to log */
"Registering SDLZ driver '%s'", drivername);
/*
* Allocate memory for a sdlz_implementation object. Error if
* we cannot.
*/
return (ISC_R_NOMEMORY);
/* Make sure memory region is set to all 0's */
/* Store the data passed into this method */
/* attach the new sdlz_implementation object to a memory context */
/*
* initialize the driver lock, error if we cannot
* (used if a driver does not support multiple threads)
*/
if (result != ISC_R_SUCCESS) {
"isc_mutex_init() failed: %s",
goto cleanup_mctx;
}
/*
* register the DLZ driver. Pass in our "extra" sdlz information as
* a driverarg. (that's why we stored the passed in driver arg in our
* sdlz_implementation structure) Also, store the dlz_implementation
* structure in our sdlz_implementation.
*/
/* if registration fails, cleanup and get outta here. */
if (result != ISC_R_SUCCESS)
goto cleanup_mutex;
return (ISC_R_SUCCESS);
/* destroy the driver lock, we don't need it anymore */
/*
* return the memory back to the available memory pool and
* remove it from the memory context.
*/
return (result);
}
void
/* Write debugging message to log */
"Unregistering SDLZ driver.");
/*
* Performs checks to make sure data is as we expect it to be.
*/
/* Unregister the DLZ driver implementation */
/* destroy the driver lock, we don't need it anymore */
/*
* return the memory back to the available memory pool and
* remove it from the memory context.
*/
}