|
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 |
}
|