Blame contrib/dlz/modules/filesystem/dlz_filesystem_dynamic.c

Packit Service ae04f2
/*
Packit Service ae04f2
 * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
Packit Service ae04f2
 *
Packit Service ae04f2
 * Permission to use, copy, modify, and distribute this software for any
Packit Service ae04f2
 * purpose with or without fee is hereby granted, provided that the
Packit Service ae04f2
 * above copyright notice and this permission notice appear in all
Packit Service ae04f2
 * copies.
Packit Service ae04f2
 *
Packit Service ae04f2
 * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
Packit Service ae04f2
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
Packit Service ae04f2
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
Packit Service ae04f2
 * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
Packit Service ae04f2
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
Packit Service ae04f2
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
Packit Service ae04f2
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
Packit Service ae04f2
 * USE OR PERFORMANCE OF THIS SOFTWARE.
Packit Service ae04f2
 *
Packit Service ae04f2
 * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
Packit Service ae04f2
 * conceived and contributed by Rob Butler.
Packit Service ae04f2
 *
Packit Service ae04f2
 * Permission to use, copy, modify, and distribute this software for any
Packit Service ae04f2
 * purpose with or without fee is hereby granted, provided that the
Packit Service ae04f2
 * above copyright notice and this permission notice appear in all
Packit Service ae04f2
 * copies.
Packit Service ae04f2
 *
Packit Service ae04f2
 * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
Packit Service ae04f2
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
Packit Service ae04f2
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
Packit Service ae04f2
 * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
Packit Service ae04f2
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
Packit Service ae04f2
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
Packit Service ae04f2
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
Packit Service ae04f2
 * USE OR PERFORMANCE OF THIS SOFTWARE.
Packit Service ae04f2
 */
Packit Service ae04f2
Packit Service ae04f2
/*
Packit Service ae04f2
 * Copyright (C) 1999-2001, 2013, 2016  Internet Systems Consortium, Inc. ("ISC")
Packit Service ae04f2
 *
Packit Service ae04f2
 * This Source Code Form is subject to the terms of the Mozilla Public
Packit Service ae04f2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
Packit Service ae04f2
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
Packit Service ae04f2
 */
Packit Service ae04f2
Packit Service ae04f2
/*
Packit Service ae04f2
 * This provides the externally loadable filesystem DLZ module, without
Packit Service ae04f2
 * update support
Packit Service ae04f2
 */
Packit Service ae04f2
Packit Service ae04f2
#include <stdio.h>
Packit Service ae04f2
#include <string.h>
Packit Service ae04f2
#include <stdarg.h>
Packit Service ae04f2
#include <stdlib.h>
Packit Service ae04f2
Packit Service ae04f2
#include <sys/stat.h>
Packit Service ae04f2
Packit Service ae04f2
#include "dlz_minimal.h"
Packit Service ae04f2
#include "dlz_list.h"
Packit Service ae04f2
#include "dir.h"
Packit Service ae04f2
Packit Service ae04f2
typedef struct config_data {
Packit Service ae04f2
	char		*basedir;
Packit Service ae04f2
	int		basedirsize;
Packit Service ae04f2
	char		*datadir;
Packit Service ae04f2
	int		datadirsize;
Packit Service ae04f2
	char		*xfrdir;
Packit Service ae04f2
	int		xfrdirsize;
Packit Service ae04f2
	int		splitcnt;
Packit Service ae04f2
	char		separator;
Packit Service ae04f2
	char		pathsep;
Packit Service ae04f2
Packit Service ae04f2
	/* Helper functions from the dlz_dlopen driver */
Packit Service ae04f2
	log_t *log;
Packit Service ae04f2
	dns_sdlz_putrr_t *putrr;
Packit Service ae04f2
	dns_sdlz_putnamedrr_t *putnamedrr;
Packit Service ae04f2
	dns_dlz_writeablezone_t *writeable_zone;
Packit Service ae04f2
} config_data_t;
Packit Service ae04f2
Packit Service ae04f2
typedef struct dir_entry dir_entry_t;
Packit Service ae04f2
Packit Service ae04f2
struct dir_entry {
Packit Service ae04f2
	char dirpath[DIR_PATHMAX];
Packit Service ae04f2
	DLZ_LINK(dir_entry_t)	link;
Packit Service ae04f2
};
Packit Service ae04f2
Packit Service ae04f2
typedef DLZ_LIST(dir_entry_t) dlist_t;
Packit Service ae04f2
Packit Service ae04f2
/* forward reference */
Packit Service ae04f2
Packit Service ae04f2
static void
Packit Service ae04f2
b9_add_helper(struct config_data *cd, const char *helper_name, void *ptr);
Packit Service ae04f2
Packit Service ae04f2
/*
Packit Service ae04f2
 * Private methods
Packit Service ae04f2
 */
Packit Service ae04f2
static bool
Packit Service ae04f2
is_safe(const char *input) {
Packit Service ae04f2
	unsigned int i;
Packit Service ae04f2
	unsigned int len = strlen(input);
Packit Service ae04f2
Packit Service ae04f2
        /* check that only allowed characters are in the domain name */
Packit Service ae04f2
	for (i = 0; i < len; i++) {
Packit Service ae04f2
		/* '.' is allowed, but has special requirements */
Packit Service ae04f2
		if (input[i] == '.') {
Packit Service ae04f2
			/* '.' is not allowed as first char */
Packit Service ae04f2
			if (i == 0)
Packit Service ae04f2
				return (false);
Packit Service ae04f2
			/* '..', two dots together is not allowed. */
Packit Service ae04f2
			if (input[i-1] == '.')
Packit Service ae04f2
				return (false);
Packit Service ae04f2
			/* '.' is not allowed as last char */
Packit Service ae04f2
			if (i == len - 1)
Packit Service ae04f2
				return (false);
Packit Service ae04f2
			/* only 1 dot in ok location, continue at next char */
Packit Service ae04f2
			continue;
Packit Service ae04f2
		}
Packit Service ae04f2
		/* '-' is allowed, continue at next char */
Packit Service ae04f2
		if (input[i] == '-')
Packit Service ae04f2
			continue;
Packit Service ae04f2
		/* 0-9 is allowed, continue at next char */
Packit Service ae04f2
		if (input[i] >= '0' && input[i] <= '9')
Packit Service ae04f2
			continue;
Packit Service ae04f2
		/* A-Z uppercase is allowed, continue at next char */
Packit Service ae04f2
		if (input[i] >= 'A' && input[i] <= 'Z')
Packit Service ae04f2
			continue;
Packit Service ae04f2
		/* a-z lowercase is allowed, continue at next char */
Packit Service ae04f2
		if (input[i] >= 'a' && input[i] <= 'z')
Packit Service ae04f2
			continue;
Packit Service ae04f2
Packit Service ae04f2
		/*
Packit Service ae04f2
		 * colon needs to be allowed for IPV6 client
Packit Service ae04f2
		 * addresses.  Not dangerous in domain names, as not a
Packit Service ae04f2
		 * special char.
Packit Service ae04f2
		 */
Packit Service ae04f2
		if (input[i] == ':')
Packit Service ae04f2
			continue;
Packit Service ae04f2
Packit Service ae04f2
		/*
Packit Service ae04f2
		 * '@' needs to be allowed for in zone data.  Not
Packit Service ae04f2
		 * dangerous in domain names, as not a special char.
Packit Service ae04f2
		 */
Packit Service ae04f2
		if (input[i] == '@')
Packit Service ae04f2
			continue;
Packit Service ae04f2
Packit Service ae04f2
		/*
Packit Service ae04f2
		 * if we reach this point we have encountered a
Packit Service ae04f2
		 * disallowed char!
Packit Service ae04f2
		 */
Packit Service ae04f2
		return (false);
Packit Service ae04f2
	}
Packit Service ae04f2
        /* everything ok. */
Packit Service ae04f2
	return (true);
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
static isc_result_t
Packit Service ae04f2
create_path_helper(char *out, const char *in, config_data_t *cd) {
Packit Service ae04f2
	char *tmpString;
Packit Service ae04f2
	char *tmpPtr;
Packit Service ae04f2
	int i;
Packit Service ae04f2
Packit Service ae04f2
	tmpString = strdup(in);
Packit Service ae04f2
	if (tmpString == NULL)
Packit Service ae04f2
		return (ISC_R_NOMEMORY);
Packit Service ae04f2
Packit Service ae04f2
	/*
Packit Service ae04f2
	 * don't forget is_safe guarantees '.' will NOT be the
Packit Service ae04f2
	 * first/last char
Packit Service ae04f2
	 */
Packit Service ae04f2
	while ((tmpPtr = strrchr(tmpString, '.')) != NULL) {
Packit Service ae04f2
		i = 0;
Packit Service ae04f2
		while (tmpPtr[i+1] != '\0') {
Packit Service ae04f2
			if (cd->splitcnt < 1)
Packit Service ae04f2
				strcat(out, (char *) &tmpPtr[i+1]);
Packit Service ae04f2
			else
Packit Service ae04f2
				strncat(out, (char *) &tmpPtr[i+1],
Packit Service ae04f2
					cd->splitcnt);
Packit Service ae04f2
			strncat(out, (char *) &cd->pathsep, 1);
Packit Service ae04f2
			if (cd->splitcnt == 0)
Packit Service ae04f2
				break;
Packit Service ae04f2
			if (strlen((char *) &tmpPtr[i+1]) <=
Packit Service ae04f2
			    (unsigned int) cd->splitcnt)
Packit Service ae04f2
				break;
Packit Service ae04f2
			i += cd->splitcnt;
Packit Service ae04f2
		}
Packit Service ae04f2
		tmpPtr[0] = '\0';
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	/* handle the "first" label properly */
Packit Service ae04f2
	i=0;
Packit Service ae04f2
	tmpPtr = tmpString;
Packit Service ae04f2
	while (tmpPtr[i] != '\0') {
Packit Service ae04f2
		if (cd->splitcnt < 1)
Packit Service ae04f2
			strcat(out, (char *) &tmpPtr[i]);
Packit Service ae04f2
		else
Packit Service ae04f2
			strncat(out, (char *) &tmpPtr[i], cd->splitcnt);
Packit Service ae04f2
		strncat(out, (char *) &cd->pathsep, 1);
Packit Service ae04f2
		if (cd->splitcnt == 0)
Packit Service ae04f2
			break;
Packit Service ae04f2
		if (strlen((char *) &tmpPtr[i]) <=
Packit Service ae04f2
		    (unsigned int) cd->splitcnt)
Packit Service ae04f2
			break;
Packit Service ae04f2
		i += cd->splitcnt;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	free(tmpString);
Packit Service ae04f2
	return (ISC_R_SUCCESS);
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
/*%
Packit Service ae04f2
 * Checks to make sure zone and host are safe.  If safe, then
Packit Service ae04f2
 * hashes zone and host strings to build a path.  If zone / host
Packit Service ae04f2
 * are not safe an error is returned.
Packit Service ae04f2
 */
Packit Service ae04f2
Packit Service ae04f2
static isc_result_t
Packit Service ae04f2
create_path(const char *zone, const char *host, const char *client,
Packit Service ae04f2
	    config_data_t *cd, char **path)
Packit Service ae04f2
{
Packit Service ae04f2
Packit Service ae04f2
	char *tmpPath;
Packit Service ae04f2
	int pathsize;
Packit Service ae04f2
	int len;
Packit Service ae04f2
	isc_result_t result;
Packit Service ae04f2
	bool isroot = false;
Packit Service ae04f2
Packit Service ae04f2
	/* special case for root zone */
Packit Service ae04f2
	if (strcmp(zone, ".") == 0)
Packit Service ae04f2
		isroot = true;
Packit Service ae04f2
Packit Service ae04f2
	/* if the requested zone is "unsafe", return error */
Packit Service ae04f2
	if (!isroot && !is_safe(zone))
Packit Service ae04f2
		return (ISC_R_FAILURE);
Packit Service ae04f2
Packit Service ae04f2
	/* if host was passed, verify that it is safe */
Packit Service ae04f2
	if (host != NULL && !is_safe(host))
Packit Service ae04f2
		return (ISC_R_FAILURE);
Packit Service ae04f2
Packit Service ae04f2
	/* if client was passed, verify that it is safe */
Packit Service ae04f2
	if (client != NULL && !is_safe(client))
Packit Service ae04f2
		return (ISC_R_FAILURE);
Packit Service ae04f2
Packit Service ae04f2
	/* Determine how much memory the split up string will require */
Packit Service ae04f2
	if (host != NULL)
Packit Service ae04f2
		len = strlen(zone) + strlen(host);
Packit Service ae04f2
	else if (client != NULL)
Packit Service ae04f2
		len = strlen(zone) + strlen(client);
Packit Service ae04f2
	else
Packit Service ae04f2
		len = strlen(zone);
Packit Service ae04f2
Packit Service ae04f2
	/*
Packit Service ae04f2
	 * even though datadir and xfrdir will never be in the same
Packit Service ae04f2
	 * string we only waste a few bytes by allocating for both,
Packit Service ae04f2
	 * and then we are safe from buffer overruns.
Packit Service ae04f2
	 */
Packit Service ae04f2
	pathsize = len + cd->basedirsize +
Packit Service ae04f2
		   cd->datadirsize + cd->xfrdirsize + 4;
Packit Service ae04f2
Packit Service ae04f2
	/* if we are splitting names, we will need extra space. */
Packit Service ae04f2
	if (cd->splitcnt > 0)
Packit Service ae04f2
		pathsize += len/cd->splitcnt;
Packit Service ae04f2
Packit Service ae04f2
	tmpPath = malloc(pathsize * sizeof(char));
Packit Service ae04f2
	if (tmpPath == NULL) {
Packit Service ae04f2
		/* write error message */
Packit Service ae04f2
		cd->log(ISC_LOG_ERROR,
Packit Service ae04f2
			"Filesystem driver unable to "
Packit Service ae04f2
			"allocate memory in create_path().");
Packit Service ae04f2
		result = ISC_R_NOMEMORY;
Packit Service ae04f2
		goto cleanup_mem;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	/*
Packit Service ae04f2
	 * build path string.
Packit Service ae04f2
	 * start out with base directory.
Packit Service ae04f2
	 */
Packit Service ae04f2
	strcpy(tmpPath, cd->basedir);
Packit Service ae04f2
Packit Service ae04f2
	/* add zone name - parsed properly */
Packit Service ae04f2
	if (!isroot) {
Packit Service ae04f2
		result = create_path_helper(tmpPath, zone, cd);
Packit Service ae04f2
		if (result != ISC_R_SUCCESS)
Packit Service ae04f2
			goto cleanup_mem;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	/*
Packit Service ae04f2
	 * When neither client or host is passed we are building a
Packit Service ae04f2
	 * path to see if a zone is supported.  We require that a zone
Packit Service ae04f2
	 * path have the "data dir" directory contained within it so
Packit Service ae04f2
	 * that we know this zone is really supported.  Otherwise,
Packit Service ae04f2
	 * this zone may not really be supported because we are
Packit Service ae04f2
	 * supporting a delagated sub zone.
Packit Service ae04f2
	 *
Packit Service ae04f2
	 * Example:
Packit Service ae04f2
	 *
Packit Service ae04f2
	 * We are supporting long.domain.com and using a splitcnt of
Packit Service ae04f2
	 * 0.  the base dir is "/base-dir/" and the data dir is
Packit Service ae04f2
	 * "/.datadir" We want to see if we are authoritative for
Packit Service ae04f2
	 * domain.com.  Path /base-dir/com/domain/.datadir since
Packit Service ae04f2
	 * /base-dir/com/domain/.datadir does not exist, we are not
Packit Service ae04f2
	 * authoritative for the domain "domain.com".  However we are
Packit Service ae04f2
	 * authoritative for the domain "long.domain.com" because the
Packit Service ae04f2
	 * path /base-dir/com/domain/long/.datadir does exist!
Packit Service ae04f2
	 */
Packit Service ae04f2
Packit Service ae04f2
	/* if client is passed append xfr dir, otherwise append data dir */
Packit Service ae04f2
	if (client != NULL) {
Packit Service ae04f2
		strcat(tmpPath, cd->xfrdir);
Packit Service ae04f2
		strncat(tmpPath, (char *) &cd->pathsep, 1);
Packit Service ae04f2
		strcat(tmpPath, client);
Packit Service ae04f2
	} else
Packit Service ae04f2
		strcat(tmpPath, cd->datadir);
Packit Service ae04f2
Packit Service ae04f2
	/* if host not null, add it. */
Packit Service ae04f2
	if (host != NULL) {
Packit Service ae04f2
		strncat(tmpPath, (char *) &cd->pathsep, 1);
Packit Service ae04f2
		result = create_path_helper(tmpPath, host, cd);
Packit Service ae04f2
		if (result != ISC_R_SUCCESS)
Packit Service ae04f2
			goto cleanup_mem;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	/* return the path we built. */
Packit Service ae04f2
	*path = tmpPath;
Packit Service ae04f2
Packit Service ae04f2
	/* return success */
Packit Service ae04f2
	result = ISC_R_SUCCESS;
Packit Service ae04f2
Packit Service ae04f2
 cleanup_mem:
Packit Service ae04f2
	/* cleanup memory */
Packit Service ae04f2
Packit Service ae04f2
	/* free tmpPath memory */
Packit Service ae04f2
	if (tmpPath != NULL && result != ISC_R_SUCCESS)
Packit Service ae04f2
		free(tmpPath);
Packit Service ae04f2
Packit Service ae04f2
	return (result);
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
static isc_result_t
Packit Service ae04f2
process_dir(dir_t *dir, void *passback, config_data_t *cd,
Packit Service ae04f2
	    dlist_t *dir_list, unsigned int basedirlen)
Packit Service ae04f2
{
Packit Service ae04f2
Packit Service ae04f2
	char tmp[DIR_PATHMAX + DIR_NAMEMAX];
Packit Service ae04f2
	int astPos;
Packit Service ae04f2
	struct stat	sb;
Packit Service ae04f2
	isc_result_t result = ISC_R_FAILURE;
Packit Service ae04f2
	char *endp;
Packit Service ae04f2
	char *type;
Packit Service ae04f2
	char *ttlStr;
Packit Service ae04f2
	char *data;
Packit Service ae04f2
	char host[DIR_NAMEMAX];
Packit Service ae04f2
	char *tmpString;
Packit Service ae04f2
	char *tmpPtr;
Packit Service ae04f2
	int ttl;
Packit Service ae04f2
	int i;
Packit Service ae04f2
	int len;
Packit Service ae04f2
	dir_entry_t *direntry;
Packit Service ae04f2
	bool foundHost;
Packit Service ae04f2
Packit Service ae04f2
	tmp[0] = '\0'; /* set 1st byte to '\0' so strcpy works right. */
Packit Service ae04f2
	host[0] = '\0';
Packit Service ae04f2
	foundHost = false;
Packit Service ae04f2
Packit Service ae04f2
	/* copy base directory name to tmp. */
Packit Service ae04f2
	strcpy(tmp, dir->dirname);
Packit Service ae04f2
Packit Service ae04f2
	/* dir->dirname will always have '*' as the last char. */
Packit Service ae04f2
	astPos = strlen(dir->dirname) - 1;
Packit Service ae04f2
Packit Service ae04f2
	/* if dir_list != NULL, were are performing a zone xfr */
Packit Service ae04f2
	if (dir_list != NULL) {
Packit Service ae04f2
		/* if splitcnt == 0, determine host from path. */
Packit Service ae04f2
		if (cd->splitcnt == 0) {
Packit Service ae04f2
			if (strlen(tmp) - 3 > basedirlen) {
Packit Service ae04f2
				tmp[astPos-1] = '\0';
Packit Service ae04f2
				tmpString = (char *) &tmp[basedirlen+1];
Packit Service ae04f2
				/* handle filesystem's special wildcard "-"  */
Packit Service ae04f2
				if (strcmp(tmpString, "-") == 0) {
Packit Service ae04f2
					strcpy(host, "*");
Packit Service ae04f2
				} else {
Packit Service ae04f2
					/*
Packit Service ae04f2
					 * not special wildcard -- normal name
Packit Service ae04f2
					 */
Packit Service ae04f2
					while ((tmpPtr = strrchr(tmpString,
Packit Service ae04f2
								 cd->pathsep))
Packit Service ae04f2
					       != NULL)
Packit Service ae04f2
					{
Packit Service ae04f2
						if ((strlen(host) +
Packit Service ae04f2
						     strlen(tmpPtr + 1) + 2)
Packit Service ae04f2
						    > DIR_NAMEMAX)
Packit Service ae04f2
							continue;
Packit Service ae04f2
						strcat(host, tmpPtr + 1);
Packit Service ae04f2
						strcat(host, ".");
Packit Service ae04f2
						tmpPtr[0] = '\0';
Packit Service ae04f2
					}
Packit Service ae04f2
					if ((strlen(host) +
Packit Service ae04f2
					     strlen(tmpString) + 1)
Packit Service ae04f2
					    <= DIR_NAMEMAX)
Packit Service ae04f2
						strcat(host, tmpString);
Packit Service ae04f2
				}
Packit Service ae04f2
Packit Service ae04f2
				foundHost = true;
Packit Service ae04f2
				/* set tmp again for use later */
Packit Service ae04f2
				strcpy(tmp, dir->dirname);
Packit Service ae04f2
			}
Packit Service ae04f2
		} else {
Packit Service ae04f2
			/*
Packit Service ae04f2
			 * if splitcnt != 0 determine host from
Packit Service ae04f2
			 * ".host" directory entry
Packit Service ae04f2
			 */
Packit Service ae04f2
			while (dir_read(dir) == ISC_R_SUCCESS) {
Packit Service ae04f2
				if (strncasecmp(".host",
Packit Service ae04f2
						dir->entry.name, 5) == 0) {
Packit Service ae04f2
					/*
Packit Service ae04f2
					 * handle filesystem's special
Packit Service ae04f2
					 * wildcard "-"
Packit Service ae04f2
					 */
Packit Service ae04f2
					if (strcmp((char *) &dir->entry.name[6],
Packit Service ae04f2
						   "-") == 0)
Packit Service ae04f2
						strcpy(host, "*");
Packit Service ae04f2
					else {
Packit Service ae04f2
						strncpy(host,
Packit Service ae04f2
						   (char *) &dir->entry.name[6],
Packit Service ae04f2
						   sizeof(host) - 1);
Packit Service ae04f2
						host[255] = '\0';
Packit Service ae04f2
					}
Packit Service ae04f2
					foundHost = true;
Packit Service ae04f2
					break;
Packit Service ae04f2
				}
Packit Service ae04f2
			}
Packit Service ae04f2
			/* reset dir list for use later */
Packit Service ae04f2
			dir_reset(dir);
Packit Service ae04f2
		} /* end of else */
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	while (dir_read(dir) == ISC_R_SUCCESS) {
Packit Service ae04f2
		cd->log(ISC_LOG_DEBUG(1),
Packit Service ae04f2
			"Filesystem driver Dir name:"
Packit Service ae04f2
			" '%s' Dir entry: '%s'\n",
Packit Service ae04f2
			dir->dirname, dir->entry.name);
Packit Service ae04f2
Packit Service ae04f2
		/* skip any entries starting with "." */
Packit Service ae04f2
		if (dir->entry.name[0] == '.')
Packit Service ae04f2
			continue;
Packit Service ae04f2
Packit Service ae04f2
		/*
Packit Service ae04f2
		 * get rid of '*', set to NULL.  Effectively trims
Packit Service ae04f2
		 * string from previous loop to base directory only
Packit Service ae04f2
		 * while still leaving memory for concat to be
Packit Service ae04f2
		 * performed next.
Packit Service ae04f2
		 */
Packit Service ae04f2
Packit Service ae04f2
		tmp[astPos] = '\0';
Packit Service ae04f2
Packit Service ae04f2
		/* add name to base directory name. */
Packit Service ae04f2
		strcat(tmp, dir->entry.name);
Packit Service ae04f2
Packit Service ae04f2
		/* make sure we can stat entry */
Packit Service ae04f2
		if (stat(tmp, &sb) == 0 ) {
Packit Service ae04f2
			/* if entry is a directory */
Packit Service ae04f2
			if ((sb.st_mode & S_IFDIR) != 0) {
Packit Service ae04f2
				/*
Packit Service ae04f2
				 * if dir list is NOT NULL, add dir to
Packit Service ae04f2
				 * dir list
Packit Service ae04f2
				 */
Packit Service ae04f2
				if (dir_list != NULL) {
Packit Service ae04f2
					direntry = malloc(sizeof(dir_entry_t));
Packit Service ae04f2
					if (direntry == NULL)
Packit Service ae04f2
						return (ISC_R_NOMEMORY);
Packit Service ae04f2
					strcpy(direntry->dirpath, tmp);
Packit Service ae04f2
					DLZ_LINK_INIT(direntry, link);
Packit Service ae04f2
					DLZ_LIST_APPEND(*dir_list, direntry,
Packit Service ae04f2
							link);
Packit Service ae04f2
					result = ISC_R_SUCCESS;
Packit Service ae04f2
				}
Packit Service ae04f2
				continue;
Packit Service ae04f2
Packit Service ae04f2
				/*
Packit Service ae04f2
				 * if entry is a file be sure we do
Packit Service ae04f2
				 * not add entry to DNS results if we
Packit Service ae04f2
				 * are performing a zone xfr and we
Packit Service ae04f2
				 * could not find a host entry.
Packit Service ae04f2
				 */
Packit Service ae04f2
Packit Service ae04f2
			} else if (dir_list != NULL &&
Packit Service ae04f2
				   foundHost == false) {
Packit Service ae04f2
				continue;
Packit Service ae04f2
			}
Packit Service ae04f2
		} else /* if we cannot stat entry, skip it. */
Packit Service ae04f2
			continue;
Packit Service ae04f2
Packit Service ae04f2
		type = dir->entry.name;
Packit Service ae04f2
		ttlStr = strchr(type,  cd->separator);
Packit Service ae04f2
		if (ttlStr == NULL) {
Packit Service ae04f2
			cd->log(ISC_LOG_ERROR,
Packit Service ae04f2
				"Filesystem driver: "
Packit Service ae04f2
				"%s could not be parsed properly", tmp);
Packit Service ae04f2
			return (ISC_R_FAILURE);
Packit Service ae04f2
		}
Packit Service ae04f2
Packit Service ae04f2
		/* replace separator char with NULL to split string */
Packit Service ae04f2
		ttlStr[0] = '\0';
Packit Service ae04f2
		/* start string after NULL of previous string */
Packit Service ae04f2
		ttlStr = (char *) &ttlStr[1];
Packit Service ae04f2
Packit Service ae04f2
		data = strchr(ttlStr, cd->separator);
Packit Service ae04f2
		if (data == NULL) {
Packit Service ae04f2
			cd->log(ISC_LOG_ERROR,
Packit Service ae04f2
				"Filesystem driver: "
Packit Service ae04f2
				"%s could not be parsed properly", tmp);
Packit Service ae04f2
			return (ISC_R_FAILURE);
Packit Service ae04f2
		}
Packit Service ae04f2
Packit Service ae04f2
		/* replace separator char with NULL to split string */
Packit Service ae04f2
		data[0] = '\0';
Packit Service ae04f2
Packit Service ae04f2
		/* start string after NULL of previous string */
Packit Service ae04f2
		data = (char *) &data[1];
Packit Service ae04f2
Packit Service ae04f2
		/* replace all cd->separator chars with a space. */
Packit Service ae04f2
		len = strlen(data);
Packit Service ae04f2
Packit Service ae04f2
		for (i=0; i < len; i++) {
Packit Service ae04f2
			if (data[i] == cd->separator)
Packit Service ae04f2
				data[i] = ' ';
Packit Service ae04f2
		}
Packit Service ae04f2
Packit Service ae04f2
		/* convert text to int, make sure it worked right */
Packit Service ae04f2
		ttl = strtol(ttlStr, &endp, 10);
Packit Service ae04f2
		if (*endp != '\0' || ttl < 0)
Packit Service ae04f2
			cd->log(ISC_LOG_ERROR,
Packit Service ae04f2
				"Filesystem driver "
Packit Service ae04f2
				"ttl must be a positive number");
Packit Service ae04f2
Packit Service ae04f2
		/* pass data back to Bind */
Packit Service ae04f2
		if (dir_list == NULL)
Packit Service ae04f2
			result = cd->putrr((dns_sdlzlookup_t *) passback,
Packit Service ae04f2
					   type, ttl, data);
Packit Service ae04f2
		else
Packit Service ae04f2
			result = cd->putnamedrr((dns_sdlzallnodes_t *) passback,
Packit Service ae04f2
						(char *) host,
Packit Service ae04f2
						type, ttl, data);
Packit Service ae04f2
Packit Service ae04f2
		/* if error, return error right away */
Packit Service ae04f2
		if (result != ISC_R_SUCCESS)
Packit Service ae04f2
			return (result);
Packit Service ae04f2
	} /* end of while loop */
Packit Service ae04f2
Packit Service ae04f2
	return (result);
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
/*
Packit Service ae04f2
 * DLZ methods
Packit Service ae04f2
 */
Packit Service ae04f2
isc_result_t
Packit Service ae04f2
dlz_allowzonexfr(void *dbdata, const char *name, const char *client) {
Packit Service ae04f2
	isc_result_t result;
Packit Service ae04f2
	char *path;
Packit Service ae04f2
	struct stat	sb;
Packit Service ae04f2
	config_data_t *cd;
Packit Service ae04f2
	path = NULL;
Packit Service ae04f2
Packit Service ae04f2
	cd = (config_data_t *) dbdata;
Packit Service ae04f2
Packit Service ae04f2
	if (create_path(name, NULL, client, cd, &path) != ISC_R_SUCCESS) {
Packit Service ae04f2
		return (ISC_R_NOTFOUND);
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	if (stat(path, &sb) != 0) {
Packit Service ae04f2
		result = ISC_R_NOTFOUND;
Packit Service ae04f2
		goto complete_AXFR;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	if ((sb.st_mode & S_IFREG) != 0) {
Packit Service ae04f2
		result = ISC_R_SUCCESS;
Packit Service ae04f2
		goto complete_AXFR;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	result = ISC_R_NOTFOUND;
Packit Service ae04f2
Packit Service ae04f2
 complete_AXFR:
Packit Service ae04f2
	free(path);
Packit Service ae04f2
	return (result);
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
isc_result_t
Packit Service ae04f2
dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes) {
Packit Service ae04f2
	isc_result_t result;
Packit Service ae04f2
	dlist_t *dir_list;
Packit Service ae04f2
	config_data_t *cd = (config_data_t *) dbdata;
Packit Service ae04f2
	char *basepath;
Packit Service ae04f2
	unsigned int basepathlen;
Packit Service ae04f2
	struct stat	sb;
Packit Service ae04f2
	dir_t dir;
Packit Service ae04f2
	dir_entry_t *dir_entry;
Packit Service ae04f2
	dir_entry_t *next_de;
Packit Service ae04f2
Packit Service ae04f2
	basepath = NULL;
Packit Service ae04f2
	dir_list = NULL;
Packit Service ae04f2
Packit Service ae04f2
	/* allocate memory for list */
Packit Service ae04f2
	dir_list = malloc(sizeof(dlist_t));
Packit Service ae04f2
	if (dir_list == NULL) {
Packit Service ae04f2
		result = ISC_R_NOTFOUND;
Packit Service ae04f2
		goto complete_allnds;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	/* initialize list */
Packit Service ae04f2
	DLZ_LIST_INIT(*dir_list);
Packit Service ae04f2
Packit Service ae04f2
	if (create_path(zone, NULL, NULL, cd, &basepath) != ISC_R_SUCCESS) {
Packit Service ae04f2
		result = ISC_R_NOTFOUND;
Packit Service ae04f2
		goto complete_allnds;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	/* remove path separator at end of path so stat works properly */
Packit Service ae04f2
	basepathlen = strlen(basepath);
Packit Service ae04f2
Packit Service ae04f2
	if (stat(basepath, &sb) != 0) {
Packit Service ae04f2
		result = ISC_R_NOTFOUND;
Packit Service ae04f2
		goto complete_allnds;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	if ((sb.st_mode & S_IFDIR) == 0) {
Packit Service ae04f2
		result = ISC_R_NOTFOUND;
Packit Service ae04f2
		goto complete_allnds;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	/* initialize and open directory */
Packit Service ae04f2
	dir_init(&dir;;
Packit Service ae04f2
	result = dir_open(&dir, basepath);
Packit Service ae04f2
Packit Service ae04f2
	/* if directory open failed, return error. */
Packit Service ae04f2
	if (result != ISC_R_SUCCESS) {
Packit Service ae04f2
		cd->log(ISC_LOG_ERROR,
Packit Service ae04f2
			"Unable to open %s directory to read entries.",
Packit Service ae04f2
			basepath);
Packit Service ae04f2
		result = ISC_R_FAILURE;
Packit Service ae04f2
		goto complete_allnds;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	/* process the directory */
Packit Service ae04f2
	result = process_dir(&dir, allnodes, cd, dir_list, basepathlen);
Packit Service ae04f2
Packit Service ae04f2
	/* close the directory */
Packit Service ae04f2
	dir_close(&dir;;
Packit Service ae04f2
Packit Service ae04f2
	if (result != ISC_R_SUCCESS)
Packit Service ae04f2
		goto complete_allnds;
Packit Service ae04f2
Packit Service ae04f2
	/* get first dir entry from list. */
Packit Service ae04f2
	dir_entry = DLZ_LIST_HEAD(*dir_list);
Packit Service ae04f2
	while (dir_entry != NULL) {
Packit Service ae04f2
		result = dir_open(&dir, dir_entry->dirpath);
Packit Service ae04f2
		/* if directory open failed, return error. */
Packit Service ae04f2
		if (result != ISC_R_SUCCESS) {
Packit Service ae04f2
			cd->log(ISC_LOG_ERROR,
Packit Service ae04f2
				"Unable to open %s "
Packit Service ae04f2
				"directory to read entries.", basepath);
Packit Service ae04f2
			result = ISC_R_FAILURE;
Packit Service ae04f2
			goto complete_allnds;
Packit Service ae04f2
		}
Packit Service ae04f2
Packit Service ae04f2
		/* process the directory */
Packit Service ae04f2
		result = process_dir(&dir, allnodes, cd, dir_list, basepathlen);
Packit Service ae04f2
Packit Service ae04f2
		/* close the directory */
Packit Service ae04f2
		dir_close(&dir;;
Packit Service ae04f2
Packit Service ae04f2
		if (result != ISC_R_SUCCESS)
Packit Service ae04f2
			goto complete_allnds;
Packit Service ae04f2
Packit Service ae04f2
		dir_entry = DLZ_LIST_NEXT(dir_entry, link);
Packit Service ae04f2
	} /* end while */
Packit Service ae04f2
Packit Service ae04f2
 complete_allnds:
Packit Service ae04f2
	if (dir_list != NULL) {
Packit Service ae04f2
		/* clean up entries from list. */
Packit Service ae04f2
		dir_entry = DLZ_LIST_HEAD(*dir_list);
Packit Service ae04f2
		while (dir_entry != NULL) {
Packit Service ae04f2
			next_de = DLZ_LIST_NEXT(dir_entry, link);
Packit Service ae04f2
			free(dir_entry);
Packit Service ae04f2
			dir_entry = next_de;
Packit Service ae04f2
		} /* end while */
Packit Service ae04f2
		free(dir_list);
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	if (basepath != NULL)
Packit Service ae04f2
		free(basepath);
Packit Service ae04f2
Packit Service ae04f2
	return (result);
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
#if DLZ_DLOPEN_VERSION < 3
Packit Service ae04f2
isc_result_t
Packit Service ae04f2
dlz_findzonedb(void *dbdata, const char *name)
Packit Service ae04f2
#else
Packit Service ae04f2
isc_result_t
Packit Service ae04f2
dlz_findzonedb(void *dbdata, const char *name,
Packit Service ae04f2
	       dns_clientinfomethods_t *methods,
Packit Service ae04f2
	       dns_clientinfo_t *clientinfo)
Packit Service ae04f2
#endif
Packit Service ae04f2
{
Packit Service ae04f2
Packit Service ae04f2
	isc_result_t result;
Packit Service ae04f2
	config_data_t *cd = (config_data_t *) dbdata;
Packit Service ae04f2
	char *path;
Packit Service ae04f2
	struct stat sb;
Packit Service ae04f2
	path = NULL;
Packit Service ae04f2
Packit Service ae04f2
#if DLZ_DLOPEN_VERSION >= 3
Packit Service ae04f2
	UNUSED(methods);
Packit Service ae04f2
	UNUSED(clientinfo);
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
	if (create_path(name, NULL, NULL, cd, &path) != ISC_R_SUCCESS)
Packit Service ae04f2
		return (ISC_R_NOTFOUND);
Packit Service ae04f2
Packit Service ae04f2
	cd->log(ISC_LOG_DEBUG(1),
Packit Service ae04f2
		"Filesystem driver Findzone() Checking for path: '%s'\n", path);
Packit Service ae04f2
Packit Service ae04f2
	if (stat(path, &sb) != 0) {
Packit Service ae04f2
		result = ISC_R_NOTFOUND;
Packit Service ae04f2
		goto complete_FZ;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	if ((sb.st_mode & S_IFDIR) != 0) {
Packit Service ae04f2
		result = ISC_R_SUCCESS;
Packit Service ae04f2
		goto complete_FZ;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	result = ISC_R_NOTFOUND;
Packit Service ae04f2
Packit Service ae04f2
 complete_FZ:
Packit Service ae04f2
Packit Service ae04f2
	free(path);
Packit Service ae04f2
	return (result);
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
#if DLZ_DLOPEN_VERSION == 1
Packit Service ae04f2
isc_result_t
Packit Service ae04f2
dlz_lookup(const char *zone, const char *name,
Packit Service ae04f2
	   void *dbdata, dns_sdlzlookup_t *lookup)
Packit Service ae04f2
#else
Packit Service ae04f2
isc_result_t
Packit Service ae04f2
dlz_lookup(const char *zone, const char *name,
Packit Service ae04f2
	   void *dbdata, dns_sdlzlookup_t *lookup,
Packit Service ae04f2
	   dns_clientinfomethods_t *methods,
Packit Service ae04f2
	   dns_clientinfo_t *clientinfo)
Packit Service ae04f2
#endif
Packit Service ae04f2
{
Packit Service ae04f2
	isc_result_t result = ISC_R_NOTFOUND;
Packit Service ae04f2
	config_data_t *cd = (config_data_t *) dbdata;
Packit Service ae04f2
	char *path;
Packit Service ae04f2
	struct stat sb;
Packit Service ae04f2
	dir_t dir;
Packit Service ae04f2
	path = NULL;
Packit Service ae04f2
Packit Service ae04f2
	UNUSED(lookup);
Packit Service ae04f2
#if DLZ_DLOPEN_VERSION >= 2
Packit Service ae04f2
	UNUSED(methods);
Packit Service ae04f2
	UNUSED(clientinfo);
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
	if (strcmp(name, "*") == 0)
Packit Service ae04f2
		/*
Packit Service ae04f2
		 * handle filesystem's special wildcard "-"
Packit Service ae04f2
		 */
Packit Service ae04f2
		result = create_path(zone, "-", NULL, cd, &path);
Packit Service ae04f2
	else
Packit Service ae04f2
		result = create_path(zone, name, NULL, cd, &path);
Packit Service ae04f2
Packit Service ae04f2
	if (result != ISC_R_SUCCESS)
Packit Service ae04f2
		return (ISC_R_NOTFOUND);
Packit Service ae04f2
Packit Service ae04f2
	/* remove path separator at end of path so stat works properly */
Packit Service ae04f2
	path[strlen(path)-1] = '\0';
Packit Service ae04f2
Packit Service ae04f2
	cd->log(ISC_LOG_DEBUG(1),
Packit Service ae04f2
		"Filesystem driver lookup() Checking for path: '%s'\n", path);
Packit Service ae04f2
Packit Service ae04f2
	if (stat(path, &sb) != 0) {
Packit Service ae04f2
		result = ISC_R_NOTFOUND;
Packit Service ae04f2
		goto complete_lkup;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	if ((sb.st_mode & S_IFDIR) == 0) {
Packit Service ae04f2
		result = ISC_R_NOTFOUND;
Packit Service ae04f2
		goto complete_lkup;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	/* initialize and open directory */
Packit Service ae04f2
	dir_init(&dir;;
Packit Service ae04f2
	result = dir_open(&dir, path);
Packit Service ae04f2
Packit Service ae04f2
	/* if directory open failed, return error. */
Packit Service ae04f2
	if (result != ISC_R_SUCCESS) {
Packit Service ae04f2
		cd->log(ISC_LOG_ERROR,
Packit Service ae04f2
			"Unable to open %s directory to read entries.", path);
Packit Service ae04f2
		result = ISC_R_FAILURE;
Packit Service ae04f2
		goto complete_lkup;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	/* process any records in the directory */
Packit Service ae04f2
	result = process_dir(&dir, lookup, cd, NULL, 0);
Packit Service ae04f2
Packit Service ae04f2
	/* close the directory */
Packit Service ae04f2
	dir_close(&dir;;
Packit Service ae04f2
Packit Service ae04f2
 complete_lkup:
Packit Service ae04f2
Packit Service ae04f2
	free(path);
Packit Service ae04f2
	return (result);
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
isc_result_t
Packit Service ae04f2
dlz_create(const char *dlzname, unsigned int argc, char *argv[],
Packit Service ae04f2
	   void **dbdata, ...)
Packit Service ae04f2
{
Packit Service ae04f2
	isc_result_t result = ISC_R_NOMEMORY;
Packit Service ae04f2
	config_data_t *cd;
Packit Service ae04f2
	char *endp;
Packit Service ae04f2
	int len;
Packit Service ae04f2
	char pathsep;
Packit Service ae04f2
	const char *helper_name;
Packit Service ae04f2
	va_list ap;
Packit Service ae04f2
Packit Service ae04f2
	UNUSED(dlzname);
Packit Service ae04f2
Packit Service ae04f2
	/* allocate memory for our config data and helper functions */
Packit Service ae04f2
	cd = calloc(1, sizeof(config_data_t));
Packit Service ae04f2
	if (cd == NULL)
Packit Service ae04f2
		goto no_mem;
Packit Service ae04f2
Packit Service ae04f2
	/* zero the memory */
Packit Service ae04f2
	memset(cd, 0, sizeof(config_data_t));
Packit Service ae04f2
Packit Service ae04f2
	/* Fill in the helper functions */
Packit Service ae04f2
	va_start(ap, dbdata);
Packit Service ae04f2
	while ((helper_name = va_arg(ap, const char*)) != NULL)
Packit Service ae04f2
		b9_add_helper(cd, helper_name, va_arg(ap, void*));
Packit Service ae04f2
	va_end(ap);
Packit Service ae04f2
Packit Service ae04f2
	/* we require 5 command line args. */
Packit Service ae04f2
	if (argc != 6) {
Packit Service ae04f2
		cd->log(ISC_LOG_ERROR,
Packit Service ae04f2
			"Filesystem driver requires "
Packit Service ae04f2
			"6 command line args.");
Packit Service ae04f2
		result = ISC_R_FAILURE;
Packit Service ae04f2
		goto free_cd;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	if (strlen(argv[5]) > 1) {
Packit Service ae04f2
		cd->log(ISC_LOG_ERROR,
Packit Service ae04f2
			"Filesystem driver can only "
Packit Service ae04f2
			"accept a single character for separator.");
Packit Service ae04f2
		result = ISC_R_FAILURE;
Packit Service ae04f2
		goto free_cd;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	/* verify base dir ends with '/' or '\' */
Packit Service ae04f2
	len = strlen(argv[1]);
Packit Service ae04f2
	if (argv[1][len-1] != '\\' && argv[1][len-1] != '/') {
Packit Service ae04f2
		cd->log(ISC_LOG_ERROR,
Packit Service ae04f2
			"Base dir parameter for filesystem driver "
Packit Service ae04f2
			"should end with %s",
Packit Service ae04f2
			"either '/' or '\\' ");
Packit Service ae04f2
		result = ISC_R_FAILURE;
Packit Service ae04f2
		goto free_cd;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	/* determine and save path separator for later */
Packit Service ae04f2
	if (argv[1][len-1] == '\\')
Packit Service ae04f2
		pathsep = '\\';
Packit Service ae04f2
	else
Packit Service ae04f2
		pathsep = '/';
Packit Service ae04f2
Packit Service ae04f2
	cd->pathsep = pathsep;
Packit Service ae04f2
Packit Service ae04f2
	/* get and store our base directory */
Packit Service ae04f2
	cd->basedir = strdup(argv[1]);
Packit Service ae04f2
	if (cd->basedir == NULL)
Packit Service ae04f2
		goto no_mem;
Packit Service ae04f2
	cd->basedirsize = strlen(cd->basedir);
Packit Service ae04f2
Packit Service ae04f2
	/* get and store our data sub-dir */
Packit Service ae04f2
	cd->datadir = strdup(argv[2]);
Packit Service ae04f2
	if (cd->datadir == NULL)
Packit Service ae04f2
		goto no_mem;
Packit Service ae04f2
	cd->datadirsize = strlen(cd->datadir);
Packit Service ae04f2
Packit Service ae04f2
	/* get and store our zone xfr sub-dir */
Packit Service ae04f2
	cd->xfrdir = strdup(argv[3]);
Packit Service ae04f2
	if (cd->xfrdir == NULL)
Packit Service ae04f2
		goto no_mem;
Packit Service ae04f2
	cd->xfrdirsize = strlen(cd->xfrdir);
Packit Service ae04f2
Packit Service ae04f2
	/* get and store our directory split count */
Packit Service ae04f2
	cd->splitcnt = strtol(argv[4], &endp, 10);
Packit Service ae04f2
	if (*endp != '\0' || cd->splitcnt < 0)
Packit Service ae04f2
		cd->log(ISC_LOG_ERROR,
Packit Service ae04f2
			"Directory split count must be zero (0) "
Packit Service ae04f2
			"or a positive number");
Packit Service ae04f2
Packit Service ae04f2
	/* get and store our separator character */
Packit Service ae04f2
	cd->separator = *argv[5];
Packit Service ae04f2
Packit Service ae04f2
	/* pass back config data */
Packit Service ae04f2
	*dbdata = cd;
Packit Service ae04f2
Packit Service ae04f2
	/* return success */
Packit Service ae04f2
	return (ISC_R_SUCCESS);
Packit Service ae04f2
Packit Service ae04f2
	/* handle no memory error */
Packit Service ae04f2
 no_mem:
Packit Service ae04f2
Packit Service ae04f2
	/* write error message */
Packit Service ae04f2
	if (cd != NULL && cd->log != NULL)
Packit Service ae04f2
		cd->log(ISC_LOG_ERROR,
Packit Service ae04f2
			"filesystem_dynamic: Filesystem driver unable to "
Packit Service ae04f2
			"allocate memory for config data.");
Packit Service ae04f2
Packit Service ae04f2
 free_cd:
Packit Service ae04f2
	/* if we allocated a config data object clean it up */
Packit Service ae04f2
	if (cd != NULL)
Packit Service ae04f2
		dlz_destroy(cd);
Packit Service ae04f2
Packit Service ae04f2
	/* return error */
Packit Service ae04f2
	return (result);
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
void
Packit Service ae04f2
dlz_destroy(void *dbdata) {
Packit Service ae04f2
	config_data_t *cd;
Packit Service ae04f2
Packit Service ae04f2
	cd = (config_data_t *) dbdata;
Packit Service ae04f2
Packit Service ae04f2
	/*
Packit Service ae04f2
	 * free memory for each section of config data that was
Packit Service ae04f2
	 * allocated
Packit Service ae04f2
	 */
Packit Service ae04f2
	if (cd->basedir != NULL)
Packit Service ae04f2
		free(cd->basedir);
Packit Service ae04f2
Packit Service ae04f2
	if (cd->datadir != NULL)
Packit Service ae04f2
		free(cd->datadir);
Packit Service ae04f2
Packit Service ae04f2
	if (cd->xfrdir != NULL)
Packit Service ae04f2
		free(cd->xfrdir);
Packit Service ae04f2
Packit Service ae04f2
	/* free config data memory */
Packit Service ae04f2
	free(cd);
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
/*
Packit Service ae04f2
 * Return the version of the API
Packit Service ae04f2
 */
Packit Service ae04f2
int
Packit Service ae04f2
dlz_version(unsigned int *flags) {
Packit Service ae04f2
	UNUSED(flags);
Packit Service ae04f2
	return (DLZ_DLOPEN_VERSION);
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
/*
Packit Service ae04f2
 * Register a helper function from the bind9 dlz_dlopen driver
Packit Service ae04f2
 */
Packit Service ae04f2
static void
Packit Service ae04f2
b9_add_helper(struct config_data *cd, const char *helper_name, void *ptr) {
Packit Service ae04f2
	if (strcmp(helper_name, "log") == 0)
Packit Service ae04f2
		cd->log = (log_t *)ptr;
Packit Service ae04f2
	if (strcmp(helper_name, "putrr") == 0)
Packit Service ae04f2
		cd->putrr = (dns_sdlz_putrr_t *)ptr;
Packit Service ae04f2
	if (strcmp(helper_name, "putnamedrr") == 0)
Packit Service ae04f2
		cd->putnamedrr = (dns_sdlz_putnamedrr_t *)ptr;
Packit Service ae04f2
	if (strcmp(helper_name, "writeable_zone") == 0)
Packit Service ae04f2
		cd->writeable_zone = (dns_dlz_writeablezone_t *)ptr;
Packit Service ae04f2
}