From ba8f85b49c38af7bc2a9acdef5dcde2de008d25e Mon Sep 17 00:00:00 2001
From: peter <peter@FreeBSD.org>
Date: Sat, 12 Jul 2008 05:00:28 +0000
Subject: Flatten bind9 vendor work area

---
 lib/dns/dlz.c | 510 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 510 insertions(+)
 create mode 100644 lib/dns/dlz.c

(limited to 'lib/dns/dlz.c')

diff --git a/lib/dns/dlz.c b/lib/dns/dlz.c
new file mode 100644
index 0000000..ee6c03b
--- /dev/null
+++ b/lib/dns/dlz.c
@@ -0,0 +1,510 @@
+/*
+ * Portions Copyright (C) 2005  Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 1999-2001  Internet Software Consortium.
+ *
+ * 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 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: dlz.c,v 1.2.2.2 2005/09/06 03:47:17 marka Exp $ */
+
+/*! \file */
+
+/***
+ *** Imports
+ ***/
+
+#include <config.h>
+
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/master.h>
+#include <dns/dlz.h>
+
+
+#include <isc/buffer.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/rwlock.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+/***
+ *** Supported DLZ DB Implementations Registry
+ ***/
+
+static ISC_LIST(dns_dlzimplementation_t) dlz_implementations;
+static isc_rwlock_t dlz_implock;
+static isc_once_t once = ISC_ONCE_INIT;
+
+static void
+dlz_initialize(void) {
+	RUNTIME_CHECK(isc_rwlock_init(&dlz_implock, 0, 0) == ISC_R_SUCCESS);
+	ISC_LIST_INIT(dlz_implementations);
+}
+
+/*%
+ * Searches the dlz_implementations list for a driver matching name.
+ */
+static inline dns_dlzimplementation_t *
+dlz_impfind(const char *name) {
+	dns_dlzimplementation_t *imp;
+
+	for (imp = ISC_LIST_HEAD(dlz_implementations);
+	     imp != NULL;
+	     imp = ISC_LIST_NEXT(imp, link))
+		if (strcasecmp(name, imp->name) == 0)
+			return (imp);
+	return (NULL);
+}
+
+/***
+ *** Basic DLZ Methods
+ ***/
+
+isc_result_t
+dns_dlzallowzonexfr(dns_view_t *view, dns_name_t *name,
+		    isc_sockaddr_t *clientaddr, dns_db_t **dbp)
+{
+	isc_result_t result;
+	dns_dlzallowzonexfr_t allowzonexfr;
+	dns_dlzdb_t *dlzdatabase;
+
+	/*
+	 * Performs checks to make sure data is as we expect it to be.
+	 */
+	REQUIRE(DNS_DLZ_VALID(view->dlzdatabase));
+	REQUIRE(name != NULL);
+	REQUIRE(dbp != NULL && *dbp == NULL);
+
+	/* ask driver if the zone is supported */
+	dlzdatabase = view->dlzdatabase;
+	allowzonexfr = dlzdatabase->implementation->methods->allowzonexfr;
+	result = (*allowzonexfr)(dlzdatabase->implementation->driverarg,
+			         dlzdatabase->dbdata, dlzdatabase->mctx,
+				 view->rdclass, name, clientaddr, dbp);
+
+	if (result == ISC_R_NOTIMPLEMENTED)
+		return (ISC_R_NOTFOUND);
+	return (result);
+}
+
+isc_result_t
+dns_dlzcreate(isc_mem_t *mctx, const char *dlzname, const char *drivername,
+	      unsigned int argc, char *argv[], dns_dlzdb_t **dbp)
+{
+	dns_dlzimplementation_t *impinfo;
+	isc_result_t result;
+
+	/*
+	 * initialize the dlz_implementations list, this is guaranteed
+	 * to only really happen once.
+	 */
+	RUNTIME_CHECK(isc_once_do(&once, dlz_initialize) == ISC_R_SUCCESS);
+
+	/*
+	 * Performs checks to make sure data is as we expect it to be.
+	 */
+	REQUIRE(dbp != NULL && *dbp == NULL);
+	REQUIRE(dlzname != NULL);
+	REQUIRE(drivername != NULL);
+	REQUIRE(mctx != NULL);
+
+	/* write log message */
+	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+		      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
+		      "Loading '%s' using driver %s", dlzname, drivername);
+
+	/* lock the dlz_implementations list so we can search it. */
+	RWLOCK(&dlz_implock, isc_rwlocktype_read);
+
+	/* search for the driver implementation	 */
+	impinfo = dlz_impfind(drivername);
+	if (impinfo == NULL) {
+		RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
+
+		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+			      "unsupported DLZ database driver '%s'."
+			      "  %s not loaded.",
+			      drivername, dlzname);
+
+		return (ISC_R_NOTFOUND);
+	}
+
+	/* Allocate memory to hold the DLZ database driver */
+	(*dbp) = isc_mem_get(mctx, sizeof(dns_dlzdb_t));
+	if ((*dbp) == NULL) {
+		RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
+		return (ISC_R_NOMEMORY);
+	}
+
+	/* Make sure memory region is set to all 0's */
+	memset((*dbp), 0, sizeof(dns_dlzdb_t));
+
+	(*dbp)->implementation = impinfo;
+
+	/* Create a new database using implementation 'drivername'. */
+	result = ((impinfo->methods->create)(mctx, dlzname, argc, argv,
+					     impinfo->driverarg,
+					     &(*dbp)->dbdata));
+
+	/* mark the DLZ driver as valid */
+	if (result == ISC_R_SUCCESS) {
+		RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
+		(*dbp)->magic = DNS_DLZ_MAGIC;
+		isc_mem_attach(mctx, &(*dbp)->mctx);
+		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+			      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+			      "DLZ driver loaded successfully.");
+		return (ISC_R_SUCCESS);
+	} else {
+		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+			      "DLZ driver failed to load.");
+	}
+
+	/* impinfo->methods->create failed. */
+	RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
+	isc_mem_put(mctx, (*dbp), sizeof(dns_dlzdb_t));
+	return (result);
+}
+
+void
+dns_dlzdestroy(dns_dlzdb_t **dbp) {
+	isc_mem_t *mctx;
+	dns_dlzdestroy_t destroy;
+
+	/* Write debugging message to log */
+	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+		      "Unloading DLZ driver.");
+
+	/*
+	 * Perform checks to make sure data is as we expect it to be.
+	 */
+	REQUIRE(dbp != NULL && DNS_DLZ_VALID(*dbp));
+
+	/* call the drivers destroy method */
+	if ((*dbp) != NULL) {
+		mctx = (*dbp)->mctx;
+		destroy = (*dbp)->implementation->methods->destroy;
+		(*destroy)((*dbp)->implementation->driverarg,(*dbp)->dbdata);
+		/* return memory */
+		isc_mem_put(mctx, (*dbp), sizeof(dns_dlzdb_t));
+		isc_mem_detach(&mctx);
+	}
+
+	*dbp = NULL;
+}
+
+
+isc_result_t
+dns_dlzfindzone(dns_view_t *view, dns_name_t *name, unsigned int minlabels,
+		dns_db_t **dbp)
+{
+	dns_fixedname_t fname;
+	dns_name_t *zonename;
+	unsigned int namelabels;
+	unsigned int i;
+	isc_result_t result;
+	dns_dlzfindzone_t findzone;
+	dns_dlzdb_t *dlzdatabase;
+
+	/*
+	 * Performs checks to make sure data is as we expect it to be.
+	 */
+	REQUIRE(DNS_DLZ_VALID(view->dlzdatabase));
+	REQUIRE(name != NULL);
+	REQUIRE(dbp != NULL && *dbp == NULL);
+
+	/* setup a "fixed" dns name */
+	dns_fixedname_init(&fname);
+	zonename = dns_fixedname_name(&fname);
+
+	/* count the number of labels in the name */
+	namelabels = dns_name_countlabels(name);
+
+	/*
+	 * loop through starting with the longest domain name and
+	 * trying shorter names portions of the name until we find a
+	 * match, have an error, or are below the 'minlabels'
+	 * threshold.  minlabels is 0, if the standard database didn't
+	 * have a zone name match.  Otherwise minlables is the number
+	 * of labels in that name.  We need to beat that for a
+	 * "better" match for the DLZ database to be authoritative
+	 * instead of the standard database.
+	 */
+	for (i = namelabels; i > minlabels && i > 1; i--) {
+		if (i == namelabels) {
+			result = dns_name_copy(name, zonename, NULL);
+			if (result != ISC_R_SUCCESS)
+				return (result);
+		} else
+			dns_name_split(name, i, NULL, zonename);
+
+		/* ask SDLZ driver if the zone is supported */
+		dlzdatabase = view->dlzdatabase;
+		findzone = dlzdatabase->implementation->methods->findzone;
+		result = (*findzone)(dlzdatabase->implementation->driverarg,
+				     dlzdatabase->dbdata, dlzdatabase->mctx,
+				     view->rdclass, zonename, dbp);
+		if (result != ISC_R_NOTFOUND)
+			return (result);
+	}
+	return (ISC_R_NOTFOUND);
+}
+
+/*%
+ * Registers a DLZ driver.  This basically just adds the dlz
+ * driver to the list of available drivers in the dlz_implementations list.
+ */
+isc_result_t
+dns_dlzregister(const char *drivername, const dns_dlzmethods_t *methods,
+		void *driverarg, isc_mem_t *mctx,
+		dns_dlzimplementation_t **dlzimp)
+{
+
+	dns_dlzimplementation_t *dlz_imp;
+
+	/* Write debugging message to log */
+	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+		      "Registering DLZ driver '%s'", drivername);
+
+	/*
+	 * Performs checks to make sure data is as we expect it to be.
+	 */
+	REQUIRE(drivername != NULL);
+	REQUIRE(methods != NULL);
+	REQUIRE(methods->create != NULL);
+	REQUIRE(methods->destroy != NULL);
+	REQUIRE(methods->findzone != NULL);
+	REQUIRE(mctx != NULL);
+	REQUIRE(dlzimp != NULL && *dlzimp == NULL);
+
+	/*
+	 * initialize the dlz_implementations list, this is guaranteed
+	 * to only really happen once.
+	 */
+	RUNTIME_CHECK(isc_once_do(&once, dlz_initialize) == ISC_R_SUCCESS);
+
+	/* lock the dlz_implementations list so we can modify it. */
+	RWLOCK(&dlz_implock, isc_rwlocktype_write);
+
+	/*
+	 * check that another already registered driver isn't using
+	 * the same name
+	 */
+	dlz_imp = dlz_impfind(drivername);
+	if (dlz_imp != NULL) {
+		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+			      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+			      "DLZ Driver '%s' already registered",
+			      drivername);
+		RWUNLOCK(&dlz_implock, isc_rwlocktype_write);
+		return (ISC_R_EXISTS);
+	}
+
+	/*
+	 * Allocate memory for a dlz_implementation object.  Error if
+	 * we cannot.
+	 */
+	dlz_imp = isc_mem_get(mctx, sizeof(dns_dlzimplementation_t));
+	if (dlz_imp == NULL) {
+		RWUNLOCK(&dlz_implock, isc_rwlocktype_write);
+		return (ISC_R_NOMEMORY);
+	}
+
+	/* Make sure memory region is set to all 0's */
+	memset(dlz_imp, 0, sizeof(dns_dlzimplementation_t));
+
+	/* Store the data passed into this method */
+	dlz_imp->name = drivername;
+	dlz_imp->methods = methods;
+	dlz_imp->mctx = NULL;
+	dlz_imp->driverarg = driverarg;
+
+	/* attach the new dlz_implementation object to a memory context */
+	isc_mem_attach(mctx, &dlz_imp->mctx);
+
+	/*
+	 * prepare the dlz_implementation object to be put in a list,
+	 * and append it to the list
+	 */
+	ISC_LINK_INIT(dlz_imp, link);
+	ISC_LIST_APPEND(dlz_implementations, dlz_imp, link);
+
+	/* Unlock the dlz_implementations list.	 */
+	RWUNLOCK(&dlz_implock, isc_rwlocktype_write);
+
+	/* Pass back the dlz_implementation that we created. */
+	*dlzimp = dlz_imp;
+
+	return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Helper function for dns_dlzstrtoargv().
+ * Pardon the gratuitous recursion.
+ */
+static isc_result_t
+dns_dlzstrtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp,
+		    char ***argvp, unsigned int n)
+{
+	isc_result_t result;
+
+ restart:
+	/* Discard leading whitespace. */
+	while (*s == ' ' || *s == '\t')
+		s++;
+
+	if (*s == '\0') {
+		/* We have reached the end of the string. */
+		*argcp = n;
+		*argvp = isc_mem_get(mctx, n * sizeof(char *));
+		if (*argvp == NULL)
+			return (ISC_R_NOMEMORY);
+	} else {
+		char *p = s;
+		while (*p != ' ' && *p != '\t' && *p != '\0' && *p != '{') {
+			if (*p == '\n') {
+				*p = ' ';
+				goto restart;
+			}
+			p++;
+		}
+
+		/* do "grouping", items between { and } are one arg */
+		if (*p == '{') {
+			char *t = p;
+			/*
+			 * shift all characters to left by 1 to get rid of '{'
+			 */
+			while (*t != '\0') {
+				t++;
+				*(t-1) = *t;
+			}
+			while (*p != '\0' && *p != '}') {
+				p++;
+			}
+			/* get rid of '}' character */
+			if (*p == '}') {
+				*p = '\0';
+				p++;
+			}
+			/* normal case, no "grouping" */
+		} else if (*p != '\0')
+			*p++ = '\0';
+
+		result = dns_dlzstrtoargvsub(mctx, p, argcp, argvp, n + 1);
+		if (result != ISC_R_SUCCESS)
+			return (result);
+		(*argvp)[n] = s;
+	}
+	return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Tokenize the string "s" into whitespace-separated words,
+ * return the number of words in '*argcp' and an array
+ * of pointers to the words in '*argvp'.  The caller
+ * must free the array using isc_mem_put().  The string
+ * is modified in-place.
+ */
+isc_result_t
+dns_dlzstrtoargv(isc_mem_t *mctx, char *s,
+		 unsigned int *argcp, char ***argvp)
+{
+	return(dns_dlzstrtoargvsub(mctx, s, argcp, argvp, 0));
+}
+
+/*%
+ * Unregisters a DLZ driver.  This basically just removes the dlz
+ * driver from the list of available drivers in the dlz_implementations list.
+ */
+void
+dns_dlzunregister(dns_dlzimplementation_t **dlzimp) {
+	dns_dlzimplementation_t *dlz_imp;
+	isc_mem_t *mctx;
+
+	/* Write debugging message to log */
+	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+		      "Unregistering DLZ driver.");
+
+	/*
+	 * Performs checks to make sure data is as we expect it to be.
+	 */
+	REQUIRE(dlzimp != NULL && *dlzimp != NULL);
+
+	/*
+	 * initialize the dlz_implementations list, this is guaranteed
+	 * to only really happen once.
+	 */
+	RUNTIME_CHECK(isc_once_do(&once, dlz_initialize) == ISC_R_SUCCESS);
+
+	dlz_imp = *dlzimp;
+
+	/* lock the dlz_implementations list so we can modify it. */
+	RWLOCK(&dlz_implock, isc_rwlocktype_write);
+
+	/* remove the dlz_implementation object from the list */
+	ISC_LIST_UNLINK(dlz_implementations, dlz_imp, link);
+	mctx = dlz_imp->mctx;
+
+	/*
+	 * return the memory back to the available memory pool and
+	 * remove it from the memory context.
+	 */
+	isc_mem_put(mctx, dlz_imp, sizeof(dns_dlzimplementation_t));
+	isc_mem_detach(&mctx);
+
+	/* Unlock the dlz_implementations list. */
+	RWUNLOCK(&dlz_implock, isc_rwlocktype_write);
+}
-- 
cgit v1.1