2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 10:10:06 +00:00
bind/contrib/dlz/modules/filesystem/dlz_filesystem_dynamic.c
Ondřej Surý 288f5a4b52 Various little fixes found by coccinelle
The coccinellery repository provides many little semantic patches to fix common
problems in the code.  The number of semantic patches in the coccinellery
repository is high and most of the semantic patches apply only for Linux, so it
doesn't make sense to run them on regular basis as the processing takes a lot of
time.

The list of issue found in BIND 9, by no means complete, includes:

- double assignment to a variable
- `continue` at the end of the loop
- double checks for `NULL`
- useless checks for `NULL` (cannot be `NULL`, because of earlier return)
- using `0` instead of `NULL`
- useless extra condition (`if (foo) return; if (!foo) { ...; }`)
- removing & in front of static functions passed as arguments
2019-10-01 16:48:55 +02:00

976 lines
23 KiB
C

/*
* 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, 2013, 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/.
*/
/*
* This provides the externally loadable filesystem DLZ module, without
* update support
*/
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <sys/stat.h>
#include "dlz_minimal.h"
#include "dlz_list.h"
#include "dir.h"
typedef struct config_data {
char *basedir;
int basedirsize;
char *datadir;
int datadirsize;
char *xfrdir;
int xfrdirsize;
int splitcnt;
char separator;
char pathsep;
/* 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;
} config_data_t;
typedef struct dir_entry dir_entry_t;
struct dir_entry {
char dirpath[DIR_PATHMAX];
DLZ_LINK(dir_entry_t) link;
};
typedef DLZ_LIST(dir_entry_t) dlist_t;
/* forward reference */
static void
b9_add_helper(struct config_data *cd, const char *helper_name, void *ptr);
/*
* Private methods
*/
static bool
is_safe(const char *input) {
unsigned int i;
unsigned int len = strlen(input);
/* check that only allowed characters are in the domain name */
for (i = 0; i < len; i++) {
/* '.' is allowed, but has special requirements */
if (input[i] == '.') {
/* '.' is not allowed as first char */
if (i == 0)
return (false);
/* '..', two dots together is not allowed. */
if (input[i-1] == '.')
return (false);
/* '.' is not allowed as last char */
if (i == len - 1)
return (false);
/* only 1 dot in ok location, continue at next char */
continue;
}
/* '-' is allowed, continue at next char */
if (input[i] == '-')
continue;
/* 0-9 is allowed, continue at next char */
if (input[i] >= '0' && input[i] <= '9')
continue;
/* A-Z uppercase is allowed, continue at next char */
if (input[i] >= 'A' && input[i] <= 'Z')
continue;
/* a-z lowercase is allowed, continue at next char */
if (input[i] >= 'a' && input[i] <= 'z')
continue;
/*
* colon needs to be allowed for IPV6 client
* addresses. Not dangerous in domain names, as not a
* special char.
*/
if (input[i] == ':')
continue;
/*
* '@' needs to be allowed for in zone data. Not
* dangerous in domain names, as not a special char.
*/
if (input[i] == '@')
continue;
/*
* if we reach this point we have encountered a
* disallowed char!
*/
return (false);
}
/* everything ok. */
return (true);
}
static isc_result_t
create_path_helper(char *out, const char *in, config_data_t *cd) {
char *tmpString;
char *tmpPtr;
int i;
tmpString = strdup(in);
if (tmpString == NULL)
return (ISC_R_NOMEMORY);
/*
* don't forget is_safe guarantees '.' will NOT be the
* first/last char
*/
while ((tmpPtr = strrchr(tmpString, '.')) != NULL) {
i = 0;
while (tmpPtr[i+1] != '\0') {
if (cd->splitcnt < 1)
strcat(out, (char *) &tmpPtr[i+1]);
else
strncat(out, (char *) &tmpPtr[i+1],
cd->splitcnt);
strncat(out, (char *) &cd->pathsep, 1);
if (cd->splitcnt == 0)
break;
if (strlen((char *) &tmpPtr[i+1]) <=
(unsigned int) cd->splitcnt)
break;
i += cd->splitcnt;
}
tmpPtr[0] = '\0';
}
/* handle the "first" label properly */
i=0;
tmpPtr = tmpString;
while (tmpPtr[i] != '\0') {
if (cd->splitcnt < 1)
strcat(out, (char *) &tmpPtr[i]);
else
strncat(out, (char *) &tmpPtr[i], cd->splitcnt);
strncat(out, (char *) &cd->pathsep, 1);
if (cd->splitcnt == 0)
break;
if (strlen((char *) &tmpPtr[i]) <=
(unsigned int) cd->splitcnt)
break;
i += cd->splitcnt;
}
free(tmpString);
return (ISC_R_SUCCESS);
}
/*%
* Checks to make sure zone and host are safe. If safe, then
* hashes zone and host strings to build a path. If zone / host
* are not safe an error is returned.
*/
static isc_result_t
create_path(const char *zone, const char *host, const char *client,
config_data_t *cd, char **path)
{
char *tmpPath;
int pathsize;
int len;
isc_result_t result;
bool isroot = false;
/* special case for root zone */
if (strcmp(zone, ".") == 0)
isroot = true;
/* if the requested zone is "unsafe", return error */
if (!isroot && !is_safe(zone))
return (ISC_R_FAILURE);
/* if host was passed, verify that it is safe */
if (host != NULL && !is_safe(host))
return (ISC_R_FAILURE);
/* if client was passed, verify that it is safe */
if (client != NULL && !is_safe(client))
return (ISC_R_FAILURE);
/* Determine how much memory the split up string will require */
if (host != NULL)
len = strlen(zone) + strlen(host);
else if (client != NULL)
len = strlen(zone) + strlen(client);
else
len = strlen(zone);
/*
* even though datadir and xfrdir will never be in the same
* string we only waste a few bytes by allocating for both,
* and then we are safe from buffer overruns.
*/
pathsize = len + cd->basedirsize +
cd->datadirsize + cd->xfrdirsize + 4;
/* if we are splitting names, we will need extra space. */
if (cd->splitcnt > 0)
pathsize += len/cd->splitcnt;
tmpPath = malloc(pathsize * sizeof(char));
if (tmpPath == NULL) {
/* write error message */
cd->log(ISC_LOG_ERROR,
"Filesystem driver unable to "
"allocate memory in create_path().");
result = ISC_R_NOMEMORY;
goto cleanup_mem;
}
/*
* build path string.
* start out with base directory.
*/
strcpy(tmpPath, cd->basedir);
/* add zone name - parsed properly */
if (!isroot) {
result = create_path_helper(tmpPath, zone, cd);
if (result != ISC_R_SUCCESS)
goto cleanup_mem;
}
/*
* When neither client or host is passed we are building a
* path to see if a zone is supported. We require that a zone
* path have the "data dir" directory contained within it so
* that we know this zone is really supported. Otherwise,
* this zone may not really be supported because we are
* supporting a delagated sub zone.
*
* Example:
*
* We are supporting long.domain.com and using a splitcnt of
* 0. the base dir is "/base-dir/" and the data dir is
* "/.datadir" We want to see if we are authoritative for
* domain.com. Path /base-dir/com/domain/.datadir since
* /base-dir/com/domain/.datadir does not exist, we are not
* authoritative for the domain "domain.com". However we are
* authoritative for the domain "long.domain.com" because the
* path /base-dir/com/domain/long/.datadir does exist!
*/
/* if client is passed append xfr dir, otherwise append data dir */
if (client != NULL) {
strcat(tmpPath, cd->xfrdir);
strncat(tmpPath, (char *) &cd->pathsep, 1);
strcat(tmpPath, client);
} else
strcat(tmpPath, cd->datadir);
/* if host not null, add it. */
if (host != NULL) {
strncat(tmpPath, (char *) &cd->pathsep, 1);
result = create_path_helper(tmpPath, host, cd);
if (result != ISC_R_SUCCESS)
goto cleanup_mem;
}
/* return the path we built. */
*path = tmpPath;
/* return success */
result = ISC_R_SUCCESS;
cleanup_mem:
/* cleanup memory */
/* free tmpPath memory */
if (tmpPath != NULL && result != ISC_R_SUCCESS)
free(tmpPath);
return (result);
}
static isc_result_t
process_dir(dir_t *dir, void *passback, config_data_t *cd,
dlist_t *dir_list, unsigned int basedirlen)
{
char tmp[DIR_PATHMAX + DIR_NAMEMAX];
int astPos;
struct stat sb;
isc_result_t result = ISC_R_FAILURE;
char *endp;
char *type;
char *ttlStr;
char *data;
char host[DIR_NAMEMAX];
char *tmpString;
char *tmpPtr;
int ttl;
int i;
int len;
dir_entry_t *direntry;
bool foundHost;
tmp[0] = '\0'; /* set 1st byte to '\0' so strcpy works right. */
host[0] = '\0';
foundHost = false;
/* copy base directory name to tmp. */
strcpy(tmp, dir->dirname);
/* dir->dirname will always have '*' as the last char. */
astPos = strlen(dir->dirname) - 1;
/* if dir_list != NULL, were are performing a zone xfr */
if (dir_list != NULL) {
/* if splitcnt == 0, determine host from path. */
if (cd->splitcnt == 0) {
if (strlen(tmp) - 3 > basedirlen) {
tmp[astPos-1] = '\0';
tmpString = (char *) &tmp[basedirlen+1];
/* handle filesystem's special wildcard "-" */
if (strcmp(tmpString, "-") == 0) {
strcpy(host, "*");
} else {
/*
* not special wildcard -- normal name
*/
while ((tmpPtr = strrchr(tmpString,
cd->pathsep))
!= NULL)
{
if ((strlen(host) +
strlen(tmpPtr + 1) + 2)
> DIR_NAMEMAX)
continue;
strcat(host, tmpPtr + 1);
strcat(host, ".");
tmpPtr[0] = '\0';
}
if ((strlen(host) +
strlen(tmpString) + 1)
<= DIR_NAMEMAX)
strcat(host, tmpString);
}
foundHost = true;
/* set tmp again for use later */
strcpy(tmp, dir->dirname);
}
} else {
/*
* if splitcnt != 0 determine host from
* ".host" directory entry
*/
while (dir_read(dir) == ISC_R_SUCCESS) {
if (strncasecmp(".host",
dir->entry.name, 5) == 0) {
/*
* handle filesystem's special
* wildcard "-"
*/
if (strcmp((char *) &dir->entry.name[6],
"-") == 0)
strcpy(host, "*");
else {
strncpy(host,
(char *) &dir->entry.name[6],
sizeof(host) - 1);
host[255] = '\0';
}
foundHost = true;
break;
}
}
/* reset dir list for use later */
dir_reset(dir);
} /* end of else */
}
while (dir_read(dir) == ISC_R_SUCCESS) {
cd->log(ISC_LOG_DEBUG(1),
"Filesystem driver Dir name:"
" '%s' Dir entry: '%s'\n",
dir->dirname, dir->entry.name);
/* skip any entries starting with "." */
if (dir->entry.name[0] == '.')
continue;
/*
* get rid of '*', set to NULL. Effectively trims
* string from previous loop to base directory only
* while still leaving memory for concat to be
* performed next.
*/
tmp[astPos] = '\0';
/* add name to base directory name. */
strcat(tmp, dir->entry.name);
/* make sure we can stat entry */
if (stat(tmp, &sb) == 0 ) {
/* if entry is a directory */
if ((sb.st_mode & S_IFDIR) != 0) {
/*
* if dir list is NOT NULL, add dir to
* dir list
*/
if (dir_list != NULL) {
direntry = malloc(sizeof(dir_entry_t));
if (direntry == NULL)
return (ISC_R_NOMEMORY);
strcpy(direntry->dirpath, tmp);
DLZ_LINK_INIT(direntry, link);
DLZ_LIST_APPEND(*dir_list, direntry,
link);
result = ISC_R_SUCCESS;
}
continue;
/*
* if entry is a file be sure we do
* not add entry to DNS results if we
* are performing a zone xfr and we
* could not find a host entry.
*/
} else if (dir_list != NULL &&
foundHost == false) {
continue;
}
} else /* if we cannot stat entry, skip it. */
continue;
type = dir->entry.name;
ttlStr = strchr(type, cd->separator);
if (ttlStr == NULL) {
cd->log(ISC_LOG_ERROR,
"Filesystem driver: "
"%s could not be parsed properly", tmp);
return (ISC_R_FAILURE);
}
/* replace separator char with NULL to split string */
ttlStr[0] = '\0';
/* start string after NULL of previous string */
ttlStr = (char *) &ttlStr[1];
data = strchr(ttlStr, cd->separator);
if (data == NULL) {
cd->log(ISC_LOG_ERROR,
"Filesystem driver: "
"%s could not be parsed properly", tmp);
return (ISC_R_FAILURE);
}
/* replace separator char with NULL to split string */
data[0] = '\0';
/* start string after NULL of previous string */
data = (char *) &data[1];
/* replace all cd->separator chars with a space. */
len = strlen(data);
for (i=0; i < len; i++) {
if (data[i] == cd->separator)
data[i] = ' ';
}
/* convert text to int, make sure it worked right */
ttl = strtol(ttlStr, &endp, 10);
if (*endp != '\0' || ttl < 0)
cd->log(ISC_LOG_ERROR,
"Filesystem driver "
"ttl must be a postive number");
/* pass data back to Bind */
if (dir_list == NULL)
result = cd->putrr((dns_sdlzlookup_t *) passback,
type, ttl, data);
else
result = cd->putnamedrr((dns_sdlzallnodes_t *) passback,
(char *) host,
type, ttl, data);
/* if error, return error right away */
if (result != ISC_R_SUCCESS)
return (result);
} /* end of while loop */
return (result);
}
/*
* DLZ methods
*/
isc_result_t
dlz_allowzonexfr(void *dbdata, const char *name, const char *client) {
isc_result_t result;
char *path;
struct stat sb;
config_data_t *cd;
path = NULL;
cd = (config_data_t *) dbdata;
if (create_path(name, NULL, client, cd, &path) != ISC_R_SUCCESS) {
return (ISC_R_NOTFOUND);
}
if (stat(path, &sb) != 0) {
result = ISC_R_NOTFOUND;
goto complete_AXFR;
}
if ((sb.st_mode & S_IFREG) != 0) {
result = ISC_R_SUCCESS;
goto complete_AXFR;
}
result = ISC_R_NOTFOUND;
complete_AXFR:
free(path);
return (result);
}
isc_result_t
dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes) {
isc_result_t result;
dlist_t *dir_list;
config_data_t *cd = (config_data_t *) dbdata;
char *basepath;
unsigned int basepathlen;
struct stat sb;
dir_t dir;
dir_entry_t *dir_entry;
dir_entry_t *next_de;
basepath = NULL;
/* allocate memory for list */
dir_list = malloc(sizeof(dlist_t));
if (dir_list == NULL) {
result = ISC_R_NOTFOUND;
goto complete_allnds;
}
/* initialize list */
DLZ_LIST_INIT(*dir_list);
if (create_path(zone, NULL, NULL, cd, &basepath) != ISC_R_SUCCESS) {
result = ISC_R_NOTFOUND;
goto complete_allnds;
}
/* remove path separator at end of path so stat works properly */
basepathlen = strlen(basepath);
if (stat(basepath, &sb) != 0) {
result = ISC_R_NOTFOUND;
goto complete_allnds;
}
if ((sb.st_mode & S_IFDIR) == 0) {
result = ISC_R_NOTFOUND;
goto complete_allnds;
}
/* initialize and open directory */
dir_init(&dir);
result = dir_open(&dir, basepath);
/* if directory open failed, return error. */
if (result != ISC_R_SUCCESS) {
cd->log(ISC_LOG_ERROR,
"Unable to open %s directory to read entries.",
basepath);
result = ISC_R_FAILURE;
goto complete_allnds;
}
/* process the directory */
result = process_dir(&dir, allnodes, cd, dir_list, basepathlen);
/* close the directory */
dir_close(&dir);
if (result != ISC_R_SUCCESS)
goto complete_allnds;
/* get first dir entry from list. */
dir_entry = DLZ_LIST_HEAD(*dir_list);
while (dir_entry != NULL) {
result = dir_open(&dir, dir_entry->dirpath);
/* if directory open failed, return error. */
if (result != ISC_R_SUCCESS) {
cd->log(ISC_LOG_ERROR,
"Unable to open %s "
"directory to read entries.", basepath);
result = ISC_R_FAILURE;
goto complete_allnds;
}
/* process the directory */
result = process_dir(&dir, allnodes, cd, dir_list, basepathlen);
/* close the directory */
dir_close(&dir);
if (result != ISC_R_SUCCESS)
goto complete_allnds;
dir_entry = DLZ_LIST_NEXT(dir_entry, link);
} /* end while */
complete_allnds:
if (dir_list != NULL) {
/* clean up entries from list. */
dir_entry = DLZ_LIST_HEAD(*dir_list);
while (dir_entry != NULL) {
next_de = DLZ_LIST_NEXT(dir_entry, link);
free(dir_entry);
dir_entry = next_de;
} /* end while */
free(dir_list);
}
if (basepath != NULL)
free(basepath);
return (result);
}
#if DLZ_DLOPEN_VERSION < 3
isc_result_t
dlz_findzonedb(void *dbdata, const char *name)
#else
isc_result_t
dlz_findzonedb(void *dbdata, const char *name,
dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo)
#endif
{
isc_result_t result;
config_data_t *cd = (config_data_t *) dbdata;
char *path;
struct stat sb;
path = NULL;
#if DLZ_DLOPEN_VERSION >= 3
UNUSED(methods);
UNUSED(clientinfo);
#endif
if (create_path(name, NULL, NULL, cd, &path) != ISC_R_SUCCESS)
return (ISC_R_NOTFOUND);
cd->log(ISC_LOG_DEBUG(1),
"Filesystem driver Findzone() Checking for path: '%s'\n", path);
if (stat(path, &sb) != 0) {
result = ISC_R_NOTFOUND;
goto complete_FZ;
}
if ((sb.st_mode & S_IFDIR) != 0) {
result = ISC_R_SUCCESS;
goto complete_FZ;
}
result = ISC_R_NOTFOUND;
complete_FZ:
free(path);
return (result);
}
#if DLZ_DLOPEN_VERSION == 1
isc_result_t
dlz_lookup(const char *zone, const char *name,
void *dbdata, dns_sdlzlookup_t *lookup)
#else
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
{
isc_result_t result = ISC_R_NOTFOUND;
config_data_t *cd = (config_data_t *) dbdata;
char *path;
struct stat sb;
dir_t dir;
path = NULL;
UNUSED(lookup);
#if DLZ_DLOPEN_VERSION >= 2
UNUSED(methods);
UNUSED(clientinfo);
#endif
if (strcmp(name, "*") == 0)
/*
* handle filesystem's special wildcard "-"
*/
result = create_path(zone, "-", NULL, cd, &path);
else
result = create_path(zone, name, NULL, cd, &path);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOTFOUND);
/* remove path separator at end of path so stat works properly */
path[strlen(path)-1] = '\0';
cd->log(ISC_LOG_DEBUG(1),
"Filesystem driver lookup() Checking for path: '%s'\n", path);
if (stat(path, &sb) != 0) {
result = ISC_R_NOTFOUND;
goto complete_lkup;
}
if ((sb.st_mode & S_IFDIR) == 0) {
result = ISC_R_NOTFOUND;
goto complete_lkup;
}
/* initialize and open directory */
dir_init(&dir);
result = dir_open(&dir, path);
/* if directory open failed, return error. */
if (result != ISC_R_SUCCESS) {
cd->log(ISC_LOG_ERROR,
"Unable to open %s directory to read entries.", path);
result = ISC_R_FAILURE;
goto complete_lkup;
}
/* process any records in the directory */
result = process_dir(&dir, lookup, cd, NULL, 0);
/* close the directory */
dir_close(&dir);
complete_lkup:
free(path);
return (result);
}
isc_result_t
dlz_create(const char *dlzname, unsigned int argc, char *argv[],
void **dbdata, ...)
{
isc_result_t result = ISC_R_NOMEMORY;
config_data_t *cd;
char *endp;
int len;
char pathsep;
const char *helper_name;
va_list ap;
UNUSED(dlzname);
/* allocate memory for our config data and helper functions */
cd = calloc(1, sizeof(config_data_t));
if (cd == NULL)
goto no_mem;
/* zero the memory */
memset(cd, 0, sizeof(config_data_t));
/* Fill in the helper functions */
va_start(ap, dbdata);
while ((helper_name = va_arg(ap, const char*)) != NULL)
b9_add_helper(cd, helper_name, va_arg(ap, void*));
va_end(ap);
/* we require 5 command line args. */
if (argc != 6) {
cd->log(ISC_LOG_ERROR,
"Filesystem driver requires "
"6 command line args.");
result = ISC_R_FAILURE;
goto free_cd;
}
if (strlen(argv[5]) > 1) {
cd->log(ISC_LOG_ERROR,
"Filesystem driver can only "
"accept a single character for separator.");
result = ISC_R_FAILURE;
goto free_cd;
}
/* verify base dir ends with '/' or '\' */
len = strlen(argv[1]);
if (argv[1][len-1] != '\\' && argv[1][len-1] != '/') {
cd->log(ISC_LOG_ERROR,
"Base dir parameter for filesystem driver "
"should end with %s",
"either '/' or '\\' ");
result = ISC_R_FAILURE;
goto free_cd;
}
/* determine and save path separator for later */
if (argv[1][len-1] == '\\')
pathsep = '\\';
else
pathsep = '/';
cd->pathsep = pathsep;
/* get and store our base directory */
cd->basedir = strdup(argv[1]);
if (cd->basedir == NULL)
goto no_mem;
cd->basedirsize = strlen(cd->basedir);
/* get and store our data sub-dir */
cd->datadir = strdup(argv[2]);
if (cd->datadir == NULL)
goto no_mem;
cd->datadirsize = strlen(cd->datadir);
/* get and store our zone xfr sub-dir */
cd->xfrdir = strdup(argv[3]);
if (cd->xfrdir == NULL)
goto no_mem;
cd->xfrdirsize = strlen(cd->xfrdir);
/* get and store our directory split count */
cd->splitcnt = strtol(argv[4], &endp, 10);
if (*endp != '\0' || cd->splitcnt < 0)
cd->log(ISC_LOG_ERROR,
"Directory split count must be zero (0) "
"or a postive number");
/* get and store our separator character */
cd->separator = *argv[5];
/* pass back config data */
*dbdata = cd;
/* return success */
return (ISC_R_SUCCESS);
/* handle no memory error */
no_mem:
/* write error message */
if (cd != NULL && cd->log != NULL)
cd->log(ISC_LOG_ERROR,
"filesystem_dynamic: Filesystem driver unable to "
"allocate memory for config data.");
free_cd:
/* if we allocated a config data object clean it up */
if (cd != NULL)
dlz_destroy(cd);
/* return error */
return (result);
}
void
dlz_destroy(void *dbdata) {
config_data_t *cd;
cd = (config_data_t *) dbdata;
/*
* free memory for each section of config data that was
* allocated
*/
if (cd->basedir != NULL)
free(cd->basedir);
if (cd->datadir != NULL)
free(cd->datadir);
if (cd->xfrdir != NULL)
free(cd->xfrdir);
/* free config data memory */
free(cd);
}
/*
* 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 config_data *cd, const char *helper_name, void *ptr) {
if (strcmp(helper_name, "log") == 0)
cd->log = (log_t *)ptr;
if (strcmp(helper_name, "putrr") == 0)
cd->putrr = (dns_sdlz_putrr_t *)ptr;
if (strcmp(helper_name, "putnamedrr") == 0)
cd->putnamedrr = (dns_sdlz_putnamedrr_t *)ptr;
if (strcmp(helper_name, "writeable_zone") == 0)
cd->writeable_zone = (dns_dlz_writeablezone_t *)ptr;
}