mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
[master] DLZ modules: filesystem, ldap, wildcard
3523. [contrib] Ported filesystem and ldap DLZ drivers to dynamically-loadable modules, and added the "wildcard" module based on a contribution from Vadim Goncharov <vgoncharov@nic.ru>. [RT #23569]
This commit is contained in:
parent
21a7fde6ba
commit
72c86c105a
26 changed files with 5026 additions and 653 deletions
5
CHANGES
5
CHANGES
|
|
@ -1,3 +1,8 @@
|
|||
3523. [contrib] Ported filesystem and ldap DLZ drivers to
|
||||
dynamically-loadable modules, and added the
|
||||
"wildcard" module based on a contribution from
|
||||
Vadim Goncharov <vgoncharov@nic.ru>. [RT #23569]
|
||||
|
||||
3522. [bug] DLZ lookups could fail to return SERVFAIL when
|
||||
they ought to. [RT #32685]
|
||||
|
||||
|
|
|
|||
|
|
@ -602,6 +602,7 @@ dlz_dlopen_init(isc_mem_t *mctx) {
|
|||
|
||||
result = dns_sdlzregister("dlopen", &dlz_dlopen_methods, NULL,
|
||||
DNS_SDLZFLAG_RELATIVEOWNER |
|
||||
DNS_SDLZFLAG_RELATIVERDATA |
|
||||
DNS_SDLZFLAG_THREADSAFE,
|
||||
mctx, &dlz_dlopen);
|
||||
|
||||
|
|
|
|||
|
|
@ -580,6 +580,7 @@ dlz_dlopen_init(isc_mem_t *mctx) {
|
|||
|
||||
result = dns_sdlzregister("dlopen", &dlz_dlopen_methods, NULL,
|
||||
DNS_SDLZFLAG_RELATIVEOWNER |
|
||||
DNS_SDLZFLAG_RELATIVERDATA |
|
||||
DNS_SDLZFLAG_THREADSAFE,
|
||||
mctx, &dlz_dlopen);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
prefix = /usr
|
||||
libdir = $(prefix)/lib/bind9
|
||||
|
||||
CFLAGS=-fPIC -g
|
||||
CFLAGS=-fPIC -g -I../include
|
||||
BDB_LIBS=-ldb
|
||||
|
||||
all: dlz_bdbhpt_dynamic.so
|
||||
|
||||
dlz_bdbhpt_dynamic.so:
|
||||
dlz_bdbhpt_dynamic.so: dlz_bdbhpt_dynamic.c
|
||||
$(CC) $(CFLAGS) -shared -o dlz_bdbhpt_dynamic.so \
|
||||
dlz_bdbhpt_dynamic.c $(BDB_LIBS)
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
461
contrib/dlz/modules/common/dlz_dbi.c
Normal file
461
contrib/dlz/modules/common/dlz_dbi.c
Normal file
|
|
@ -0,0 +1,461 @@
|
|||
/*
|
||||
* 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) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (C) 1999-2001 Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include <dlz_minimal.h>
|
||||
#include <dlz_list.h>
|
||||
#include <dlz_dbi.h>
|
||||
#include <dlz_pthread.h>
|
||||
|
||||
/*%
|
||||
* properly destroys a querylist by de-allocating the
|
||||
* memory for each query segment, and then the list itself
|
||||
*/
|
||||
|
||||
void
|
||||
destroy_querylist(query_list_t **querylist) {
|
||||
query_segment_t *tseg = NULL;
|
||||
query_segment_t *nseg = NULL;
|
||||
|
||||
/* if query list is null, nothing to do */
|
||||
if (*querylist == NULL)
|
||||
return;
|
||||
|
||||
/* start at the top of the list */
|
||||
nseg = DLZ_LIST_HEAD(**querylist);
|
||||
while (nseg != NULL) { /* loop, until end of list */
|
||||
tseg = nseg;
|
||||
/*
|
||||
* free the query segment's text string but only if it
|
||||
* was really a query segment, and not a pointer to
|
||||
* %zone%, or %record%, or %client%
|
||||
*/
|
||||
if (tseg->cmd != NULL && tseg->direct == ISC_TRUE)
|
||||
free(tseg->cmd);
|
||||
/* get the next query segment, before we destroy this one. */
|
||||
nseg = DLZ_LIST_NEXT(nseg, link);
|
||||
/* deallocate this query segment. */
|
||||
free(tseg);
|
||||
}
|
||||
/* deallocate the query segment list */
|
||||
free(*querylist);
|
||||
}
|
||||
|
||||
/*% constructs a query list by parsing a string into query segments */
|
||||
isc_result_t
|
||||
build_querylist(const char *query_str, char **zone, char **record,
|
||||
char **client, query_list_t **querylist, unsigned int flags,
|
||||
log_t log)
|
||||
{
|
||||
isc_result_t result;
|
||||
isc_boolean_t foundzone = ISC_FALSE;
|
||||
isc_boolean_t foundrecord = ISC_FALSE;
|
||||
isc_boolean_t foundclient = ISC_FALSE;
|
||||
char *temp_str = NULL;
|
||||
char *right_str = NULL;
|
||||
query_list_t *tql;
|
||||
query_segment_t *tseg = NULL;
|
||||
|
||||
/* if query string is null, or zero length */
|
||||
if (query_str == NULL || strlen(query_str) < 1) {
|
||||
if ((flags & REQUIRE_QUERY) == 0)
|
||||
/* we don't need it were ok. */
|
||||
return (ISC_R_SUCCESS);
|
||||
else
|
||||
/* we did need it, PROBLEM!!! */
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
/* allocate memory for query list */
|
||||
tql = calloc(1, sizeof(query_list_t));
|
||||
/* couldn't allocate memory. Problem!! */
|
||||
if (tql == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
/* initialize the query segment list */
|
||||
DLZ_LIST_INIT(*tql);
|
||||
|
||||
/* make a copy of query_str so we can chop it up */
|
||||
temp_str = right_str = strdup(query_str);
|
||||
/* couldn't make a copy, problem!! */
|
||||
if (right_str == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* loop through the string and chop it up */
|
||||
while (right_str != NULL) {
|
||||
/* allocate memory for tseg */
|
||||
tseg = calloc(1, sizeof(query_segment_t));
|
||||
if (tseg == NULL) { /* no memory, clean everything up. */
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
tseg->cmd = NULL;
|
||||
tseg->direct = ISC_FALSE;
|
||||
/* initialize the query segment link */
|
||||
DLZ_LINK_INIT(tseg, link);
|
||||
/* append the query segment to the list */
|
||||
DLZ_LIST_APPEND(*tql, tseg, link);
|
||||
|
||||
/*
|
||||
* split string at the first "$". set query segment to
|
||||
* left portion
|
||||
*/
|
||||
tseg->cmd = strdup(strsep(&right_str, "$"));
|
||||
if (tseg->cmd == NULL) {
|
||||
/* no memory, clean everything up. */
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* tseg->cmd points directly to a string. */
|
||||
tseg->direct = ISC_TRUE;
|
||||
tseg->strlen = strlen(tseg->cmd);
|
||||
|
||||
/* check if we encountered "$zone$" token */
|
||||
if (strcasecmp(tseg->cmd, "zone") == 0) {
|
||||
/*
|
||||
* we don't really need, or want the "zone"
|
||||
* text, so get rid of it.
|
||||
*/
|
||||
free(tseg->cmd);
|
||||
/* set tseg->cmd to in-direct zone string */
|
||||
tseg->cmd = (char**) zone;
|
||||
tseg->strlen = 0;
|
||||
/* tseg->cmd points in-directly to a string */
|
||||
tseg->direct = ISC_FALSE;
|
||||
foundzone = ISC_TRUE;
|
||||
/* check if we encountered "$record$" token */
|
||||
} else if (strcasecmp(tseg->cmd, "record") == 0) {
|
||||
/*
|
||||
* we don't really need, or want the "record"
|
||||
* text, so get rid of it.
|
||||
*/
|
||||
free(tseg->cmd);
|
||||
/* set tseg->cmd to in-direct record string */
|
||||
tseg->cmd = (char**) record;
|
||||
tseg->strlen = 0;
|
||||
/* tseg->cmd points in-directly poinsts to a string */
|
||||
tseg->direct = ISC_FALSE;
|
||||
foundrecord = ISC_TRUE;
|
||||
/* check if we encountered "$client$" token */
|
||||
} else if (strcasecmp(tseg->cmd, "client") == 0) {
|
||||
/*
|
||||
* we don't really need, or want the "client"
|
||||
* text, so get rid of it.
|
||||
*/
|
||||
free(tseg->cmd);
|
||||
/* set tseg->cmd to in-direct record string */
|
||||
tseg->cmd = (char**) client;
|
||||
tseg->strlen = 0;
|
||||
/* tseg->cmd points in-directly poinsts to a string */
|
||||
tseg->direct = ISC_FALSE;
|
||||
foundclient = ISC_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* we don't need temp_str any more */
|
||||
free(temp_str);
|
||||
/*
|
||||
* add checks later to verify zone and record are found if
|
||||
* necessary.
|
||||
*/
|
||||
|
||||
/* if this query requires %client%, make sure we found it */
|
||||
if (((flags & REQUIRE_CLIENT) != 0) && (!foundclient) ) {
|
||||
/* Write error message to log */
|
||||
if (log != NULL)
|
||||
log(ISC_LOG_ERROR,
|
||||
"Required token $client$ not found.");
|
||||
result = ISC_R_FAILURE;
|
||||
goto flag_fail;
|
||||
}
|
||||
|
||||
/* if this query requires %record%, make sure we found it */
|
||||
if (((flags & REQUIRE_RECORD) != 0) && (!foundrecord) ) {
|
||||
/* Write error message to log */
|
||||
if (log != NULL)
|
||||
log(ISC_LOG_ERROR,
|
||||
"Required token $record$ not found.");
|
||||
result = ISC_R_FAILURE;
|
||||
goto flag_fail;
|
||||
}
|
||||
|
||||
/* if this query requires %zone%, make sure we found it */
|
||||
if (((flags & REQUIRE_ZONE) != 0) && (!foundzone) ) {
|
||||
/* Write error message to log */
|
||||
if (log != NULL)
|
||||
log(ISC_LOG_ERROR, "Required token $zone$ not found.");
|
||||
result = ISC_R_FAILURE;
|
||||
goto flag_fail;
|
||||
}
|
||||
|
||||
/* pass back the query list */
|
||||
*querylist = (query_list_t *) tql;
|
||||
|
||||
/* return success */
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup:
|
||||
/* get rid of temp_str */
|
||||
if (temp_str != NULL)
|
||||
free(temp_str);
|
||||
|
||||
flag_fail:
|
||||
/* get rid of what was build of the query list */
|
||||
if (tql != NULL)
|
||||
destroy_querylist(&tql);
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*%
|
||||
* build a query string from query segments, and dynamic segments
|
||||
* dynamic segments replace where the tokens %zone%, %record%, %client%
|
||||
* used to be in our queries from named.conf
|
||||
*/
|
||||
char *
|
||||
build_querystring(query_list_t *querylist) {
|
||||
query_segment_t *tseg = NULL;
|
||||
unsigned int length = 0;
|
||||
char *qs = NULL;
|
||||
|
||||
/* start at the top of the list */
|
||||
tseg = DLZ_LIST_HEAD(*querylist);
|
||||
while (tseg != NULL) {
|
||||
/*
|
||||
* if this is a query segment, use the
|
||||
* precalculated string length
|
||||
*/
|
||||
if (tseg->direct == ISC_TRUE)
|
||||
length += tseg->strlen;
|
||||
else /* calculate string length for dynamic segments. */
|
||||
length += strlen(* (char**) tseg->cmd);
|
||||
/* get the next segment */
|
||||
tseg = DLZ_LIST_NEXT(tseg, link);
|
||||
}
|
||||
|
||||
/* allocate memory for the string */
|
||||
qs = malloc(length + 1);
|
||||
/* couldn't allocate memory, We need more ram! */
|
||||
if (qs == NULL)
|
||||
return (NULL);
|
||||
|
||||
*qs = 0;
|
||||
/* start at the top of the list again */
|
||||
tseg = DLZ_LIST_HEAD(*querylist);
|
||||
while (tseg != NULL) {
|
||||
if (tseg->direct == ISC_TRUE)
|
||||
/* query segments */
|
||||
strcat(qs, tseg->cmd);
|
||||
else
|
||||
/* dynamic segments */
|
||||
strcat(qs, * (char**) tseg->cmd);
|
||||
/* get the next segment */
|
||||
tseg = DLZ_LIST_NEXT(tseg, link);
|
||||
}
|
||||
|
||||
return (qs);
|
||||
}
|
||||
|
||||
/*% constructs a dbinstance (DBI) */
|
||||
isc_result_t
|
||||
build_dbinstance(const char *allnodes_str, const char *allowxfr_str,
|
||||
const char *authority_str, const char *findzone_str,
|
||||
const char *lookup_str, const char *countzone_str,
|
||||
dbinstance_t **dbi, log_t log)
|
||||
{
|
||||
|
||||
isc_result_t result;
|
||||
dbinstance_t *db = NULL;
|
||||
int err;
|
||||
|
||||
/* allocate and zero memory for driver structure */
|
||||
db = calloc(1, sizeof(dbinstance_t));
|
||||
if (db == NULL) {
|
||||
if (log != NULL)
|
||||
log(ISC_LOG_ERROR,
|
||||
"Could not allocate memory for "
|
||||
"database instance object.");
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
memset(db, 0, sizeof(dbinstance_t));
|
||||
db->dbconn = NULL;
|
||||
db->client = NULL;
|
||||
db->record = NULL;
|
||||
db->zone = NULL;
|
||||
db->query_buf = NULL;
|
||||
db->allnodes_q = NULL;
|
||||
db->allowxfr_q = NULL;
|
||||
db->authority_q = NULL;
|
||||
db->findzone_q = NULL;
|
||||
db->countzone_q = NULL;
|
||||
db->lookup_q = NULL;
|
||||
|
||||
/* initialize the reference count mutex */
|
||||
err = dlz_mutex_init(&db->lock, NULL);
|
||||
if (err == ENOMEM) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto cleanup;
|
||||
} else if (err != 0) {
|
||||
result = ISC_R_UNEXPECTED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* build the all nodes query list */
|
||||
result = build_querylist(allnodes_str, &db->zone, &db->record,
|
||||
&db->client, &db->allnodes_q,
|
||||
REQUIRE_ZONE, log);
|
||||
/* if unsuccessful, log err msg and cleanup */
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (log != NULL)
|
||||
log(ISC_LOG_ERROR,
|
||||
"Could not build all nodes query list");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* build the allow zone transfer query list */
|
||||
result = build_querylist(allowxfr_str, &db->zone, &db->record,
|
||||
&db->client, &db->allowxfr_q,
|
||||
REQUIRE_ZONE | REQUIRE_CLIENT,
|
||||
log);
|
||||
/* if unsuccessful, log err msg and cleanup */
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (log != NULL)
|
||||
log(ISC_LOG_ERROR,
|
||||
"Could not build allow xfr query list");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* build the authority query, query list */
|
||||
result = build_querylist(authority_str, &db->zone, &db->record,
|
||||
&db->client, &db->authority_q,
|
||||
REQUIRE_ZONE, log);
|
||||
/* if unsuccessful, log err msg and cleanup */
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (log != NULL)
|
||||
log(ISC_LOG_ERROR,
|
||||
"Could not build authority query list");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* build findzone query, query list */
|
||||
result = build_querylist(findzone_str, &db->zone, &db->record,
|
||||
&db->client, &db->findzone_q,
|
||||
REQUIRE_ZONE, log);
|
||||
/* if unsuccessful, log err msg and cleanup */
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (log != NULL)
|
||||
log(ISC_LOG_ERROR,
|
||||
"Could not build find zone query list");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* build countzone query, query list */
|
||||
result = build_querylist(countzone_str, &db->zone, &db->record,
|
||||
&db->client, &db->countzone_q,
|
||||
REQUIRE_ZONE, log);
|
||||
/* if unsuccessful, log err msg and cleanup */
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (log != NULL)
|
||||
log(ISC_LOG_ERROR,
|
||||
"Could not build count zone query list");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* build lookup query, query list */
|
||||
result = build_querylist(lookup_str, &db->zone, &db->record,
|
||||
&db->client, &db->lookup_q,
|
||||
REQUIRE_RECORD, log);
|
||||
/* if unsuccessful, log err msg and cleanup */
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (log != NULL)
|
||||
log(ISC_LOG_ERROR,
|
||||
"Could not build lookup query list");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* pass back the db instance */
|
||||
*dbi = (dbinstance_t *) db;
|
||||
|
||||
/* return success */
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup:
|
||||
/* destroy whatever was build of the db instance */
|
||||
destroy_dbinstance(db);
|
||||
/* return failure */
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
void
|
||||
destroy_dbinstance(dbinstance_t *dbi) {
|
||||
/* destroy any query lists we created */
|
||||
destroy_querylist(&dbi->allnodes_q);
|
||||
destroy_querylist(&dbi->allowxfr_q);
|
||||
destroy_querylist(&dbi->authority_q);
|
||||
destroy_querylist(&dbi->findzone_q);
|
||||
destroy_querylist(&dbi->countzone_q);
|
||||
destroy_querylist(&dbi->lookup_q);
|
||||
|
||||
/* get rid of the mutex */
|
||||
(void) dlz_mutex_destroy(&dbi->lock);
|
||||
|
||||
/* return, and detach the memory */
|
||||
free(dbi);
|
||||
}
|
||||
20
contrib/dlz/modules/filesystem/Makefile
Normal file
20
contrib/dlz/modules/filesystem/Makefile
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
prefix = /usr
|
||||
libdir = $(prefix)/lib/bind9
|
||||
|
||||
CFLAGS=-fPIC -g -I../include
|
||||
|
||||
all: dlz_filesystem_dynamic.so
|
||||
|
||||
dir.o: dir.c
|
||||
$(CC) $(CFLAGS) -c dir.c
|
||||
|
||||
dlz_filesystem_dynamic.so: dlz_filesystem_dynamic.c dir.o
|
||||
$(CC) $(CFLAGS) -shared -o dlz_filesystem_dynamic.so \
|
||||
dlz_filesystem_dynamic.c dir.o
|
||||
|
||||
clean:
|
||||
rm -f dlz_filesystem_dynamic.so *.o
|
||||
|
||||
install: dlz_filesystem_dynamic.so
|
||||
mkdir -p $(DESTDIR)$(libdir)
|
||||
install dlz_filesystem_dynamic.so $(DESTDIR)$(libdir)
|
||||
116
contrib/dlz/modules/filesystem/dir.c
Normal file
116
contrib/dlz/modules/filesystem/dir.c
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dlz_minimal.h"
|
||||
#include "dir.h"
|
||||
|
||||
void
|
||||
dir_init(dir_t *dir) {
|
||||
dir->entry.name[0] = '\0';
|
||||
dir->entry.length = 0;
|
||||
|
||||
dir->handle = NULL;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dir_open(dir_t *dir, const char *dirname) {
|
||||
char *p;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
if (strlen(dirname) + 3 > sizeof(dir->dirname))
|
||||
return (ISC_R_NOSPACE);
|
||||
strcpy(dir->dirname, dirname);
|
||||
|
||||
p = dir->dirname + strlen(dir->dirname);
|
||||
if (dir->dirname < p && *(p - 1) != '/')
|
||||
*p++ = '/';
|
||||
*p++ = '*';
|
||||
*p = '\0';
|
||||
|
||||
dir->handle = opendir(dirname);
|
||||
if (dir->handle == NULL) {
|
||||
switch (errno) {
|
||||
case ENOTDIR:
|
||||
case ELOOP:
|
||||
case EINVAL:
|
||||
case ENAMETOOLONG:
|
||||
case EBADF:
|
||||
result = ISC_R_INVALIDFILE;
|
||||
case ENOENT:
|
||||
result = ISC_R_FILENOTFOUND;
|
||||
case EACCES:
|
||||
case EPERM:
|
||||
result = ISC_R_NOPERM;
|
||||
case ENOMEM:
|
||||
result = ISC_R_NOMEMORY;
|
||||
default:
|
||||
result = ISC_R_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Return previously retrieved file or get next one.
|
||||
|
||||
* Unix's dirent has
|
||||
* separate open and read functions, but the Win32 and DOS interfaces open
|
||||
* the dir stream and reads the first file in one operation.
|
||||
*/
|
||||
isc_result_t
|
||||
dir_read(dir_t *dir) {
|
||||
struct dirent *entry;
|
||||
|
||||
entry = readdir(dir->handle);
|
||||
if (entry == NULL)
|
||||
return (ISC_R_NOMORE);
|
||||
|
||||
if (sizeof(dir->entry.name) <= strlen(entry->d_name))
|
||||
return (ISC_R_UNEXPECTED);
|
||||
|
||||
strcpy(dir->entry.name, entry->d_name);
|
||||
|
||||
dir->entry.length = strlen(entry->d_name);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Close directory stream.
|
||||
*/
|
||||
void
|
||||
dir_close(dir_t *dir) {
|
||||
(void)closedir(dir->handle);
|
||||
dir->handle = NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Reposition directory stream at start.
|
||||
*/
|
||||
isc_result_t
|
||||
dir_reset(dir_t *dir) {
|
||||
rewinddir(dir->handle);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
47
contrib/dlz/modules/filesystem/dir.h
Normal file
47
contrib/dlz/modules/filesystem/dir.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#define DIR_NAMEMAX 256
|
||||
#define DIR_PATHMAX 1024
|
||||
|
||||
typedef struct direntry {
|
||||
char name[DIR_NAMEMAX];
|
||||
unsigned int length;
|
||||
} direntry_t;
|
||||
|
||||
typedef struct dir {
|
||||
char dirname[DIR_PATHMAX];
|
||||
direntry_t entry;
|
||||
DIR * handle;
|
||||
} dir_t;
|
||||
|
||||
void
|
||||
dir_init(dir_t *dir);
|
||||
|
||||
isc_result_t
|
||||
dir_open(dir_t *dir, const char *dirname);
|
||||
|
||||
isc_result_t
|
||||
dir_read(dir_t *dir);
|
||||
|
||||
isc_result_t
|
||||
dir_reset(dir_t *dir);
|
||||
|
||||
void
|
||||
dir_close(dir_t *dir);
|
||||
979
contrib/dlz/modules/filesystem/dlz_filesystem_dynamic.c
Normal file
979
contrib/dlz/modules/filesystem/dlz_filesystem_dynamic.c
Normal file
|
|
@ -0,0 +1,979 @@
|
|||
/*
|
||||
* 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) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (C) 1999-2001 Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This provides the externally loadable filesystem DLZ module, without
|
||||
* update support
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.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 isc_boolean_t
|
||||
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 (ISC_FALSE);
|
||||
/* '..', two dots together is not allowed. */
|
||||
else if (input[i-1] == '.')
|
||||
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 */
|
||||
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 (ISC_FALSE);
|
||||
}
|
||||
/* everything ok. */
|
||||
return (ISC_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;
|
||||
isc_boolean_t isroot = ISC_FALSE;
|
||||
|
||||
/* special case for root zone */
|
||||
if (strcmp(zone, ".") == 0)
|
||||
isroot = ISC_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;
|
||||
isc_boolean_t foundHost;
|
||||
|
||||
tmp[0] = '\0'; /* set 1st byte to '\0' so strcpy works right. */
|
||||
host[0] = '\0';
|
||||
foundHost = ISC_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 = ISC_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 = ISC_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 == ISC_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;
|
||||
dir_list = 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) {
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
|
||||
/* 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, ...)
|
||||
{
|
||||
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.");
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (strlen(argv[5]) > 1) {
|
||||
cd->log(ISC_LOG_ERROR,
|
||||
"Filesystem driver can only "
|
||||
"accept a single character for separator.");
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
/* 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 '\\' ");
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
/* 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.");
|
||||
|
||||
/* if we allocated a config data object clean it up */
|
||||
if (cd != NULL)
|
||||
dlz_destroy(cd);
|
||||
|
||||
/* return error */
|
||||
return (ISC_R_NOMEMORY);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
118
contrib/dlz/modules/include/dlz_dbi.h
Normal file
118
contrib/dlz/modules/include/dlz_dbi.h
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <dlz_minimal.h>
|
||||
#include <dlz_list.h>
|
||||
#include <dlz_pthread.h>
|
||||
|
||||
#ifndef DLZ_DBI_H
|
||||
#define DLZ_DBI_H 1
|
||||
|
||||
/*
|
||||
* Types
|
||||
*/
|
||||
#define REQUIRE_CLIENT 0x01
|
||||
#define REQUIRE_QUERY 0x02
|
||||
#define REQUIRE_RECORD 0x04
|
||||
#define REQUIRE_ZONE 0x08
|
||||
|
||||
typedef struct query_segment query_segment_t;
|
||||
typedef DLZ_LIST(query_segment_t) query_list_t;
|
||||
typedef struct dbinstance dbinstance_t;
|
||||
typedef DLZ_LIST(dbinstance_t) db_list_t;
|
||||
typedef struct driverinstance driverinstance_t;
|
||||
|
||||
/*%
|
||||
* a query segment is all the text between our special tokens
|
||||
* special tokens are %zone%, %record%, %client%
|
||||
*/
|
||||
struct query_segment {
|
||||
void *cmd;
|
||||
unsigned int strlen;
|
||||
isc_boolean_t direct;
|
||||
DLZ_LINK(query_segment_t) link;
|
||||
};
|
||||
|
||||
/*%
|
||||
* a database instance contains everything we need for running
|
||||
* a query against the database. Using it each separate thread
|
||||
* can dynamically construct a query and execute it against the
|
||||
* database. The "instance_lock" and locking code in the driver's
|
||||
* make sure no two threads try to use the same DBI at a time.
|
||||
*/
|
||||
struct dbinstance {
|
||||
void *dbconn;
|
||||
query_list_t *allnodes_q;
|
||||
query_list_t *allowxfr_q;
|
||||
query_list_t *authority_q;
|
||||
query_list_t *findzone_q;
|
||||
query_list_t *lookup_q;
|
||||
query_list_t *countzone_q;
|
||||
char *query_buf;
|
||||
char *zone;
|
||||
char *record;
|
||||
char *client;
|
||||
dlz_mutex_t lock;
|
||||
DLZ_LINK(dbinstance_t) link;
|
||||
};
|
||||
|
||||
/*
|
||||
* Method declarations
|
||||
*/
|
||||
|
||||
void
|
||||
destroy_querylist(query_list_t **querylist);
|
||||
|
||||
isc_result_t
|
||||
build_querylist(const char *query_str, char **zone, char **record,
|
||||
char **client, query_list_t **querylist, unsigned int flags,
|
||||
log_t log);
|
||||
|
||||
char *
|
||||
build_querystring(query_list_t *querylist);
|
||||
|
||||
isc_result_t
|
||||
build_dbinstance(const char *allnodes_str, const char *allowxfr_str,
|
||||
const char *authority_str, const char *findzone_str,
|
||||
const char *lookup_str, const char *countzone_str,
|
||||
dbinstance_t **dbi, log_t log);
|
||||
|
||||
void
|
||||
destroy_dbinstance(dbinstance_t *dbi);
|
||||
|
||||
char *
|
||||
get_parameter_value(const char *input, const char* key);
|
||||
|
||||
#endif /* DLZ_DBI_H */
|
||||
49
contrib/dlz/modules/include/dlz_list.h
Normal file
49
contrib/dlz/modules/include/dlz_list.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (C) 2004, 2006, 2007, 2011-2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (C) 1997-2002 Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef DLZ_LIST_H
|
||||
#define DLZ_LIST_H 1
|
||||
|
||||
#define DLZ_LIST(type) struct { type *head, *tail; }
|
||||
#define DLZ_LIST_INIT(list) \
|
||||
do { (list).head = NULL; (list).tail = NULL; } while (0)
|
||||
|
||||
#define DLZ_LINK(type) struct { type *prev, *next; }
|
||||
#define DLZ_LINK_INIT(elt, link) \
|
||||
do { \
|
||||
(elt)->link.prev = (void *)(-1); \
|
||||
(elt)->link.next = (void *)(-1); \
|
||||
} while (0)
|
||||
|
||||
#define DLZ_LIST_HEAD(list) ((list).head)
|
||||
#define DLZ_LIST_TAIL(list) ((list).tail)
|
||||
|
||||
#define DLZ_LIST_APPEND(list, elt, link) \
|
||||
do { \
|
||||
if ((list).tail != NULL) \
|
||||
(list).tail->link.next = (elt); \
|
||||
else \
|
||||
(list).head = (elt); \
|
||||
(elt)->link.prev = (list).tail; \
|
||||
(elt)->link.next = NULL; \
|
||||
(list).tail = (elt); \
|
||||
} while (0)
|
||||
|
||||
#define DLZ_LIST_PREV(elt, link) ((elt)->link.prev)
|
||||
#define DLZ_LIST_NEXT(elt, link) ((elt)->link.next)
|
||||
|
||||
#endif /* DLZ_LIST_H */
|
||||
|
|
@ -23,6 +23,9 @@
|
|||
* tree.
|
||||
*/
|
||||
|
||||
#ifndef DLZ_MINIMAL_H
|
||||
#define DLZ_MINIMAL_H 1
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef ISC_PLATFORM_HAVESYSUNH
|
||||
|
|
@ -45,8 +48,10 @@ typedef uint32_t dns_ttl_t;
|
|||
#define DLZ_DLOPEN_AGE 0
|
||||
#endif
|
||||
|
||||
/* return this in flags to dlz_version() if thread safe */
|
||||
/* return these in flags from dlz_version() */
|
||||
#define DNS_SDLZFLAG_THREADSAFE 0x00000001U
|
||||
#define DNS_SDLZFLAG_RELATIVEOWNER 0x00000002U
|
||||
#define DNS_SDLZFLAG_RELATIVERDATA 0x00000004U
|
||||
|
||||
/* result codes */
|
||||
#define ISC_R_SUCCESS 0
|
||||
|
|
@ -57,6 +62,9 @@ typedef uint32_t dns_ttl_t;
|
|||
#define ISC_R_FAILURE 25
|
||||
#define ISC_R_NOTIMPLEMENTED 27
|
||||
#define ISC_R_NOMORE 29
|
||||
#define ISC_R_INVALIDFILE 30
|
||||
#define ISC_R_UNEXPECTED 34
|
||||
#define ISC_R_FILENOTFOUND 38
|
||||
|
||||
/* boolean values */
|
||||
#define ISC_TRUE 1
|
||||
|
|
@ -68,6 +76,7 @@ typedef uint32_t dns_ttl_t;
|
|||
#define ISC_LOG_WARNING (-3)
|
||||
#define ISC_LOG_ERROR (-4)
|
||||
#define ISC_LOG_CRITICAL (-5)
|
||||
#define ISC_LOG_DEBUG(level) (level)
|
||||
|
||||
/* other useful definitions */
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
|
@ -196,6 +205,13 @@ dlz_lookup(const char *zone, const char *name, void *dbdata,
|
|||
dns_clientinfo_t *clientinfo);
|
||||
#endif /* DLZ_DLOPEN_VERSION */
|
||||
|
||||
/*
|
||||
* dlz_authority() is optional if dlz_lookup() supplies
|
||||
* authority information (i.e., SOA, NS) for the dns record
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_authority(const char *zone, void *dbdata, dns_sdlzlookup_t *lookup);
|
||||
|
||||
/*
|
||||
* dlz_allowzonexfr() is optional, and should be supplied if you want to
|
||||
* support zone transfers
|
||||
|
|
@ -269,3 +285,5 @@ dlz_subrdataset(const char *name, const char *rdatastr, void *dbdata,
|
|||
isc_result_t
|
||||
dlz_delrdataset(const char *name, const char *type, void *dbdata,
|
||||
void *version);
|
||||
|
||||
#endif /* DLZ_MINIMAL_H */
|
||||
38
contrib/dlz/modules/include/dlz_pthread.h
Normal file
38
contrib/dlz/modules/include/dlz_pthread.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef DLZ_PTHREAD_H
|
||||
#define DLZ_PTHREAD_H 1
|
||||
|
||||
#ifndef PTHREADS
|
||||
#define PTHREADS 1
|
||||
#endif
|
||||
|
||||
#ifdef PTHREADS
|
||||
#define dlz_mutex_t pthread_mutex_t
|
||||
#define dlz_mutex_init pthread_mutex_init
|
||||
#define dlz_mutex_destroy pthread_mutex_destroy
|
||||
#define dlz_mutex_trylock pthread_mutex_trylock
|
||||
#define dlz_mutex_unlock pthread_mutex_unlock
|
||||
#else /* !PTHREADS */
|
||||
#define dlz_mutex_t void
|
||||
#define dlz_mutex_init(a, b) (0)
|
||||
#define dlz_mutex_destroy(a) (0)
|
||||
#define dlz_mutex_trylock(a) (0)
|
||||
#define dlz_mutex_unlock(a) (0)
|
||||
#endif
|
||||
|
||||
#endif /* DLZ_PTHREAD_H */
|
||||
21
contrib/dlz/modules/ldap/Makefile
Normal file
21
contrib/dlz/modules/ldap/Makefile
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
prefix = /usr
|
||||
libdir = $(prefix)/lib/bind9
|
||||
|
||||
CFLAGS=-fPIC -g -I../include
|
||||
LDAP_LIBS=-lldap
|
||||
|
||||
all: dlz_ldap_dynamic.so
|
||||
|
||||
dlz_dbi.o: ../common/dlz_dbi.c
|
||||
$(CC) $(CFLAGS) -c ../common/dlz_dbi.c
|
||||
|
||||
dlz_ldap_dynamic.so: dlz_ldap_dynamic.c dlz_dbi.o
|
||||
$(CC) $(CFLAGS) -shared -o dlz_ldap_dynamic.so \
|
||||
dlz_ldap_dynamic.c dlz_dbi.o $(LDAP_LIBS)
|
||||
|
||||
clean:
|
||||
rm -f dlz_ldap_dynamic.so *.o
|
||||
|
||||
install: dlz_ldap_dynamic.so
|
||||
mkdir -p $(DESTDIR)$(libdir)
|
||||
install dlz_ldap_dynamic.so $(DESTDIR)$(libdir)
|
||||
1205
contrib/dlz/modules/ldap/dlz_ldap_dynamic.c
Normal file
1205
contrib/dlz/modules/ldap/dlz_ldap_dynamic.c
Normal file
File diff suppressed because it is too large
Load diff
10
contrib/dlz/modules/ldap/testing/README
Normal file
10
contrib/dlz/modules/ldap/testing/README
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
These files were used for testing on Ubuntu Linux using OpenLDAP.
|
||||
|
||||
- Move aside /etc/ldap/slapd.d
|
||||
- Move slapd.conf to /etc/ldap
|
||||
- Move dlz.schema to /etc/ldap/schema/dlz.schema
|
||||
- Run "/etc/init.d/slapd restart"
|
||||
- Run "ldapadd -x -f example.ldif -D 'cn=Manager,o=bind-dlz' -w secret"
|
||||
|
||||
LDAP server is now loaded with example.com data from the file example.ldif
|
||||
|
||||
187
contrib/dlz/modules/ldap/testing/dlz.schema
Normal file
187
contrib/dlz/modules/ldap/testing/dlz.schema
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
#
|
||||
#
|
||||
# 1.3.6.1.4.1.18420.1.1.X is reserved for attribute types declared by the DLZ project.
|
||||
# 1.3.6.1.4.1.18420.1.2.X is reserved for object classes declared by the DLZ project.
|
||||
# 1.3.6.1.4.1.18420.1.3.X is reserved for PRIVATE extensions to the DLZ attribute
|
||||
# types and object classes that may be needed by end users
|
||||
# to add security, etc. Attributes and object classes using
|
||||
# this OID MUST NOT be published outside of an organization
|
||||
# except to offer them for consideration to become part of the
|
||||
# standard attributes and object classes published by the DLZ project.
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.18420.1.1.10
|
||||
NAME 'dlzZoneName'
|
||||
DESC 'DNS zone name - domain name not including host name'
|
||||
SUP name
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.18420.1.1.20
|
||||
NAME 'dlzHostName'
|
||||
DESC 'Host portion of a domain name'
|
||||
SUP name
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.18420.1.1.30
|
||||
NAME 'dlzData'
|
||||
DESC 'Data for the resource record'
|
||||
SUP name
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.18420.1.1.40
|
||||
NAME 'dlzType'
|
||||
DESC 'DNS record type - A, SOA, NS, MX, etc...'
|
||||
SUP name
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.18420.1.1.50
|
||||
NAME 'dlzSerial'
|
||||
DESC 'SOA record serial number'
|
||||
EQUALITY integerMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.18420.1.1.60
|
||||
NAME 'dlzRefresh'
|
||||
DESC 'SOA record refresh time in seconds'
|
||||
EQUALITY integerMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.18420.1.1.70
|
||||
NAME 'dlzRetry'
|
||||
DESC 'SOA retry time in seconds'
|
||||
EQUALITY integerMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.18420.1.1.80
|
||||
NAME 'dlzExpire'
|
||||
DESC 'SOA expire time in seconds'
|
||||
EQUALITY integerMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.18420.1.1.90
|
||||
NAME 'dlzMinimum'
|
||||
DESC 'SOA minimum time in seconds'
|
||||
EQUALITY integerMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.18420.1.1.100
|
||||
NAME 'dlzAdminEmail'
|
||||
DESC 'E-mail address of person responsible for this zone - @ should be replaced with . (period)'
|
||||
SUP name
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.18420.1.1.110
|
||||
NAME 'dlzPrimaryNS'
|
||||
DESC 'Primary name server for this zone - should be host name not IP address'
|
||||
SUP name
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.18420.1.1.120
|
||||
NAME 'dlzIPAddr'
|
||||
DESC 'IP address - IPV4 should be in dot notation xxx.xxx.xxx.xxx IPV6 should be in colon notation xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx'
|
||||
EQUALITY caseExactIA5Match
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{40}
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.18420.1.1.130
|
||||
NAME 'dlzCName'
|
||||
DESC 'DNS cname'
|
||||
SUP name
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.18420.1.1.140
|
||||
NAME 'dlzPreference'
|
||||
DESC 'DNS MX record preference. Lower numbers have higher preference'
|
||||
EQUALITY integerMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.18420.1.1.150
|
||||
NAME 'dlzTTL'
|
||||
DESC 'DNS time to live - how long this record can be cached by caching DNS servers'
|
||||
EQUALITY integerMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
|
||||
SINGLE-VALUE )
|
||||
|
||||
attributetype ( 1.3.6.1.4.1.18420.1.1.160
|
||||
NAME 'dlzRecordID'
|
||||
DESC 'Unique ID for each DLZ resource record'
|
||||
SUP name
|
||||
SINGLE-VALUE )
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Object class definitions
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
objectclass ( 1.3.6.1.4.1.18420.1.2.10
|
||||
NAME 'dlzZone'
|
||||
DESC 'Zone name portion of a domain name'
|
||||
SUP top STRUCTURAL
|
||||
MUST ( objectclass $ dlzZoneName ) )
|
||||
|
||||
objectclass ( 1.3.6.1.4.1.18420.1.2.20
|
||||
NAME 'dlzHost'
|
||||
DESC 'Host name portion of a domain name'
|
||||
SUP top STRUCTURAL
|
||||
MUST ( objectclass $ dlzHostName ) )
|
||||
|
||||
objectclass ( 1.3.6.1.4.1.18420.1.2.30
|
||||
NAME 'dlzAbstractRecord'
|
||||
DESC 'Data common to all DNS record types'
|
||||
SUP top ABSTRACT
|
||||
MUST ( objectclass $ dlzRecordID $ dlzHostName $ dlzType $ dlzTTL ) )
|
||||
|
||||
objectclass ( 1.3.6.1.4.1.18420.1.2.40
|
||||
NAME 'dlzGenericRecord'
|
||||
DESC 'Generic DNS record - useful when a specific object class has not been defined for a DNS record'
|
||||
SUP dlzAbstractRecord STRUCTURAL
|
||||
MUST ( dlzData ) )
|
||||
|
||||
objectclass ( 1.3.6.1.4.1.18420.1.2.50
|
||||
NAME 'dlzARecord'
|
||||
DESC 'DNS A record'
|
||||
SUP dlzAbstractrecord STRUCTURAL
|
||||
MUST ( dlzIPAddr ) )
|
||||
|
||||
objectclass ( 1.3.6.1.4.1.18420.1.2.60
|
||||
NAME 'dlzNSRecord'
|
||||
DESC 'DNS NS record'
|
||||
SUP dlzGenericRecord STRUCTURAL )
|
||||
|
||||
objectclass ( 1.3.6.1.4.1.18420.1.2.70
|
||||
NAME 'dlzMXRecord'
|
||||
DESC 'DNS MX record'
|
||||
SUP dlzGenericRecord STRUCTURAL
|
||||
MUST ( dlzPreference ) )
|
||||
|
||||
objectclass ( 1.3.6.1.4.1.18420.1.2.80
|
||||
NAME 'dlzSOARecord'
|
||||
DESC 'DNS SOA record'
|
||||
SUP dlzAbstractRecord STRUCTURAL
|
||||
MUST ( dlzSerial $ dlzRefresh $ dlzRetry
|
||||
$ dlzExpire $ dlzMinimum $ dlzAdminEmail $ dlzPrimaryNS ) )
|
||||
|
||||
objectclass ( 1.3.6.1.4.1.18420.1.2.90
|
||||
NAME 'dlzTextRecord'
|
||||
DESC 'Text data with spaces should be wrapped in double quotes'
|
||||
SUP dlzGenericRecord STRUCTURAL )
|
||||
|
||||
objectclass ( 1.3.6.1.4.1.18420.1.2.100
|
||||
NAME 'dlzPTRRecord'
|
||||
DESC 'DNS PTR record'
|
||||
SUP dlzGenericRecord STRUCTURAL )
|
||||
|
||||
objectclass ( 1.3.6.1.4.1.18420.1.2.110
|
||||
NAME 'dlzCNameRecord'
|
||||
DESC 'DNS CName record'
|
||||
SUP dlzGenericRecord STRUCTURAL )
|
||||
|
||||
objectclass ( 1.3.6.1.4.1.18420.1.2.120
|
||||
NAME 'dlzXFR'
|
||||
DESC 'Host allowed to perform zone transfer'
|
||||
SUP top STRUCTURAL
|
||||
MUST ( objectclass $ dlzRecordID $ dlzIPAddr ) )
|
||||
168
contrib/dlz/modules/ldap/testing/example.ldif
Normal file
168
contrib/dlz/modules/ldap/testing/example.ldif
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
# server suffix - o=bind-dlz
|
||||
|
||||
dn: o=bind-dlz
|
||||
objectclass: organization
|
||||
o: bind-dlz
|
||||
|
||||
dn: ou=dns,o=bind-dlz
|
||||
objectclass: organizationalUnit
|
||||
ou: dns
|
||||
|
||||
dn: dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzZone
|
||||
dlzZoneName: example.com
|
||||
|
||||
dn: dlzHostName=@,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzHost
|
||||
dlzHostName: @
|
||||
|
||||
dn: dlzHostName=www,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzHost
|
||||
dlzHostName: www
|
||||
|
||||
dn: dlzHostName=mail,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzHost
|
||||
dlzHostName: mail
|
||||
|
||||
dn: dlzHostName=backup,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzHost
|
||||
dlzHostName: backup
|
||||
|
||||
dn: dlzHostName=ns1,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzHost
|
||||
dlzHostName: ns1
|
||||
|
||||
dn: dlzHostName=ns2,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzHost
|
||||
dlzHostName: ns2
|
||||
|
||||
dn: dlzHostName=~,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzHost
|
||||
dlzHostName: ~
|
||||
|
||||
dn: dlzRecordID=1,dlzHostName=@,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzGenericRecord
|
||||
dlzRecordID: 1
|
||||
dlzHostName: @
|
||||
dlzType: txt
|
||||
dlzData: "this is a text record"
|
||||
dlzTTL: 10
|
||||
|
||||
dn: dlzRecordID=2,dlzHostName=www,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzARecord
|
||||
dlzRecordID: 2
|
||||
dlzHostName: www
|
||||
dlzType: a
|
||||
dlzIPAddr: 192.168.0.1
|
||||
dlzTTL: 10
|
||||
|
||||
dn: dlzRecordID=3,dlzHostName=mail,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzARecord
|
||||
dlzRecordID: 3
|
||||
dlzHostName: mail
|
||||
dlzType: a
|
||||
dlzIPAddr: 192.168.0.2
|
||||
dlzTTL: 10
|
||||
|
||||
dn: dlzRecordID=4,dlzHostName=backup,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzARecord
|
||||
dlzRecordID: 4
|
||||
dlzHostName: backup
|
||||
dlzType: a
|
||||
dlzIPAddr: 192.168.0.3
|
||||
dlzTTL: 10
|
||||
|
||||
dn: dlzRecordID=5,dlzHostName=@,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzMXRecord
|
||||
dlzRecordID: 5
|
||||
dlzHostName: @
|
||||
dlzType: mx
|
||||
dlzData: mail
|
||||
dlzPreference: 20
|
||||
dlzTTL: 10
|
||||
|
||||
dn: dlzRecordID=6,dlzHostName=@,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzMXRecord
|
||||
dlzRecordID: 6
|
||||
dlzHostName: @
|
||||
dlzType: mx
|
||||
dlzData: backup
|
||||
dlzPreference: 40
|
||||
dlzTTL: 10
|
||||
|
||||
dn: dlzRecordID=7,dlzHostName=www,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzMXRecord
|
||||
dlzRecordID: 7
|
||||
dlzHostName: www
|
||||
dlzType: mx
|
||||
dlzData: backup
|
||||
dlzPreference: 40
|
||||
dlzTTL: 10
|
||||
|
||||
dn: dlzRecordID=8,dlzHostName=www,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzMXRecord
|
||||
dlzRecordID: 8
|
||||
dlzHostName: www
|
||||
dlzType: mx
|
||||
dlzData: mail
|
||||
dlzPreference: 20
|
||||
dlzTTL: 10
|
||||
|
||||
dn: dlzRecordID=9,dlzHostName=ns1,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzARecord
|
||||
dlzRecordID: 9
|
||||
dlzHostName: ns1
|
||||
dlzType: a
|
||||
dlzIPAddr: 192.168.0.4
|
||||
dlzTTL: 10
|
||||
|
||||
dn: dlzRecordID=10,dlzHostName=ns2,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzARecord
|
||||
dlzRecordID: 10
|
||||
dlzHostName: ns2
|
||||
dlzType: a
|
||||
dlzIPAddr: 192.168.0.5
|
||||
dlzTTL: 10
|
||||
|
||||
dn: dlzRecordID=11,dlzHostName=@,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzSOARecord
|
||||
dlzRecordID: 11
|
||||
dlzHostName: @
|
||||
dlzType: soa
|
||||
dlzSerial: 2
|
||||
dlzRefresh: 2800
|
||||
dlzRetry: 7200
|
||||
dlzExpire: 604800
|
||||
dlzMinimum: 86400
|
||||
dlzAdminEmail: root.example.com.
|
||||
dlzPrimaryns: ns1.example.com.
|
||||
dlzTTL: 10
|
||||
|
||||
dn: dlzRecordID=12,dlzHostName=@,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzNSRecord
|
||||
dlzRecordID: 12
|
||||
dlzHostName: @
|
||||
dlzType: ns
|
||||
dlzData: ns1.example.com.
|
||||
dlzTTL: 10
|
||||
|
||||
dn: dlzRecordID=13,dlzHostName=@,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzNSRecord
|
||||
dlzRecordID: 13
|
||||
dlzHostName: @
|
||||
dlzType: ns
|
||||
dlzData: ns2
|
||||
dlzTTL: 10
|
||||
|
||||
dn: dlzRecordID=14,dlzHostName=~,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzARecord
|
||||
dlzRecordID: 14
|
||||
dlzHostName: ~
|
||||
dlzType: a
|
||||
dlzIPAddr: 192.168.0.250
|
||||
dlzTTL: 10
|
||||
|
||||
dn: dlzRecordID=15,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzXFR
|
||||
dlzRecordID: 15
|
||||
dlzIPAddr: 127.0.0.1
|
||||
46
contrib/dlz/modules/ldap/testing/named.conf
Normal file
46
contrib/dlz/modules/ldap/testing/named.conf
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
controls { };
|
||||
|
||||
options {
|
||||
directory ".";
|
||||
port 5300;
|
||||
pid-file "named.pid";
|
||||
session-keyfile "session.key";
|
||||
listen-on { any; };
|
||||
listen-on-v6 { none; };
|
||||
recursion no;
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-md5;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 127.0.0.1 port 9953 allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
dlz "test" {
|
||||
database "dlopen ../dlz_ldap_dynamic.so 2
|
||||
v3 simple {cn=Manager,o=bind-dlz} {secret} {127.0.0.1}
|
||||
ldap:///dlzZoneName=$zone$,ou=dns,o=bind-dlz???objectclass=dlzZone
|
||||
ldap:///dlzHostName=$record$,dlzZoneName=$zone$,ou=dns,o=bind-dlz?dlzTTL,dlzType,dlzPreference,dlzData,dlzIPAddr?sub?(&(objectclass=dlzAbstractRecord)(!(dlzType=soa)))
|
||||
ldap:///dlzHostName=@,dlzZoneName=$zone$,ou=dns,o=bind-dlz?dlzTTL,dlzType,dlzData,dlzPrimaryNS,dlzAdminEmail,dlzSerial,dlzRefresh,dlzRetry,dlzExpire,dlzMinimum?sub?(&(objectclass=dlzAbstractRecord)(dlzType=soa))
|
||||
ldap:///dlzZoneName=$zone$,ou=dns,o=bind-dlz?dlzTTL,dlzType,dlzHostName,dlzPreference,dlzData,dlzIPAddr,dlzPrimaryNS,dlzAdminEmail,dlzSerial,dlzRefresh,dlzRetry,dlzExpire,dlzMinimum?sub?(&(objectclass=dlzAbstractRecord)(!(dlzType=soa)))
|
||||
ldap:///dlzZoneName=$zone$,ou=dns,o=bind-dlz??sub?(&(objectclass=dlzXFR)(dlzIPAddr=$client$))";
|
||||
};
|
||||
44
contrib/dlz/modules/ldap/testing/slapd.conf
Normal file
44
contrib/dlz/modules/ldap/testing/slapd.conf
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# this is the full path to the core.schema
|
||||
include /etc/ldap/schema/core.schema
|
||||
|
||||
# this is the full path to the dlz.schema
|
||||
include /etc/ldap/schema/dlz.schema
|
||||
|
||||
# these files hold the slapd process ID and program args when
|
||||
# slapd is started.
|
||||
pidfile /var/run/slapd/slapd.pid
|
||||
argsfile /var/run/slapd/slapd.args
|
||||
|
||||
modulepath /usr/lib/ldap
|
||||
moduleload back_hdb
|
||||
|
||||
# this allows ldap version 2 connections. You should comment
|
||||
# it out if you don't need ldap version 2.
|
||||
allow bind_v2
|
||||
|
||||
# this sets up the Berkeley DB database backend for LDAP to use.
|
||||
database hdb
|
||||
|
||||
# This is the root of the LDAP server. You still need to add
|
||||
# an entry to this location via a LDIF file, or you won't be
|
||||
# able to add anything else into the LDAP server.
|
||||
suffix "o=bind-dlz"
|
||||
|
||||
# this is the "username" you have to use when connecting to the
|
||||
# ldap server to make updates. Type the whole thing exactly
|
||||
# as you see it as a parameter to ldapadd.
|
||||
rootdn "cn=Manager,o=bind-dlz"
|
||||
|
||||
# this is the "password" you have to use when connecting to the
|
||||
# ldap server to make updates.
|
||||
rootpw secret
|
||||
|
||||
# this is the directory that the LDAP server will create the
|
||||
# Berkeley DB backend in.
|
||||
directory /var/lib/ldap
|
||||
|
||||
# this just adds some indexing to the LDAP server.
|
||||
# probably should have more to better optimize DLZ LDAP searches.
|
||||
index cn,sn,uid pres,eq
|
||||
index objectClass eq
|
||||
|
||||
20
contrib/dlz/modules/wildcard/Makefile
Normal file
20
contrib/dlz/modules/wildcard/Makefile
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
prefix = /usr
|
||||
libdir = $(prefix)/lib/bind9
|
||||
|
||||
CFLAGS=-fPIC -g -I../include
|
||||
|
||||
all: dlz_wildcard_dynamic.so
|
||||
|
||||
dlz_dbi.o: ../common/dlz_dbi.c
|
||||
$(CC) $(CFLAGS) -c ../common/dlz_dbi.c
|
||||
|
||||
dlz_wildcard_dynamic.so: dlz_wildcard_dynamic.c dlz_dbi.o
|
||||
$(CC) $(CFLAGS) -shared -o dlz_wildcard_dynamic.so \
|
||||
dlz_wildcard_dynamic.c dlz_dbi.o
|
||||
|
||||
clean:
|
||||
rm -f dlz_wildcard_dynamic.so *.o
|
||||
|
||||
install: dlz_wildcard_dynamic.so
|
||||
mkdir -p $(DESTDIR)$(libdir)
|
||||
install dlz_wildcard_dynamic.so $(DESTDIR)$(libdir)
|
||||
31
contrib/dlz/modules/wildcard/README
Normal file
31
contrib/dlz/modules/wildcard/README
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
The "wildcard" DLZ module provides a "template" zone for domains matching
|
||||
a wildcard name. For example, the following DLZ configuration would match
|
||||
any zone name containing the string "example" and ending with .com, such
|
||||
as "thisexample.com", "exampleofthat.com", or "anexampleoftheotherthing.com".
|
||||
|
||||
dlz "test" {
|
||||
database "dlopen ../dlz_wildcard_dynamic.so
|
||||
*example*.com 10.53.* 1800
|
||||
@ 3600 SOA {ns3.example.nil. support.example.nil. 42 14400 7200 2592000 600}
|
||||
@ 3600 NS ns3.example.nil.
|
||||
@ 3600 NS ns4.example.nil.
|
||||
@ 3600 NS ns8.example.nil.
|
||||
@ 3600 MX {5 mail.example.nil.}
|
||||
ftp 86400 A 192.0.0.1
|
||||
sql 86400 A 192.0.0.2
|
||||
tmp {} A 192.0.0.3
|
||||
www 86400 A 192.0.0.3
|
||||
www 86400 AAAA ::1
|
||||
txt 300 TXT {\"you requested $record$ in $zone$\"}
|
||||
* 86400 A 192.0.0.100";
|
||||
};
|
||||
|
||||
For any zone name matchin the wildcard, it would return the data from
|
||||
the template. "$zone$" is replaced with zone name: i.e., the shortest
|
||||
possible string of labels in the query name that matches the wildcard.
|
||||
"$record$" is replaced with the remainder of the query name. In the
|
||||
example above, a query for "txt.thisexample.com/TXT" would return the
|
||||
string "you requested txt in thisexample.com".
|
||||
|
||||
Any client whose source address matches the second wildcard ("10.53.*")
|
||||
is allowed to request a zone transfer.
|
||||
738
contrib/dlz/modules/wildcard/dlz_wildcard_dynamic.c
Normal file
738
contrib/dlz/modules/wildcard/dlz_wildcard_dynamic.c
Normal file
|
|
@ -0,0 +1,738 @@
|
|||
/*
|
||||
* Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
* Copyright (C) 2012 Vadim Goncharov, Russia, vadim_nuclight@mail.ru.
|
||||
*
|
||||
* 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) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (C) 1999-2001 Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This provides the externally loadable wildcard DLZ module.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <dlz_minimal.h>
|
||||
#include <dlz_list.h>
|
||||
#include <dlz_dbi.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#define DE_CONST(konst, var) \
|
||||
do { \
|
||||
union { const void *k; void *v; } _u; \
|
||||
_u.k = konst; \
|
||||
var = _u.v; \
|
||||
} while (0)
|
||||
|
||||
/* fnmatch() return values. */
|
||||
#define FNM_NOMATCH 1 /* Match failed. */
|
||||
|
||||
/* fnmatch() flags. */
|
||||
#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
|
||||
#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
|
||||
#define FNM_PERIOD 0x04 /* Period must be matched by period. */
|
||||
#define FNM_LEADING_DIR 0x08 /* Ignore /<tail> after Imatch. */
|
||||
#define FNM_CASEFOLD 0x10 /* Case insensitive search. */
|
||||
#define FNM_IGNORECASE FNM_CASEFOLD
|
||||
#define FNM_FILE_NAME FNM_PATHNAME
|
||||
|
||||
/*
|
||||
* Our data structures.
|
||||
*/
|
||||
|
||||
typedef struct named_rr nrr_t;
|
||||
typedef DLZ_LIST(nrr_t) rr_list_t;
|
||||
|
||||
typedef struct config_data {
|
||||
char *zone_pattern;
|
||||
char *axfr_pattern;
|
||||
rr_list_t rrs_list;
|
||||
char *zone;
|
||||
char *record;
|
||||
char *client;
|
||||
|
||||
/* 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;
|
||||
|
||||
struct named_rr {
|
||||
char *name;
|
||||
char *type;
|
||||
int ttl;
|
||||
query_list_t *data;
|
||||
DLZ_LINK(nrr_t) link;
|
||||
};
|
||||
|
||||
/*
|
||||
* Forward references
|
||||
*/
|
||||
static int
|
||||
rangematch(const char *, char, int, char **);
|
||||
|
||||
static int
|
||||
fnmatch(const char *pattern, const char *string, int flags);
|
||||
|
||||
static void
|
||||
b9_add_helper(struct config_data *cd, const char *helper_name, void *ptr);
|
||||
|
||||
static const char *
|
||||
shortest_match(const char *pattern, const char *string);
|
||||
|
||||
isc_result_t
|
||||
dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes) {
|
||||
config_data_t *cd = (config_data_t *) dbdata;
|
||||
isc_result_t result;
|
||||
char *querystring = NULL;
|
||||
nrr_t *nrec;
|
||||
int i = 0;
|
||||
|
||||
DE_CONST(zone, cd->zone);
|
||||
|
||||
/* Write info message to log */
|
||||
cd->log(ISC_LOG_DEBUG(1),
|
||||
"dlz_wildcard allnodes called for zone '%s'", zone);
|
||||
|
||||
result = ISC_R_FAILURE;
|
||||
|
||||
nrec = DLZ_LIST_HEAD(cd->rrs_list);
|
||||
while (nrec != NULL) {
|
||||
cd->record = nrec->name;
|
||||
|
||||
querystring = build_querystring(nrec->data);
|
||||
|
||||
if (querystring == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
cd->log(ISC_LOG_DEBUG(2),
|
||||
"dlz_wildcard allnodes entry num %d: calling "
|
||||
"putnamedrr(name=%s type=%s ttl=%d qs=%s)",
|
||||
i++, nrec->name, nrec->type, nrec->ttl, querystring);
|
||||
|
||||
result = cd->putnamedrr(allnodes, nrec->name, nrec->type,
|
||||
nrec->ttl, querystring);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto done;
|
||||
|
||||
nrec = DLZ_LIST_NEXT(nrec, link);
|
||||
}
|
||||
|
||||
done:
|
||||
cd->zone = NULL;
|
||||
|
||||
if (querystring != NULL)
|
||||
free(querystring);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dlz_allowzonexfr(void *dbdata, const char *name, const char *client) {
|
||||
config_data_t *cd = (config_data_t *) dbdata;
|
||||
|
||||
UNUSED(name);
|
||||
|
||||
/* Write info message to log */
|
||||
cd->log(ISC_LOG_DEBUG(1),
|
||||
"dlz_wildcard allowzonexfr called for client '%s'", client);
|
||||
|
||||
if (fnmatch(cd->axfr_pattern, client, FNM_CASEFOLD) == 0)
|
||||
return (ISC_R_SUCCESS);
|
||||
else
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
|
||||
#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
|
||||
{
|
||||
config_data_t *cd = (config_data_t *) dbdata;
|
||||
const char *p;
|
||||
|
||||
#if DLZ_DLOPEN_VERSION >= 3
|
||||
UNUSED(methods);
|
||||
UNUSED(clientinfo);
|
||||
#endif
|
||||
|
||||
p = shortest_match(cd->zone_pattern, name);
|
||||
if (p == NULL)
|
||||
return (ISC_R_NOTFOUND);
|
||||
|
||||
/* Write info message to log */
|
||||
cd->log(ISC_LOG_DEBUG(1),
|
||||
"dlz_wildcard findzonedb matched '%s'", p);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
#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;
|
||||
config_data_t *cd = (config_data_t *) dbdata;
|
||||
char *querystring = NULL;
|
||||
const char *p;
|
||||
char *namebuf;
|
||||
nrr_t *nrec;
|
||||
isc_boolean_t origin = ISC_TRUE;
|
||||
|
||||
#if DLZ_DLOPEN_VERSION >= 2
|
||||
UNUSED(methods);
|
||||
UNUSED(clientinfo);
|
||||
#endif
|
||||
|
||||
p = shortest_match(cd->zone_pattern, zone);
|
||||
if (p == NULL)
|
||||
return (ISC_R_NOTFOUND);
|
||||
|
||||
DE_CONST(name, cd->record);
|
||||
DE_CONST(p, cd->zone);
|
||||
|
||||
if ((p != zone) && (strcmp(name, "@") == 0 || strcmp(name, zone) == 0))
|
||||
{
|
||||
size_t len = p - zone;
|
||||
namebuf = malloc(len);
|
||||
strncpy(namebuf, zone, len - 1);
|
||||
namebuf[len - 1] = '\0';
|
||||
cd->record = namebuf;
|
||||
origin = ISC_FALSE;
|
||||
} else if (p == zone)
|
||||
cd->record = "@";
|
||||
|
||||
/* Write info message to log */
|
||||
cd->log(ISC_LOG_DEBUG(1),
|
||||
"dlz_wildcard_dynamic: lookup for '%s' in '%s': "
|
||||
"trying '%s' in '%s'",
|
||||
name, zone, cd->record, cd->zone);
|
||||
|
||||
result = ISC_R_NOTFOUND;
|
||||
nrec = DLZ_LIST_HEAD(cd->rrs_list);
|
||||
while (nrec != NULL) {
|
||||
nrr_t *next = DLZ_LIST_NEXT(nrec, link);
|
||||
if (strcmp(cd->record, nrec->name) == 0) {
|
||||
/* We handle authority data in dlz_authority() */
|
||||
if (strcmp(nrec->type, "SOA") == 0 ||
|
||||
strcmp(nrec->type, "NS") == 0)
|
||||
{
|
||||
nrec = next;
|
||||
continue;
|
||||
}
|
||||
|
||||
querystring = build_querystring(nrec->data);
|
||||
if (querystring == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
result = cd->putrr(lookup, nrec->type,
|
||||
nrec->ttl, querystring);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto done;
|
||||
|
||||
fprintf(stderr, "setting result to success on %s/%s\n", nrec->name, nrec->type);
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
free(querystring);
|
||||
querystring = NULL;
|
||||
}
|
||||
nrec = next;
|
||||
}
|
||||
|
||||
done:
|
||||
cd->zone = NULL;
|
||||
cd->record = NULL;
|
||||
|
||||
if (querystring != NULL)
|
||||
free(querystring);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dlz_authority(const char *zone, void *dbdata, dns_sdlzlookup_t *lookup) {
|
||||
isc_result_t result;
|
||||
config_data_t *cd = (config_data_t *) dbdata;
|
||||
char *querystring = NULL;
|
||||
nrr_t *nrec;
|
||||
const char *p, *name = "@";
|
||||
|
||||
p = shortest_match(cd->zone_pattern, zone);
|
||||
if (p == NULL)
|
||||
return (ISC_R_NOTFOUND);
|
||||
|
||||
DE_CONST(p, cd->zone);
|
||||
|
||||
/* Write info message to log */
|
||||
cd->log(ISC_LOG_DEBUG(1),
|
||||
"dlz_wildcard_dynamic: authority for '%s'", zone);
|
||||
|
||||
result = ISC_R_NOTFOUND;
|
||||
nrec = DLZ_LIST_HEAD(cd->rrs_list);
|
||||
while (nrec != NULL) {
|
||||
isc_boolean_t origin;
|
||||
if (strcmp("@", nrec->name) == 0) {
|
||||
isc_result_t presult;
|
||||
|
||||
querystring = build_querystring(nrec->data);
|
||||
if (querystring == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
presult = cd->putrr(lookup, nrec->type,
|
||||
nrec->ttl, querystring);
|
||||
if (presult != ISC_R_SUCCESS) {
|
||||
result = presult;
|
||||
goto done;
|
||||
}
|
||||
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
free(querystring);
|
||||
querystring = NULL;
|
||||
}
|
||||
nrec = DLZ_LIST_NEXT(nrec, link);
|
||||
}
|
||||
|
||||
done:
|
||||
cd->zone = NULL;
|
||||
|
||||
if (querystring != NULL)
|
||||
free(querystring);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_rrlist(config_data_t *cd) {
|
||||
nrr_t *trec, *nrec;
|
||||
|
||||
nrec = DLZ_LIST_HEAD(cd->rrs_list);
|
||||
|
||||
while (nrec != NULL) {
|
||||
trec = nrec;
|
||||
|
||||
destroy_querylist(&trec->data);
|
||||
|
||||
if (trec->name != NULL)
|
||||
free(trec->name);
|
||||
if (trec->type != NULL)
|
||||
free(trec->type);
|
||||
trec->name = trec->type = NULL;
|
||||
|
||||
/* Get the next record, before we destroy this one. */
|
||||
nrec = DLZ_LIST_NEXT(nrec, link);
|
||||
|
||||
free(trec);
|
||||
}
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dlz_create(const char *dlzname, unsigned int argc, char *argv[],
|
||||
void **dbdata, ...)
|
||||
{
|
||||
config_data_t *cd;
|
||||
char *endp;
|
||||
int i, def_ttl;
|
||||
nrr_t *trec = NULL;
|
||||
isc_result_t result;
|
||||
const char *helper_name;
|
||||
va_list ap;
|
||||
|
||||
if (argc < 8 || argc % 4 != 0)
|
||||
return (ISC_R_FAILURE);
|
||||
|
||||
cd = calloc(1, sizeof(config_data_t));
|
||||
if (cd == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
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);
|
||||
|
||||
/*
|
||||
* Write info message to log
|
||||
*/
|
||||
cd->log(ISC_LOG_INFO,
|
||||
"Loading '%s' using DLZ_wildcard driver. "
|
||||
"Zone: %s, AXFR allowed for: %s, $TTL: %s",
|
||||
dlzname, argv[1], argv[2], argv[3]);
|
||||
|
||||
/* initialize the records list here to simplify cleanup */
|
||||
DLZ_LIST_INIT(cd->rrs_list);
|
||||
|
||||
cd->zone_pattern = strdup(argv[1]);
|
||||
if (cd->zone_pattern == NULL)
|
||||
goto cleanup;
|
||||
|
||||
cd->axfr_pattern = strdup(argv[2]);
|
||||
if (cd->axfr_pattern == NULL)
|
||||
goto cleanup;
|
||||
|
||||
def_ttl = strtol(argv[3], &endp, 10);
|
||||
if (*endp != '\0' || def_ttl < 0) {
|
||||
def_ttl = 3600;
|
||||
cd->log(ISC_LOG_ERROR, "default TTL invalid, using 3600");
|
||||
}
|
||||
|
||||
for (i = 4; i < argc; i += 4) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
|
||||
trec = malloc(sizeof(nrr_t));
|
||||
if (trec == NULL)
|
||||
goto full_cleanup;
|
||||
|
||||
memset(trec, 0, sizeof(nrr_t));
|
||||
|
||||
/* Initialize the record link */
|
||||
DLZ_LINK_INIT(trec, link);
|
||||
/* Append the record to the list */
|
||||
DLZ_LIST_APPEND(cd->rrs_list, trec, link);
|
||||
|
||||
trec->name = strdup(argv[i]);
|
||||
if (trec->name == NULL)
|
||||
goto full_cleanup;
|
||||
|
||||
trec->type = strdup(argv[i + 2]);
|
||||
if (trec->type == NULL)
|
||||
goto full_cleanup;
|
||||
|
||||
trec->ttl = strtol(argv[i + 1], &endp, 10);
|
||||
if (argv[i + 1][0] == '\0' || *endp != '\0' || trec->ttl < 0)
|
||||
trec->ttl = def_ttl;
|
||||
|
||||
result = build_querylist(argv[i + 3], &cd->zone,
|
||||
&cd->record, &cd->client,
|
||||
&trec->data, 0, cd->log);
|
||||
/* If unsuccessful, log err msg and cleanup */
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
cd->log(ISC_LOG_ERROR,
|
||||
"Could not build RR data list at argv[%d]",
|
||||
i + 3);
|
||||
goto full_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
*dbdata = cd;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
full_cleanup:
|
||||
destroy_rrlist(cd);
|
||||
|
||||
cleanup:
|
||||
if (cd->zone_pattern != NULL)
|
||||
free(cd->zone_pattern);
|
||||
if (cd->axfr_pattern != NULL)
|
||||
free(cd->axfr_pattern);
|
||||
free(cd);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
dlz_destroy(void *dbdata) {
|
||||
config_data_t *cd = (config_data_t *) dbdata;
|
||||
|
||||
/*
|
||||
* Write debugging message to log
|
||||
*/
|
||||
cd->log(ISC_LOG_DEBUG(2), "Unloading DLZ_wildcard driver.");
|
||||
|
||||
destroy_rrlist(cd);
|
||||
|
||||
free(cd->zone_pattern);
|
||||
free(cd->axfr_pattern);
|
||||
free(cd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the version of the API
|
||||
*/
|
||||
int
|
||||
dlz_version(unsigned int *flags) {
|
||||
UNUSED(flags);
|
||||
/* XXX: ok to set DNS_SDLZFLAG_THREADSAFE here? */
|
||||
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;
|
||||
}
|
||||
|
||||
static const char *
|
||||
shortest_match(const char *pattern, const char *string) {
|
||||
const char *p = string;
|
||||
if (pattern == NULL || p == NULL || *p == '\0')
|
||||
return (NULL);
|
||||
|
||||
p += strlen(p);
|
||||
while (p-- > string) {
|
||||
if (*p == '.') {
|
||||
if (fnmatch(pattern, p + 1, FNM_CASEFOLD) == 0)
|
||||
return (p + 1);
|
||||
}
|
||||
}
|
||||
if (fnmatch(pattern, string, FNM_CASEFOLD) == 0)
|
||||
return (string);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* The helper functions stolen from the FreeBSD kernel (sys/libkern/fnmatch.c).
|
||||
*
|
||||
* Why don't we use fnmatch(3) from libc? Because it is not thread-safe, and
|
||||
* it is not thread-safe because it supports multibyte characters. But here,
|
||||
* in BIND, we want to be thread-safe and don't need multibyte - DNS names are
|
||||
* always ASCII.
|
||||
*/
|
||||
#define EOS '\0'
|
||||
|
||||
#define RANGE_MATCH 1
|
||||
#define RANGE_NOMATCH 0
|
||||
#define RANGE_ERROR (-1)
|
||||
|
||||
static int
|
||||
fnmatch(const char *pattern, const char *string, int flags) {
|
||||
const char *stringstart;
|
||||
char *newp;
|
||||
char c, test;
|
||||
|
||||
for (stringstart = string;;)
|
||||
switch (c = *pattern++) {
|
||||
case EOS:
|
||||
if ((flags & FNM_LEADING_DIR) && *string == '/')
|
||||
return (0);
|
||||
return (*string == EOS ? 0 : FNM_NOMATCH);
|
||||
case '?':
|
||||
if (*string == EOS)
|
||||
return (FNM_NOMATCH);
|
||||
if (*string == '/' && (flags & FNM_PATHNAME))
|
||||
return (FNM_NOMATCH);
|
||||
if (*string == '.' && (flags & FNM_PERIOD) &&
|
||||
(string == stringstart ||
|
||||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
|
||||
return (FNM_NOMATCH);
|
||||
++string;
|
||||
break;
|
||||
case '*':
|
||||
c = *pattern;
|
||||
/* Collapse multiple stars. */
|
||||
while (c == '*')
|
||||
c = *++pattern;
|
||||
|
||||
if (*string == '.' && (flags & FNM_PERIOD) &&
|
||||
(string == stringstart ||
|
||||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
/* Optimize for pattern with * at end or before /. */
|
||||
if (c == EOS)
|
||||
if (flags & FNM_PATHNAME)
|
||||
return ((flags & FNM_LEADING_DIR) ||
|
||||
index(string, '/') == NULL ?
|
||||
0 : FNM_NOMATCH);
|
||||
else
|
||||
return (0);
|
||||
else if (c == '/' && flags & FNM_PATHNAME) {
|
||||
if ((string = index(string, '/')) == NULL)
|
||||
return (FNM_NOMATCH);
|
||||
break;
|
||||
}
|
||||
|
||||
/* General case, use recursion. */
|
||||
while ((test = *string) != EOS) {
|
||||
if (!fnmatch(pattern, string,
|
||||
flags & ~FNM_PERIOD))
|
||||
return (0);
|
||||
if (test == '/' && flags & FNM_PATHNAME)
|
||||
break;
|
||||
++string;
|
||||
}
|
||||
return (FNM_NOMATCH);
|
||||
case '[':
|
||||
if (*string == EOS)
|
||||
return (FNM_NOMATCH);
|
||||
if (*string == '/' && (flags & FNM_PATHNAME))
|
||||
return (FNM_NOMATCH);
|
||||
if (*string == '.' && (flags & FNM_PERIOD) &&
|
||||
(string == stringstart ||
|
||||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
switch (rangematch(pattern, *string, flags, &newp)) {
|
||||
case RANGE_ERROR:
|
||||
goto norm;
|
||||
case RANGE_MATCH:
|
||||
pattern = newp;
|
||||
break;
|
||||
case RANGE_NOMATCH:
|
||||
return (FNM_NOMATCH);
|
||||
}
|
||||
++string;
|
||||
break;
|
||||
case '\\':
|
||||
if (!(flags & FNM_NOESCAPE)) {
|
||||
if ((c = *pattern++) == EOS) {
|
||||
c = '\\';
|
||||
--pattern;
|
||||
}
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
norm:
|
||||
if (c == *string)
|
||||
;
|
||||
else if ((flags & FNM_CASEFOLD) &&
|
||||
(tolower((unsigned char)c) ==
|
||||
tolower((unsigned char)*string)))
|
||||
;
|
||||
else
|
||||
return (FNM_NOMATCH);
|
||||
string++;
|
||||
break;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static int
|
||||
rangematch(const char *pattern, char test, int flags, char **newp) {
|
||||
int negate, ok;
|
||||
char c, c2;
|
||||
|
||||
/*
|
||||
* A bracket expression starting with an unquoted circumflex
|
||||
* character produces unspecified results (IEEE 1003.2-1992,
|
||||
* 3.13.2). This implementation treats it like '!', for
|
||||
* consistency with the regular expression syntax.
|
||||
* J.T. Conklin (conklin@ngai.kaleida.com)
|
||||
*/
|
||||
if ( (negate = (*pattern == '!' || *pattern == '^')) )
|
||||
++pattern;
|
||||
|
||||
if (flags & FNM_CASEFOLD)
|
||||
test = tolower((unsigned char)test);
|
||||
|
||||
/*
|
||||
* A right bracket shall lose its special meaning and represent
|
||||
* itself in a bracket expression if it occurs first in the list.
|
||||
* -- POSIX.2 2.8.3.2
|
||||
*/
|
||||
ok = 0;
|
||||
c = *pattern++;
|
||||
do {
|
||||
if (c == '\\' && !(flags & FNM_NOESCAPE))
|
||||
c = *pattern++;
|
||||
if (c == EOS)
|
||||
return (RANGE_ERROR);
|
||||
|
||||
if (c == '/' && (flags & FNM_PATHNAME))
|
||||
return (RANGE_NOMATCH);
|
||||
|
||||
if (flags & FNM_CASEFOLD)
|
||||
c = tolower((unsigned char)c);
|
||||
|
||||
if (*pattern == '-'
|
||||
&& (c2 = *(pattern+1)) != EOS && c2 != ']') {
|
||||
pattern += 2;
|
||||
if (c2 == '\\' && !(flags & FNM_NOESCAPE))
|
||||
c2 = *pattern++;
|
||||
if (c2 == EOS)
|
||||
return (RANGE_ERROR);
|
||||
|
||||
if (flags & FNM_CASEFOLD)
|
||||
c2 = tolower((unsigned char)c2);
|
||||
|
||||
if (c <= test && test <= c2)
|
||||
ok = 1;
|
||||
} else if (c == test)
|
||||
ok = 1;
|
||||
} while ((c = *pattern++) != ']');
|
||||
|
||||
*newp = (char *)(uintptr_t)pattern;
|
||||
return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
|
||||
}
|
||||
58
contrib/dlz/modules/wildcard/testing/named.conf
Normal file
58
contrib/dlz/modules/wildcard/testing/named.conf
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
controls { };
|
||||
|
||||
options {
|
||||
directory ".";
|
||||
port 5300;
|
||||
pid-file "named.pid";
|
||||
session-keyfile "session.key";
|
||||
listen-on { any; };
|
||||
listen-on-v6 { none; };
|
||||
recursion no;
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
secret "1234abcd8765";
|
||||
algorithm hmac-md5;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 127.0.0.1 port 9953 allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
/*
|
||||
* This will match any zone name containing the string "example" and
|
||||
* ending with .com, such as "thisexample.com", "exampleofthat.com",
|
||||
* or "anexampleoftheotherthing.com".
|
||||
*/
|
||||
dlz "test" {
|
||||
database "dlopen ../dlz_wildcard_dynamic.so
|
||||
*example*.com 10.53.* 1800
|
||||
@ 3600 SOA {ns3.example.nil. support.example.nil. 42 14400 7200 2592000 600}
|
||||
@ 3600 NS ns3.example.nil.
|
||||
@ 3600 NS ns4.example.nil.
|
||||
@ 3600 NS ns8.example.nil.
|
||||
@ 3600 MX {5 mail.example.nil.}
|
||||
ftp 86400 A 192.0.0.1
|
||||
sql 86400 A 192.0.0.2
|
||||
tmp {} A 192.0.0.3
|
||||
www 86400 A 192.0.0.3
|
||||
www 86400 AAAA ::1
|
||||
txt 300 TXT {\"you requested $record$ in $zone$\"}
|
||||
* 86400 A 192.0.0.100";
|
||||
};
|
||||
|
|
@ -1205,7 +1205,6 @@ settask(dns_db_t *db, isc_task_t *task) {
|
|||
UNUSED(task);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* getoriginnode() is used by the update code to find the
|
||||
* dns_rdatatype_dnskey record for a zone
|
||||
|
|
@ -1222,7 +1221,7 @@ getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
|
|||
result = findnodeext(db, &sdlz->common.origin, ISC_FALSE,
|
||||
NULL, NULL, nodep);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed : %s",
|
||||
sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed: %s",
|
||||
isc_result_totext(result));
|
||||
return (result);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue