dlz_filesystem_driver.c revision abff0f462a758383d012887d3a97da4dac0c5a94
/*
* 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 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 INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM 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.
*/
#ifdef DLZ_FILESYSTEM
#include <config.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <isc/platform.h>
#include <dlz/dlz_filesystem_driver.h>
typedef struct config_data {
char *basedir;
int basedirsize;
char *datadir;
int datadirsize;
char *xfrdir;
int xfrdirsize;
int splitcnt;
char separator;
char pathsep;
typedef struct dir_entry dir_entry_t;
struct dir_entry {
char dirpath[ISC_DIR_PATHMAX];
};
/* forward reference */
static void
/*
* Private methods
*/
static isc_boolean_t
unsigned int i;
/* 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 (ISC_FALSE);
/* '..', two dots together is not allowed. */
return (ISC_FALSE);
/* '.' is not allowed as last char */
if (i == len)
return (ISC_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 */
continue;
/* A-Z uppercase is allowed, continue at next char */
continue;
/* a-z lowercase is allowed, continue at next char */
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 (ISC_FALSE);
}
/* everything ok. */
return (ISC_TRUE);
}
static isc_result_t
char *tmpString;
char *tmpPtr;
int i;
return (ISC_R_NOMEMORY);
/*
* don't forget is_safe guarantees '.' will NOT be the
*/
i = 0;
else
break;
break;
}
tmpPtr[0] = '\0';
}
/* handle the "first" label properly */
i=0;
while (tmpPtr[i] != '\0') {
else
break;
break;
}
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
{
char *tmpPath;
int pathsize;
int len;
/* we require a zone & cd parameter */
/* require path to be a pointer to NULL */
/*
* client and host may both be NULL, but they can't both be
* NON-NULL
*/
/* special case for root zone */
/* if the requested zone is "unsafe", return error */
return (ISC_R_FAILURE);
/* if host was passed, verify that it is safe */
return (ISC_R_FAILURE);
/* if client was passed, verify that it is safe */
return (ISC_R_FAILURE);
/* Determine how much memory the split up string will require */
else
/*
* 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.
*/
/* if we are splitting names, we will need extra space. */
/* write error message */
"Filesystem driver unable to "
"allocate memory in create_path().");
goto cleanup_mem;
}
/*
* build path string.
* start out with base directory.
*/
/* add zone name - parsed properly */
if (!isroot) {
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
* authoritative for the domain "domain.com". However we are
* authoritative for the domain "long.domain.com" because the
*/
/* if client is passed append xfr dir, otherwise append data dir */
} else {
}
/* if host not null, add it. */
cd)) != ISC_R_SUCCESS)
goto cleanup_mem;
}
/* return the path we built. */
/* return success */
/* cleanup memory */
/* free tmpPath memory */
/* free tmpPath memory */
return (result);
}
static isc_result_t
{
int astPos;
char *endp;
char *type;
char *ttlStr;
char *data;
char host[ISC_DIR_NAMEMAX];
char *tmpString;
char *tmpPtr;
int ttl;
int i;
int len;
host[0] = '\0';
/* copy base directory name to tmp. */
/* dir->dirname will always have '*' as the last char. */
/* if dir_list != NULL, were are performing a zone xfr */
/* if splitcnt == 0, determine host from path. */
/* handle filesystem's special wildcard "-" */
} else {
/*
* not special wildcard -- normal name
*/
!= NULL)
{
continue;
tmpPtr[0] = '\0';
}
<= ISC_DIR_NAMEMAX)
}
/* set tmp again for use later */
}
} else {
/*
* if splitcnt != 0 determine host from
* ".host" directory entry
*/
if (strncasecmp(".host",
/*
* handle filesystem's special
* wildcard "-"
*/
"-") == 0)
else {
sizeof(host) - 1);
}
break;
}
}
/* reset dir list for use later */
} /* end of else */
}
"Filesystem driver Dir name:"
" '%s' Dir entry: '%s'\n",
/* skip any entries starting with "." */
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.
*/
/* add name to base directory name. */
/* make sure we can stat entry */
/* if entry is a directory */
/*
* if dir list is NOT NULL, add dir to
* dir list
*/
direntry =
sizeof(dir_entry_t));
return (ISC_R_NOMEMORY);
link);
}
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.
*/
continue;
}
} else /* if we cannot stat entry, skip it. */
continue;
"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 */
"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 */
/* replace all cd->separator chars with a space. */
for (i=0; i < len; i++) {
data[i] = ' ';
}
/* convert text to int, make sure it worked right */
"Filesystem driver "
"ttl must be a postive number");
}
/* pass data back to Bind */
else
(char *) host,
/* if error, return error right away */
if (result != ISC_R_SUCCESS)
return (result);
} /* end of while loop */
return (result);
}
/*
* SDLZ interface methods
*/
static isc_result_t
const char *client)
{
char *path;
return (ISC_R_NOTFOUND);
}
goto complete_AXFR;
}
goto complete_AXFR;
}
return (result);
}
static isc_result_t
{
char *basepath;
unsigned int basepathlen;
/* allocate memory for list */
goto complete_allnds;
}
/* initialize list */
return (ISC_R_NOTFOUND);
}
/* remove path separator at end of path so stat works properly */
goto complete_allnds;
}
goto complete_allnds;
}
/* initialize and open directory */
isc_dir_init(&dir);
/* if directory open failed, return error. */
if (result != ISC_R_SUCCESS) {
"Unable to open %s directory to read entries.",
basepath);
goto complete_allnds;
}
/* process the directory */
/* close the directory */
isc_dir_close(&dir);
if (result != ISC_R_SUCCESS)
goto complete_allnds;
/* get first dir entry from list. */
/* if directory open failed, return error. */
if (result != ISC_R_SUCCESS) {
"Unable to open %s "
"directory to read entries.",
basepath);
goto complete_allnds;
}
/* process the directory */
/* close the directory */
isc_dir_close(&dir);
if (result != ISC_R_SUCCESS)
goto complete_allnds;
} /* end while */
/* clean up entries from list. */
} /* end while */
}
return (result);
}
static isc_result_t
{
char *path;
&path) != ISC_R_SUCCESS) {
return (ISC_R_NOTFOUND);
}
"Filesystem driver Findzone() Checking for path: '%s'\n",
path);
goto complete_FZ;
}
goto complete_FZ;
}
return (result);
}
static isc_result_t
{
char *path;
/*
* handle filesystem's special wildcard "-"
*/
else
if ( result != ISC_R_SUCCESS) {
return (ISC_R_NOTFOUND);
}
/* remove path separator at end of path so stat works properly */
"Filesystem driver lookup() Checking for path: '%s'\n",
path);
goto complete_lkup;
}
goto complete_lkup;
}
/* initialize and open directory */
isc_dir_init(&dir);
/* if directory open failed, return error. */
if (result != ISC_R_SUCCESS) {
"Unable to open %s directory to read entries.",
path);
goto complete_lkup;
}
/* process any records in the directory */
/* close the directory */
isc_dir_close(&dir);
return (result);
}
static isc_result_t
{
char *endp;
int len;
char pathsep;
/* we require 5 command line args. */
if (argc != 6) {
"Filesystem driver requires "
"6 command line args.");
return (ISC_R_FAILURE);
}
"Filesystem driver can only "
"accept a single character for separator.");
return (ISC_R_FAILURE);
}
/* verify base dir ends with '/' or '\' */
"Base dir parameter for filesystem driver "
"should end with %s",
"either '/' or '\\' ");
return (ISC_R_FAILURE);
}
/* determine and save path separator for later */
pathsep = '\\';
else
pathsep = '/';
/* allocate memory for our config data */
goto no_mem;
/* zero the memory */
/* get and store our base directory */
goto no_mem;
/* get and store our data sub-dir */
goto no_mem;
/* get and store our zone xfr sub-dir */
goto no_mem;
/* get and store our directory split count */
"Directory split count must be zero (0) "
"or a postive number");
}
/* get and store our separator character */
/* attach config data to memory context */
/* pass back config data */
/* return success */
return (ISC_R_SUCCESS);
/* handle no memory error */
/* if we allocated a config data object clean it up */
/* write error message */
"Filesystem driver unable to "
"allocate memory for config data.");
/* return error */
return (ISC_R_NOMEMORY);
}
static void
{
/*
* free memory for each section of config data that was
* allocated
*/
/* hold memory context to use later */
/* free config data memory */
/* detach memory from context */
}
static dns_sdlzmethods_t dlz_fs_methods = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
/*%
* Wrapper around dns_sdlzregister().
*/
dlz_fs_init(void)
{
/*
* Write debugging message to log
*/
"Registering DLZ filesystem driver.");
if (result != ISC_R_SUCCESS) {
"dns_sdlzregister() failed: %s",
}
return (result);
}
/*%
* Wrapper around dns_sdlzunregister().
*/
void
dlz_fs_clear(void) {
/*
* Write debugging message to log
*/
"Unregistering DLZ filesystem driver.");
}
#endif