mirror of
https://github.com/isc-projects/bind9.git
synced 2026-04-26 08:39:00 -04:00
Move contributed DLZ modules into a separate repository
The DLZ modules are poorly maintained as we only ensure they can still be compiled, the DLZ interface is blocking, so anything that blocks the query to the database blocks the whole server and they should not be used except in testing. The DLZ interface itself should be scheduled for removal.
This commit is contained in:
parent
08138d53e4
commit
a6cce753e2
67 changed files with 20 additions and 13048 deletions
|
|
@ -316,9 +316,7 @@ stages:
|
|||
- *configure
|
||||
- *check_readline_setup
|
||||
- make -j${BUILD_PARALLEL_JOBS:-1} -k all V=1
|
||||
- test -z "${BUILD_CONTRIB}" || for DIR in contrib/dlz/modules/*; do test -f "${DIR}/Makefile" && CFLAGS="${CFLAGS} -Werror" make -C "${DIR}"; done
|
||||
- test -z "${RUN_MAKE_INSTALL}" || make DESTDIR="${INSTALL_PATH}" install
|
||||
- test -z "${RUN_MAKE_INSTALL}" -o -z "${BUILD_CONTRIB}" || for DIR in contrib/dlz/modules/*; do test -f "${DIR}/Makefile" && make -C "${DIR}" DESTDIR="${INSTALL_PATH}" install; done
|
||||
- test -z "${RUN_MAKE_INSTALL}" || DESTDIR="${INSTALL_PATH}" sh util/check-make-install
|
||||
- if [[ "${CFLAGS}" == *"-fsanitize=address"* ]]; then ( ! grep -F AddressSanitizer config.log ); fi
|
||||
- test -z "${CROSS_COMPILATION}" || grep -F -A 1 "checking whether we are cross compiling" config.log | grep -q "result.*yes"
|
||||
|
|
@ -886,7 +884,6 @@ gcc:tarball:nosphinx:
|
|||
|
||||
gcc:bookworm:amd64:
|
||||
variables:
|
||||
BUILD_CONTRIB: 1
|
||||
CC: gcc
|
||||
CFLAGS: "${CFLAGS_COMMON} --coverage -O0"
|
||||
EXTRA_CONFIGURE: "--with-libidn2 ${WITH_READLINE_LIBEDIT}"
|
||||
|
|
@ -1343,7 +1340,6 @@ tsan:stress:
|
|||
|
||||
clang:bookworm:amd64:
|
||||
variables:
|
||||
BUILD_CONTRIB: 1
|
||||
CC: ${CLANG}
|
||||
CFLAGS: "${CFLAGS_COMMON} -Wenum-conversion -DOPENSSL_API_COMPAT=10100"
|
||||
# See https://gitlab.isc.org/isc-projects/bind9/-/issues/3444
|
||||
|
|
|
|||
|
|
@ -23,9 +23,8 @@ be fixed as time permits.
|
|||
|
||||
- dlz/modules
|
||||
|
||||
Dynamically linkable DLZ modules that can be configured into
|
||||
named at runtime, enabling access to external data sources including
|
||||
LDAP, MySQL, Berkeley DB, perl scripts, etc.
|
||||
Dynamically linkable DLZ modules have been moved into a separate
|
||||
repository located at https://gitlab.isc.org/isc-projects/dlz-modules.
|
||||
|
||||
- gitchangelog/
|
||||
|
||||
|
|
|
|||
1
contrib/dlz/.gitignore
vendored
1
contrib/dlz/.gitignore
vendored
|
|
@ -1 +0,0 @@
|
|||
!Makefile
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
# for building the dlz_example driver we don't use
|
||||
# the bind9 build structure as the aim is to provide an
|
||||
# example that is separable from the bind9 source tree
|
||||
|
||||
# this means this Makefile is not portable, so the testsuite
|
||||
# skips this test on platforms where it doesn't build
|
||||
|
||||
CFLAGS += -Wall -fPIC -g
|
||||
|
||||
all: dlz_example.so
|
||||
|
||||
dlz_example.so: dlz_example.o
|
||||
$(CC) $(CFLAGS) -shared -o dlz_example.so dlz_example.o
|
||||
|
||||
clean:
|
||||
rm -f dlz_example.o dlz_example.so
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
<!--
|
||||
Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
|
||||
SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
See the COPYRIGHT file distributed with this work for additional
|
||||
information regarding copyright ownership.
|
||||
-->
|
||||
|
||||
OVERVIEW:
|
||||
|
||||
DLZ (Dynamically Loadable Zones) is an extension to BIND 9 that
|
||||
allows zone data to be retrieved directly from an external database.
|
||||
There is no required format or schema. DLZ drivers exist for several
|
||||
different database backends including PostgreSQL, MySQL, and LDAP and
|
||||
can be written for any other.
|
||||
|
||||
Historically, DLZ drivers had to be statically linked with the named
|
||||
binary and were turned on via a configure option at compile time (for
|
||||
example, "configure --with-dlz-ldap"). Currently, the drivers provided
|
||||
in the BIND 9 tarball in contrib/dlz/drivers are still linked this way.
|
||||
|
||||
However, as of BIND 9.8, it is also possible to link some DLZ modules
|
||||
dynamically at runtime, via the DLZ "dlopen" driver, which acts as a
|
||||
generic wrapper around a shared object that implements the DLZ API. The
|
||||
"dlopen" driver is linked into named by default, so configure options are
|
||||
no longer necessary unless using older DLZ drivers.
|
||||
|
||||
When the DLZ module provides data to named, it does so in text format.
|
||||
The response is converted to DNS wire format by named. This conversion,
|
||||
and the lack of any internal caching, places significant limits on the
|
||||
query performance of DLZ modules. Consequently, DLZ is not recommended
|
||||
for use on high-volume servers. However, it can be used in a hidden
|
||||
primary configuration, with secondaries retrieving zone updates via AXFR.
|
||||
(Note, however, that DLZ has no built-in support for DNS notify; secondaries
|
||||
are not automatically informed of changes to the zones in the database.)
|
||||
|
||||
CONFIGURING DLZ:
|
||||
|
||||
A DLZ database is configured with a "dlz" statement in named.conf.
|
||||
|
||||
dlz example {
|
||||
database "dlopen driver.so <args>";
|
||||
search yes;
|
||||
};
|
||||
|
||||
This specifies a DLZ module to search when answering queries; the module
|
||||
is implemented in "driver.so" and is loaded at runtime by the dlopen DLZ
|
||||
driver. Multiple "dlz" statements can be specified; when answering a
|
||||
query, all DLZ modules with the "search" option set to "yes" will be
|
||||
checked for an answer, and the best available answer will be returned
|
||||
to the client.
|
||||
|
||||
The "search" option in this example can be omitted, as "yes" is the
|
||||
default value. If it is set to "no", then this DLZ module is *not*
|
||||
searched for best-match when a query is received. Instead, zones in
|
||||
this DLZ must be separately specified in a zone statement. This can
|
||||
be useful when conventional zone semantics are desired but you wish
|
||||
to use a different back-end storage mechanism than the standard zone
|
||||
database. For example, to use a DLZ module for an NXDOMAIN redirection
|
||||
zone:
|
||||
|
||||
dlz other {
|
||||
database "dlopen driver.so <args>";
|
||||
search no;
|
||||
};
|
||||
|
||||
zone "." {
|
||||
type redirect;
|
||||
dlz other;
|
||||
};
|
||||
|
||||
EXAMPLE DRIVER:
|
||||
|
||||
This directory contains an example of an externally-lodable DLZ module,
|
||||
dlz_example.c, which demonstrates the features of the DLZ API. It sets up
|
||||
a single zone, whose name is configured in named.conf. The zone can answer
|
||||
queries and AXFR requests, and accept DDNS updates.
|
||||
|
||||
By default, at runtime, the zone implemented by this driver will contain
|
||||
an SOA, NS, and a single A record at the apex. If configured in named.conf
|
||||
to use the name "example.nil", then, the zone will look like this:
|
||||
|
||||
example.nil. 3600 IN SOA example.nil. hostmaster.example.nil. (
|
||||
123 900 600 86400 3600
|
||||
)
|
||||
example.nil. 3600 IN NS example.nil.
|
||||
example.nil. 1800 IN A 10.53.0.1
|
||||
|
||||
The driver is also capable of retrieving information about the querying
|
||||
client, and altering its response on the basis of this information. To
|
||||
demonstrate this feature, the example driver responds to queries for
|
||||
"source-addr.<zonename>/TXT" with the source address of the query.
|
||||
Note, however, that this record will *not* be included in AXFR or ANY
|
||||
responses. (Normally, this feature would be used to alter responses in
|
||||
some other fashion, e.g., by providing different address records for
|
||||
a particular name depending on the network from which the query arrived.)
|
||||
|
||||
DYNAMIC UPDATES AND TRANSACTIONS:
|
||||
|
||||
If a DLZ module wants to implement dynamic DNS updates (DDNS), the
|
||||
normal calling sequence is
|
||||
- dlz_newversion (start a 'transaction')
|
||||
- dlz_addrdataset (add records)
|
||||
- dlz_subrdataset (remove records)
|
||||
- dlz_closeversion (end a 'transaction')
|
||||
|
||||
However, BIND may also query the database during the transaction
|
||||
(e.g., to check prerequisites), and your DLZ might need to know whether
|
||||
the lookup is against the pre-existing data, or the new data.
|
||||
dlz_lookup() doesn't give you access to the 'versionp' pointer
|
||||
directly, so it must be passed via 'clientinfo' structure if
|
||||
it is needed.
|
||||
|
||||
The dlz_example.c code has sample code to show how to get the 'versionp'
|
||||
pointer from within dlz_lookup(). If it's set to NULL, we query
|
||||
the standard database; if non-NULL, we query against the in-flight
|
||||
data within the appropriate uncommitted transaction.
|
||||
|
||||
IMPLEMENTATION NOTES:
|
||||
|
||||
The minimal set of type definitions, prototypes, and macros needed
|
||||
for implementing a DLZ driver is in ../modules/dlz_minimal.h. Copy this
|
||||
header file into your source tree when creating an external DLZ module.
|
||||
|
||||
The DLZ dlopen driver provides a set of callback functions:
|
||||
|
||||
- void log(int level, const char *fmt, ...);
|
||||
|
||||
Writes the specified string to the named log, at the specified
|
||||
log level. Uses printf() format semantics.
|
||||
|
||||
- isc_result_t putrr(dns_sdlzlookup_t *lookup, const char *type,
|
||||
dns_ttl_t ttl, const char *data);
|
||||
|
||||
Puts a DNS resource record into the query response, which
|
||||
referenced by the opaque structure 'lookup' provided by named.
|
||||
|
||||
- isc_result_t putnamedrr(dns_sdlzallnotes_t *allnodes,
|
||||
const char *name, const char *type,
|
||||
dns_ttl_t ttl, const char *data);
|
||||
|
||||
Puts a DNS resource record into an AXFR response, which is
|
||||
referenced by the opaque structure 'allnodes' provided by named.
|
||||
|
||||
- isc_result_t writeable_zone(dns_view_t *view, const char *zone_name);
|
||||
|
||||
Allows the DLZ module to inform named that a given zone can receive
|
||||
DDNS updates. (Note: This is not currently supported for DLZ
|
||||
databases that are configured as 'search no;')
|
||||
|
||||
The external DLZ module can define the following functions (some of these
|
||||
are mandatory, others optional).
|
||||
|
||||
- int dlz_version(unsigned int *flags);
|
||||
|
||||
Required for alL external DLZ modules, to indicate the version number
|
||||
of the DLZ dlopen driver that this module supports. It should return
|
||||
the value DLZ_DLOPEN_VERSION, which is defined in the file
|
||||
contrib/dlz/modules/dlz_minimal.h and is currently 3. 'flags' is
|
||||
updated to indicate capabilities of the module. In particular, if
|
||||
the module is thread-safe then it sets 'flags' to include
|
||||
DNS_SDLZFLAG_THREADSAFE. (Other capability flags may be added in
|
||||
the future.)
|
||||
|
||||
- isc_result_t dlz_create(const char *dlzname,
|
||||
unsigned int argc, char *argv[],
|
||||
void **dbdata, ...);
|
||||
|
||||
Required for all external DLZ modules; this call initializes the
|
||||
module.
|
||||
|
||||
- void dlz_destroy(void *dbdata);
|
||||
|
||||
Optional. If supplied, this will be called when the driver is
|
||||
unloaded.
|
||||
|
||||
- isc_result_t dlz_findzonedb(void *dbdata, const char *name,
|
||||
dns_clientinfomethods_t *methods,
|
||||
dns_clientinfo_t *clientinfo);
|
||||
|
||||
Required for all external DLZ modules. This indicates whether
|
||||
the DLZ module can answer for the given name. Returns ISC_R_SUCCESS
|
||||
if so, and ISC_R_NOTFOUND if not. As an optimization, it can
|
||||
also return ISC_R_NOMORE: this indicates that the DLZ module has
|
||||
no data for the given name or for any name above it in the DNS.
|
||||
This prevents named from searching for a zone cut.
|
||||
|
||||
- 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);
|
||||
|
||||
Required for all external DLZ modules. This carries out the database
|
||||
lookup for a query.
|
||||
|
||||
- isc_result_t dlz_allowzonexfr(void *dbdata, const char *name,
|
||||
const char *client);
|
||||
|
||||
Optional. Supply this if you want the module to support AXFR
|
||||
for the specified zone and client. A return value of ISC_R_SUCCESS
|
||||
means AXFR is allowed, any other value means it isn't.
|
||||
|
||||
- isc_result_t dlz_allnodes(const char *zone, void *dbdata,
|
||||
dns_sdlzallnodes_t *allnodes);
|
||||
|
||||
Optional, but must be supplied dlz_allowzonexfr() is. This function
|
||||
returns all nodes in the zone in order to perform a zone transfer.
|
||||
|
||||
- isc_result_t dlz_newversion(const char *zone, void *dbdata,
|
||||
void **versionp);
|
||||
|
||||
Optional. Supply this if you want the module to support DDNS
|
||||
updates. This function starts a transaction in the database.
|
||||
|
||||
|
||||
- void dlz_closeversion(const char *zone, bool commit,
|
||||
void *dbdata, void **versionp);
|
||||
|
||||
Optional, but must be supplied if dlz_newversion() is. This function
|
||||
closes a transaction. 'commit' indicates whether to commit the changes
|
||||
to the database, or ignore them.
|
||||
|
||||
- isc_result_t dlz_configure(dns_view_t *view, void *dbdata);
|
||||
|
||||
Optional, but must be supplied in order to support DDNS updates.
|
||||
|
||||
- bool dlz_ssumatch(const char *signer, const char *name,
|
||||
const char *tcpaddr, const char *type,
|
||||
const char *key, uint32_t keydatalen,
|
||||
uint8_t *keydata, void *dbdata);
|
||||
|
||||
Optional, but must be supplied in order to support DDNS updates.
|
||||
|
||||
- isc_result_t dlz_addrdataset(const char *name, const char *rdatastr,
|
||||
void *dbdata, void *version);
|
||||
|
||||
Optional, but must be supplied in order to support DDNS updates.
|
||||
Adds the data in 'rdatastr' to a database node.
|
||||
|
||||
- isc_result_t dlz_subrdataset(const char *name, const char *rdatastr,
|
||||
void *dbdata, void *version);
|
||||
|
||||
Optional, but must be supplied in order to support DDNS updates.
|
||||
Removes the data in 'rdatastr' from a database node.
|
||||
|
||||
- isc_result_t dlz_delrdataset(const char *name, const char *rdatastr,
|
||||
void *dbdata, void *version);
|
||||
|
||||
Optional, but must be supplied in order to support DDNS updates.
|
||||
Deletes all data matching the type specified in 'rdatastr' from
|
||||
the database.
|
||||
|
|
@ -1,820 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This provides a very simple example of an external loadable DLZ
|
||||
* driver, with update support.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../modules/include/dlz_minimal.h"
|
||||
|
||||
#define CHECK(x) \
|
||||
do { \
|
||||
result = (x); \
|
||||
if (result != ISC_R_SUCCESS) \
|
||||
goto failure; \
|
||||
} while (0)
|
||||
|
||||
/* For this simple example, use fixed sized strings */
|
||||
struct record {
|
||||
char name[100];
|
||||
char type[10];
|
||||
char data[200];
|
||||
dns_ttl_t ttl;
|
||||
};
|
||||
|
||||
#define MAX_RECORDS 100
|
||||
|
||||
struct dlz_example_data {
|
||||
char *zone_name;
|
||||
|
||||
/* An example driver doesn't need good memory management :-) */
|
||||
struct record current[MAX_RECORDS];
|
||||
struct record adds[MAX_RECORDS];
|
||||
struct record deletes[MAX_RECORDS];
|
||||
|
||||
bool transaction_started;
|
||||
|
||||
/* 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;
|
||||
};
|
||||
|
||||
static bool
|
||||
single_valued(const char *type) {
|
||||
const char *single[] = { "soa", "cname", NULL };
|
||||
int i;
|
||||
|
||||
for (i = 0; single[i]; i++) {
|
||||
if (strcasecmp(single[i], type) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a record to a list
|
||||
*/
|
||||
static isc_result_t
|
||||
add_name(struct dlz_example_data *state, struct record *list, const char *name,
|
||||
const char *type, dns_ttl_t ttl, const char *data) {
|
||||
int i;
|
||||
bool single = single_valued(type);
|
||||
int first_empty = -1;
|
||||
|
||||
for (i = 0; i < MAX_RECORDS; i++) {
|
||||
if (first_empty == -1 && strlen(list[i].name) == 0U) {
|
||||
first_empty = i;
|
||||
}
|
||||
if (strcasecmp(list[i].name, name) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (strcasecmp(list[i].type, type) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (!single && strcasecmp(list[i].data, data) != 0) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (i == MAX_RECORDS && first_empty != -1) {
|
||||
i = first_empty;
|
||||
}
|
||||
if (i == MAX_RECORDS) {
|
||||
if (state->log != NULL) {
|
||||
state->log(ISC_LOG_ERROR, "dlz_example: out of record "
|
||||
"space");
|
||||
}
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
if (strlen(name) >= sizeof(list[i].name) ||
|
||||
strlen(type) >= sizeof(list[i].type) ||
|
||||
strlen(data) >= sizeof(list[i].data))
|
||||
{
|
||||
return ISC_R_NOSPACE;
|
||||
}
|
||||
|
||||
strncpy(list[i].name, name, sizeof(list[i].name));
|
||||
list[i].name[sizeof(list[i].name) - 1] = '\0';
|
||||
|
||||
strncpy(list[i].type, type, sizeof(list[i].type));
|
||||
list[i].type[sizeof(list[i].type) - 1] = '\0';
|
||||
|
||||
strncpy(list[i].data, data, sizeof(list[i].data));
|
||||
list[i].data[sizeof(list[i].data) - 1] = '\0';
|
||||
|
||||
list[i].ttl = ttl;
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a record from a list
|
||||
*/
|
||||
static isc_result_t
|
||||
del_name(struct dlz_example_data *state, struct record *list, const char *name,
|
||||
const char *type, dns_ttl_t ttl, const char *data) {
|
||||
int i;
|
||||
|
||||
UNUSED(state);
|
||||
|
||||
for (i = 0; i < MAX_RECORDS; i++) {
|
||||
if (strcasecmp(name, list[i].name) == 0 &&
|
||||
strcasecmp(type, list[i].type) == 0 &&
|
||||
strcasecmp(data, list[i].data) == 0 && ttl == list[i].ttl)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == MAX_RECORDS) {
|
||||
return ISC_R_NOTFOUND;
|
||||
}
|
||||
memset(&list[i], 0, sizeof(struct record));
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
fmt_address(isc_sockaddr_t *addr, char *buffer, size_t size) {
|
||||
char addr_buf[100];
|
||||
const char *ret;
|
||||
uint16_t port = 0;
|
||||
|
||||
switch (addr->type.sa.sa_family) {
|
||||
case AF_INET:
|
||||
port = ntohs(addr->type.sin.sin_port);
|
||||
ret = inet_ntop(AF_INET, &addr->type.sin.sin_addr, addr_buf,
|
||||
sizeof(addr_buf));
|
||||
break;
|
||||
case AF_INET6:
|
||||
port = ntohs(addr->type.sin6.sin6_port);
|
||||
ret = inet_ntop(AF_INET6, &addr->type.sin6.sin6_addr, addr_buf,
|
||||
sizeof(addr_buf));
|
||||
break;
|
||||
default:
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
if (ret == NULL) {
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
snprintf(buffer, size, "%s#%u", addr_buf, port);
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the version of the API
|
||||
*/
|
||||
int
|
||||
dlz_version(unsigned int *flags) {
|
||||
UNUSED(flags);
|
||||
return DLZ_DLOPEN_VERSION;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remember a helper function from the bind9 dlz_dlopen driver
|
||||
*/
|
||||
static void
|
||||
b9_add_helper(struct dlz_example_data *state, const char *helper_name,
|
||||
void *ptr) {
|
||||
if (strcmp(helper_name, "log") == 0) {
|
||||
state->log = (log_t *)ptr;
|
||||
}
|
||||
if (strcmp(helper_name, "putrr") == 0) {
|
||||
state->putrr = (dns_sdlz_putrr_t *)ptr;
|
||||
}
|
||||
if (strcmp(helper_name, "putnamedrr") == 0) {
|
||||
state->putnamedrr = (dns_sdlz_putnamedrr_t *)ptr;
|
||||
}
|
||||
if (strcmp(helper_name, "writeable_zone") == 0) {
|
||||
state->writeable_zone = (dns_dlz_writeablezone_t *)ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called to initialize the driver
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata,
|
||||
...) {
|
||||
struct dlz_example_data *state;
|
||||
const char *helper_name;
|
||||
va_list ap;
|
||||
char soa_data[200];
|
||||
const char *extra;
|
||||
isc_result_t result;
|
||||
int n;
|
||||
|
||||
UNUSED(dlzname);
|
||||
|
||||
state = calloc(1, sizeof(struct dlz_example_data));
|
||||
if (state == NULL) {
|
||||
return ISC_R_NOMEMORY;
|
||||
}
|
||||
|
||||
/* Fill in the helper functions */
|
||||
va_start(ap, dbdata);
|
||||
while ((helper_name = va_arg(ap, const char *)) != NULL) {
|
||||
b9_add_helper(state, helper_name, va_arg(ap, void *));
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
if (argc < 2 || argv[1][0] == '\0') {
|
||||
if (state->log != NULL) {
|
||||
state->log(ISC_LOG_ERROR, "dlz_example: please specify "
|
||||
"a zone name");
|
||||
}
|
||||
dlz_destroy(state);
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
/* Ensure zone name is absolute */
|
||||
state->zone_name = malloc(strlen(argv[1]) + 2);
|
||||
if (state->zone_name == NULL) {
|
||||
free(state);
|
||||
return ISC_R_NOMEMORY;
|
||||
}
|
||||
if (argv[1][strlen(argv[1]) - 1] == '.') {
|
||||
strcpy(state->zone_name, argv[1]);
|
||||
} else {
|
||||
sprintf(state->zone_name, "%s.", argv[1]);
|
||||
}
|
||||
|
||||
if (strcmp(state->zone_name, ".") == 0) {
|
||||
extra = ".root";
|
||||
} else {
|
||||
extra = ".";
|
||||
}
|
||||
|
||||
n = sprintf(soa_data, "%s hostmaster%s%s 123 900 600 86400 3600",
|
||||
state->zone_name, extra, state->zone_name);
|
||||
|
||||
if (n < 0) {
|
||||
CHECK(ISC_R_FAILURE);
|
||||
}
|
||||
if ((unsigned int)n >= sizeof(soa_data)) {
|
||||
CHECK(ISC_R_NOSPACE);
|
||||
}
|
||||
|
||||
add_name(state, &state->current[0], state->zone_name, "soa", 3600,
|
||||
soa_data);
|
||||
add_name(state, &state->current[0], state->zone_name, "ns", 3600,
|
||||
state->zone_name);
|
||||
add_name(state, &state->current[0], state->zone_name, "a", 1800,
|
||||
"10.53.0.1");
|
||||
|
||||
if (state->log != NULL) {
|
||||
state->log(ISC_LOG_INFO, "dlz_example: started for zone %s",
|
||||
state->zone_name);
|
||||
}
|
||||
|
||||
*dbdata = state;
|
||||
return ISC_R_SUCCESS;
|
||||
|
||||
failure:
|
||||
free(state);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Shut down the backend
|
||||
*/
|
||||
void
|
||||
dlz_destroy(void *dbdata) {
|
||||
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
||||
|
||||
if (state->log != NULL) {
|
||||
state->log(ISC_LOG_INFO, "dlz_example: shutting down zone %s",
|
||||
state->zone_name);
|
||||
}
|
||||
free(state->zone_name);
|
||||
free(state);
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we handle a given zone
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_findzonedb(void *dbdata, const char *name, dns_clientinfomethods_t *methods,
|
||||
dns_clientinfo_t *clientinfo) {
|
||||
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
||||
isc_sockaddr_t *src;
|
||||
char addrbuf[100];
|
||||
char absolute[1024];
|
||||
|
||||
strcpy(addrbuf, "unknown");
|
||||
if (methods != NULL && methods->sourceip != NULL &&
|
||||
methods->version - methods->age <= DNS_CLIENTINFOMETHODS_VERSION &&
|
||||
DNS_CLIENTINFOMETHODS_VERSION <= methods->version)
|
||||
{
|
||||
methods->sourceip(clientinfo, &src);
|
||||
fmt_address(src, addrbuf, sizeof(addrbuf));
|
||||
}
|
||||
state->log(ISC_LOG_INFO, "dlz_example: findzonedb connection from: %s",
|
||||
addrbuf);
|
||||
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: dlz_findzonedb called with name '%s' "
|
||||
"in zone DB '%s'",
|
||||
name, state->zone_name);
|
||||
|
||||
/*
|
||||
* Returning ISC_R_NOTFOUND will cause the query logic to
|
||||
* check the database for parent names, looking for zone cuts.
|
||||
*
|
||||
* Returning ISC_R_NOMORE prevents the query logic from doing
|
||||
* this; it will move onto the next database after a single query.
|
||||
*/
|
||||
if (strcasecmp(name, "test.example.com") == 0) {
|
||||
return ISC_R_NOMORE;
|
||||
}
|
||||
|
||||
/*
|
||||
* For example.net, only return ISC_R_NOMORE when queried
|
||||
* from 10.53.0.1.
|
||||
*/
|
||||
if (strcasecmp(name, "test.example.net") == 0 &&
|
||||
strncmp(addrbuf, "10.53.0.1", 9) == 0)
|
||||
{
|
||||
return ISC_R_NOMORE;
|
||||
}
|
||||
|
||||
if (strcasecmp(state->zone_name, name) == 0) {
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
snprintf(absolute, sizeof(absolute), "%s.", name);
|
||||
if (strcasecmp(state->zone_name, absolute) == 0) {
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
return ISC_R_NOTFOUND;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up one record in the sample database.
|
||||
*
|
||||
* If the queryname is "source-addr", send back a TXT record containing
|
||||
* the address of the client; this demonstrates the use of 'methods'
|
||||
* and 'clientinfo'.
|
||||
*
|
||||
* If the queryname is "too-long", send back a TXT record that's too long
|
||||
* to process; this should result in a SERVFAIL when queried.
|
||||
*/
|
||||
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) {
|
||||
isc_result_t result;
|
||||
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
||||
bool found = false;
|
||||
void *dbversion = NULL;
|
||||
isc_sockaddr_t *src;
|
||||
char full_name[256];
|
||||
char buf[512];
|
||||
int i;
|
||||
|
||||
UNUSED(zone);
|
||||
|
||||
if (state->putrr == NULL) {
|
||||
return ISC_R_NOTIMPLEMENTED;
|
||||
}
|
||||
|
||||
if (strcmp(name, "@") == 0) {
|
||||
strncpy(full_name, state->zone_name, 255);
|
||||
full_name[255] = '\0';
|
||||
} else {
|
||||
snprintf(full_name, 255, "%s.%s", name, state->zone_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we need to know the database version (as set in
|
||||
* the 'newversion' dlz function) we can pick it up from the
|
||||
* clientinfo.
|
||||
*
|
||||
* This allows a lookup to query the correct version of the DNS
|
||||
* data, if the DLZ can differentiate between versions.
|
||||
*
|
||||
* For example, if a new database transaction is created by
|
||||
* 'newversion', the lookup should query within the same
|
||||
* transaction scope if it can.
|
||||
*
|
||||
* If the DLZ only operates on 'live' data, then version
|
||||
* wouldn't necessarily be needed.
|
||||
*/
|
||||
if (clientinfo != NULL && clientinfo->version >= 2) {
|
||||
dbversion = clientinfo->dbversion;
|
||||
if (dbversion != NULL && *(bool *)dbversion) {
|
||||
state->log(ISC_LOG_INFO, "dlz_example: lookup against "
|
||||
"live "
|
||||
"transaction\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(name, "source-addr") == 0) {
|
||||
char ecsbuf[DNS_ECS_FORMATSIZE] = "not supported";
|
||||
strncpy(buf, "unknown", sizeof(buf));
|
||||
if (methods != NULL && methods->sourceip != NULL &&
|
||||
(methods->version - methods->age <=
|
||||
DNS_CLIENTINFOMETHODS_VERSION) &&
|
||||
DNS_CLIENTINFOMETHODS_VERSION <= methods->version)
|
||||
{
|
||||
methods->sourceip(clientinfo, &src);
|
||||
fmt_address(src, buf, sizeof(buf));
|
||||
}
|
||||
if (clientinfo != NULL && clientinfo->version >= 3) {
|
||||
if (clientinfo->ecs.addr.family != AF_UNSPEC) {
|
||||
dns_ecs_format(&clientinfo->ecs, ecsbuf,
|
||||
sizeof(ecsbuf));
|
||||
} else {
|
||||
snprintf(ecsbuf, sizeof(ecsbuf), "%s",
|
||||
"not present");
|
||||
}
|
||||
}
|
||||
i = strlen(buf);
|
||||
snprintf(buf + i, sizeof(buf) - i - 1, " ECS %s", ecsbuf);
|
||||
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: lookup connection from: %s", buf);
|
||||
|
||||
found = true;
|
||||
result = state->putrr(lookup, "TXT", 0, buf);
|
||||
/* We could also generate a CNAME RR:
|
||||
snprintf(buf, sizeof(buf), "%s.redirect.example.", ecsbuf);
|
||||
result = state->putrr(lookup, "CNAME", 0, buf); */
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(name, "too-long") == 0) {
|
||||
for (i = 0; i < 511; i++) {
|
||||
buf[i] = 'x';
|
||||
}
|
||||
buf[i] = '\0';
|
||||
found = true;
|
||||
result = state->putrr(lookup, "TXT", 0, buf);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_RECORDS; i++) {
|
||||
if (strcasecmp(state->current[i].name, full_name) == 0) {
|
||||
found = true;
|
||||
result = state->putrr(lookup, state->current[i].type,
|
||||
state->current[i].ttl,
|
||||
state->current[i].data);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
return ISC_R_NOTFOUND;
|
||||
}
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if a zone transfer is allowed
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_allowzonexfr(void *dbdata, const char *name, const char *client) {
|
||||
UNUSED(client);
|
||||
|
||||
/* Just say yes for all our zones */
|
||||
return dlz_findzonedb(dbdata, name, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform a zone transfer
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes) {
|
||||
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
||||
int i;
|
||||
|
||||
UNUSED(zone);
|
||||
|
||||
if (state->putnamedrr == NULL) {
|
||||
return ISC_R_NOTIMPLEMENTED;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_RECORDS; i++) {
|
||||
isc_result_t result;
|
||||
if (strlen(state->current[i].name) == 0U) {
|
||||
continue;
|
||||
}
|
||||
result = state->putnamedrr(allnodes, state->current[i].name,
|
||||
state->current[i].type,
|
||||
state->current[i].ttl,
|
||||
state->current[i].data);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start a transaction
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_newversion(const char *zone, void *dbdata, void **versionp) {
|
||||
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
||||
|
||||
if (state->transaction_started) {
|
||||
if (state->log != NULL) {
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: transaction already "
|
||||
"started for zone %s",
|
||||
zone);
|
||||
}
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
state->transaction_started = true;
|
||||
*versionp = (void *)&state->transaction_started;
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* End a transaction
|
||||
*/
|
||||
void
|
||||
dlz_closeversion(const char *zone, bool commit, void *dbdata, void **versionp) {
|
||||
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
||||
|
||||
if (!state->transaction_started) {
|
||||
if (state->log != NULL) {
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: transaction not "
|
||||
"started for zone %s",
|
||||
zone);
|
||||
}
|
||||
*versionp = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
state->transaction_started = false;
|
||||
|
||||
*versionp = NULL;
|
||||
|
||||
if (commit) {
|
||||
int i;
|
||||
if (state->log != NULL) {
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: committing "
|
||||
"transaction on zone %s",
|
||||
zone);
|
||||
}
|
||||
for (i = 0; i < MAX_RECORDS; i++) {
|
||||
if (strlen(state->deletes[i].name) > 0U) {
|
||||
(void)del_name(state, &state->current[0],
|
||||
state->deletes[i].name,
|
||||
state->deletes[i].type,
|
||||
state->deletes[i].ttl,
|
||||
state->deletes[i].data);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < MAX_RECORDS; i++) {
|
||||
if (strlen(state->adds[i].name) > 0U) {
|
||||
(void)add_name(state, &state->current[0],
|
||||
state->adds[i].name,
|
||||
state->adds[i].type,
|
||||
state->adds[i].ttl,
|
||||
state->adds[i].data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (state->log != NULL) {
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: cancelling "
|
||||
"transaction on zone %s",
|
||||
zone);
|
||||
}
|
||||
}
|
||||
memset(state->adds, 0, sizeof(state->adds));
|
||||
memset(state->deletes, 0, sizeof(state->deletes));
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure a writeable zone
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, void *dbdata) {
|
||||
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
||||
isc_result_t result;
|
||||
|
||||
if (state->log != NULL) {
|
||||
state->log(ISC_LOG_INFO, "dlz_example: starting configure");
|
||||
}
|
||||
|
||||
if (state->writeable_zone == NULL) {
|
||||
if (state->log != NULL) {
|
||||
state->log(ISC_LOG_INFO, "dlz_example: no "
|
||||
"writeable_zone method "
|
||||
"available");
|
||||
}
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
result = state->writeable_zone(view, dlzdb, state->zone_name);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (state->log != NULL) {
|
||||
state->log(ISC_LOG_ERROR,
|
||||
"dlz_example: failed to "
|
||||
"configure zone %s",
|
||||
state->zone_name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (state->log != NULL) {
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: configured writeable "
|
||||
"zone %s",
|
||||
state->zone_name);
|
||||
}
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Authorize a zone update
|
||||
*/
|
||||
bool
|
||||
dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr,
|
||||
const char *type, const char *key, uint32_t keydatalen,
|
||||
unsigned char *keydata, void *dbdata) {
|
||||
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
||||
|
||||
UNUSED(tcpaddr);
|
||||
UNUSED(type);
|
||||
UNUSED(key);
|
||||
UNUSED(keydatalen);
|
||||
UNUSED(keydata);
|
||||
|
||||
if (strncmp(name, "deny.", 5) == 0) {
|
||||
if (state->log != NULL) {
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: denying update "
|
||||
"of name=%s by %s",
|
||||
name, signer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (state->log != NULL) {
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: allowing update of "
|
||||
"name=%s by %s",
|
||||
name, signer);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
modrdataset(struct dlz_example_data *state, const char *name,
|
||||
const char *rdatastr, struct record *list) {
|
||||
char *full_name, *dclass, *type, *data, *ttlstr, *buf;
|
||||
char absolute[1024];
|
||||
isc_result_t result;
|
||||
char *saveptr = NULL;
|
||||
|
||||
buf = strdup(rdatastr);
|
||||
if (buf == NULL) {
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* The format is:
|
||||
* FULLNAME\tTTL\tDCLASS\tTYPE\tDATA
|
||||
*
|
||||
* The DATA field is space separated, and is in the data format
|
||||
* for the type used by dig
|
||||
*/
|
||||
|
||||
full_name = strtok_r(buf, "\t", &saveptr);
|
||||
if (full_name == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
ttlstr = strtok_r(NULL, "\t", &saveptr);
|
||||
if (ttlstr == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
dclass = strtok_r(NULL, "\t", &saveptr);
|
||||
if (dclass == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
type = strtok_r(NULL, "\t", &saveptr);
|
||||
if (type == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
data = strtok_r(NULL, "\t", &saveptr);
|
||||
if (data == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (name[strlen(name) - 1] != '.') {
|
||||
snprintf(absolute, sizeof(absolute), "%s.", name);
|
||||
name = absolute;
|
||||
}
|
||||
|
||||
result = add_name(state, list, name, type, strtoul(ttlstr, NULL, 10),
|
||||
data);
|
||||
free(buf);
|
||||
return result;
|
||||
|
||||
error:
|
||||
free(buf);
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dlz_addrdataset(const char *name, const char *rdatastr, void *dbdata,
|
||||
void *version) {
|
||||
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
||||
|
||||
if (version != (void *)&state->transaction_started) {
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
if (state->log != NULL) {
|
||||
state->log(ISC_LOG_INFO, "dlz_example: adding rdataset %s '%s'",
|
||||
name, rdatastr);
|
||||
}
|
||||
|
||||
return modrdataset(state, name, rdatastr, &state->adds[0]);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dlz_subrdataset(const char *name, const char *rdatastr, void *dbdata,
|
||||
void *version) {
|
||||
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
||||
|
||||
if (version != (void *)&state->transaction_started) {
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
if (state->log != NULL) {
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: subtracting rdataset "
|
||||
"%s '%s'",
|
||||
name, rdatastr);
|
||||
}
|
||||
|
||||
return modrdataset(state, name, rdatastr, &state->deletes[0]);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dlz_delrdataset(const char *name, const char *type, void *dbdata,
|
||||
void *version) {
|
||||
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
||||
|
||||
if (version != (void *)&state->transaction_started) {
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
if (state->log != NULL) {
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: deleting rdataset %s "
|
||||
"of type %s",
|
||||
name, type);
|
||||
}
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a sample named.conf file that uses the DLZ module defined in
|
||||
* dlz_example.c. It sets up a zone 'example.nil' which can accept DDNS
|
||||
* updates.
|
||||
*
|
||||
* By default, when run, the zone contains the following records:
|
||||
*
|
||||
* example.nil. 3600 IN SOA example.nil. hostmaster.example.nil. (
|
||||
* 123 900 600 86400 3600
|
||||
* )
|
||||
* example.nil. 3600 IN NS example.nil.
|
||||
* example.nil. 1800 IN A 10.53.0.1
|
||||
*
|
||||
* Additionally, a query for 'source-addr.example.nil/TXT' is always
|
||||
* answered with the source address of the query. This is used to
|
||||
* demonstrate the code that retrieves client information from the
|
||||
* caller.
|
||||
*
|
||||
* To use this driver, "dlz_external.so" must be moved into the working
|
||||
* directory for named.
|
||||
*/
|
||||
|
||||
options {
|
||||
allow-transfer { any; };
|
||||
allow-query { any; };
|
||||
notify yes;
|
||||
recursion no;
|
||||
};
|
||||
|
||||
/*
|
||||
* To test dynamic updates, create a DDNS key:
|
||||
*
|
||||
* ddns-confgen -q -z example.nil > ddns.key
|
||||
*
|
||||
* Then uncomment the following line:
|
||||
*
|
||||
* include "ddns.key";
|
||||
*
|
||||
* Use "nsupdate -k ddns.key" when sending updates. (NOTE: This driver does
|
||||
* not check the key that's used: as long as the update is signed by a key
|
||||
* known to named, the update will be accepted. Only updates to names
|
||||
* that begin with "deny." are rejected.)
|
||||
*/
|
||||
|
||||
dlz "example" {
|
||||
database "dlopen ./dlz_example.so example.nil";
|
||||
};
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
# Copyright Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
# Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
#
|
||||
# The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
|
||||
# conceived and contributed by Rob Butler.
|
||||
#
|
||||
# SPDX-License-Identifier: ISC and MPL-2.0
|
||||
#
|
||||
# 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.
|
||||
|
||||
prefix = /usr
|
||||
libdir = $(prefix)/lib/bind9
|
||||
|
||||
CFLAGS += -fPIC -g -I../include
|
||||
BDB_LIBS=-ldb
|
||||
|
||||
all: 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)
|
||||
|
||||
clean:
|
||||
rm -f dlz_bdbhpt_dynamic.so
|
||||
|
||||
install: dlz_bdbhpt_dynamic.so
|
||||
mkdir -p $(DESTDIR)$(libdir)
|
||||
install dlz_bdbhpt_dynamic.so $(DESTDIR)$(libdir)
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
<!--
|
||||
Copyright Internet Systems Consortium, Inc. ("ISC")
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
|
||||
The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
|
||||
conceived and contributed by Rob Butler.
|
||||
|
||||
SPDX-License-Identifier: ISC and MPL-2.0
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
dlz-bdbhpt-dynamic
|
||||
==================
|
||||
|
||||
A Bind 9 Dynamically Loadable BerkeleyDB High Performance Text Driver
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
This is an attempt to port the original Bind 9 DLZ bdbhpt_driver.c as
|
||||
found in the Bind 9 source tree into the new DLZ dlopen driver API.
|
||||
The goals of this project are as follows:
|
||||
|
||||
* Provide DLZ facilities to OEM-supported Bind distributions
|
||||
* Support both v1 (Bind 9.8) and v2 (Bind 9.9) of the dlopen() DLZ API
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
You will need the following:
|
||||
* Bind 9.8 or higher with the DLZ dlopen driver enabled
|
||||
* BerkeleyDB libraries and header files
|
||||
* A C compiler
|
||||
|
||||
This distribution have been successfully installed and tested on
|
||||
Ubuntu 12.04.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
With the above requirements satisfied perform the following steps:
|
||||
|
||||
1. Ensure the symlink for dlz_minimal.h points at the correct header
|
||||
file matching your Bind version
|
||||
2. Run: make
|
||||
3. Run: sudo make install # this will install dlz_bdbhpt_dynamic.so
|
||||
into /usr/lib/bind9/
|
||||
4. Add a DLZ statement similar to the example below into your
|
||||
Bind configuration
|
||||
5. Ensure your BerkeleyDB home-directory exists and can be written to
|
||||
by the bind user
|
||||
6. Use the included testing/bdbhpt-populate.pl script to provide some
|
||||
data for initial testing
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Example usage is as follows:
|
||||
|
||||
```
|
||||
dlz "bdbhpt_dynamic" {
|
||||
database "dlopen /usr/lib/bind9/dlz_bdbhpt_dynamic.so T /var/cache/bind/dlz dnsdata.db";
|
||||
};
|
||||
```
|
||||
|
||||
The arguments for the "database" line above are as follows:
|
||||
|
||||
1. dlopen - Use the dlopen DLZ driver to dynamically load our compiled
|
||||
driver
|
||||
2. The full path to your built dlz_bdbhpt_dynamic.so
|
||||
3. Single character specifying the mode to open your BerkeleyDB
|
||||
environment:
|
||||
* T - Transactional Mode - Highest safety, lowest speed.
|
||||
* C - Concurrent Mode - Lower safety (no rollback), higher speed.
|
||||
* P - Private Mode - No interprocess communication & no locking.
|
||||
Lowest safety, highest speed.
|
||||
4. Directory containing your BerkeleyDB - this is where the BerkeleyDB
|
||||
environment will be created.
|
||||
5. Filename within this directory containing your BerkeleyDB tables.
|
||||
|
||||
A copy of the above Bind configuration is included within
|
||||
example/dlz.conf.
|
||||
|
||||
Author
|
||||
------
|
||||
|
||||
The person responsible for this is:
|
||||
|
||||
Mark Goldfinch <g@g.org.nz>
|
||||
|
||||
The code is maintained at:
|
||||
|
||||
https://github.com/goldie80/dlz-bdbhpt-dynamic
|
||||
|
||||
There is very little in the way of original code in this work,
|
||||
however, original license conditions from both bdbhpt_driver.c and
|
||||
dlz_example.c are maintained in the dlz_bdbhpt_dynamic.c.
|
||||
|
|
@ -1,837 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0 and ISC
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
*
|
||||
* 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 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 is simply a merge of Andrew Tridgell's dlz_example.c and the
|
||||
* original bdb_bdbhpt_driver.c
|
||||
*
|
||||
* This provides the externally loadable bdbhpt DLZ driver, without
|
||||
* update support
|
||||
*
|
||||
*/
|
||||
|
||||
#include <db.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dlz_minimal.h"
|
||||
|
||||
/* should the bdb driver use threads. */
|
||||
#define bdbhpt_threads DB_THREAD
|
||||
|
||||
/* bdbhpt database names */
|
||||
#define dlz_data "dns_data"
|
||||
#define dlz_zone "dns_zone"
|
||||
#define dlz_xfr "dns_xfr"
|
||||
#define dlz_client "dns_client"
|
||||
|
||||
#define dlz_bdbhpt_dynamic_version "0.1"
|
||||
|
||||
/*
|
||||
* This structure contains all our DB handles and helper functions we
|
||||
* inherit from the dlz_dlopen driver
|
||||
*
|
||||
*/
|
||||
typedef struct bdbhpt_instance {
|
||||
DB_ENV *dbenv; /* bdbhpt environment */
|
||||
DB *data; /* dns_data database handle */
|
||||
DB *zone; /* zone database handle */
|
||||
DB *xfr; /* zone xfr database handle */
|
||||
DB *client; /* client database handle */
|
||||
|
||||
/* 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;
|
||||
} bdbhpt_instance_t;
|
||||
|
||||
typedef struct bdbhpt_parsed_data {
|
||||
char *host;
|
||||
char *type;
|
||||
int ttl;
|
||||
char *data;
|
||||
} bdbhpt_parsed_data_t;
|
||||
|
||||
static void
|
||||
b9_add_helper(struct bdbhpt_instance *db, const char *helper_name, void *ptr);
|
||||
|
||||
/*%
|
||||
* Reverses a string in place.
|
||||
*/
|
||||
static char *
|
||||
bdbhpt_strrev(char *str) {
|
||||
char *p1, *p2;
|
||||
|
||||
if (!str || !*str) {
|
||||
return str;
|
||||
}
|
||||
for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2) {
|
||||
*p1 ^= *p2;
|
||||
*p2 ^= *p1;
|
||||
*p1 ^= *p2;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/*%
|
||||
* Parses the DBT from the Berkeley DB into a parsed_data record
|
||||
* The parsed_data record should be allocated before and passed into the
|
||||
* bdbhpt_parse_data function. The char (type & data) fields should not
|
||||
* be "free"d as that memory is part of the DBT data field. It will be
|
||||
* "free"d when the DBT is freed.
|
||||
*/
|
||||
|
||||
static isc_result_t
|
||||
bdbhpt_parse_data(log_t *log, char *in, bdbhpt_parsed_data_t *pd) {
|
||||
char *endp, *ttlStr;
|
||||
char *tmp = in;
|
||||
char *lastchar = (char *)&tmp[strlen(tmp)];
|
||||
|
||||
/*%
|
||||
* String should be formatted as:
|
||||
* replication_id
|
||||
* (a space)
|
||||
* host_name
|
||||
* (a space)
|
||||
* ttl
|
||||
* (a space)
|
||||
* type
|
||||
* (a space)
|
||||
* remaining data
|
||||
*
|
||||
* examples:
|
||||
*
|
||||
* 9191 host 10 A 127.0.0.1
|
||||
* server1_212 host 10 A 127.0.0.2
|
||||
* {xxxx-xxxx-xxxx-xxxx-xxxx} host 10 MX 20 mail.example.com
|
||||
*/
|
||||
|
||||
/*
|
||||
* we don't need the replication id, so don't
|
||||
* bother saving a pointer to it.
|
||||
*/
|
||||
|
||||
/* find space after replication id */
|
||||
tmp = strchr(tmp, ' ');
|
||||
/* verify we found a space */
|
||||
if (tmp == NULL) {
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
/* make sure it is safe to increment pointer */
|
||||
if (++tmp > lastchar) {
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
/* save pointer to host */
|
||||
pd->host = tmp;
|
||||
|
||||
/* find space after host and change it to a '\0' */
|
||||
tmp = strchr(tmp, ' ');
|
||||
/* verify we found a space */
|
||||
if (tmp == NULL) {
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
/* change the space to a null (string terminator) */
|
||||
tmp[0] = '\0';
|
||||
/* make sure it is safe to increment pointer */
|
||||
if (++tmp > lastchar) {
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
/* save pointer to ttl string */
|
||||
ttlStr = tmp;
|
||||
|
||||
/* find space after ttl and change it to a '\0' */
|
||||
tmp = strchr(tmp, ' ');
|
||||
/* verify we found a space */
|
||||
if (tmp == NULL) {
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
/* change the space to a null (string terminator) */
|
||||
tmp[0] = '\0';
|
||||
/* make sure it is safe to increment pointer */
|
||||
if (++tmp > lastchar) {
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
/* save pointer to dns type */
|
||||
pd->type = tmp;
|
||||
|
||||
/* find space after type and change it to a '\0' */
|
||||
tmp = strchr(tmp, ' ');
|
||||
/* verify we found a space */
|
||||
if (tmp == NULL) {
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
/* change the space to a null (string terminator) */
|
||||
tmp[0] = '\0';
|
||||
/* make sure it is safe to increment pointer */
|
||||
if (++tmp > lastchar) {
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
/* save pointer to remainder of DNS data */
|
||||
pd->data = tmp;
|
||||
|
||||
/* convert ttl string to integer */
|
||||
pd->ttl = strtol(ttlStr, &endp, 10);
|
||||
if (*endp != '\0' || pd->ttl < 0) {
|
||||
log(ISC_LOG_ERROR, "bdbhpt_dynamic: "
|
||||
"ttl must be a positive number");
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
/* if we get this far everything should have worked. */
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if a zone transfer is allowed
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_allowzonexfr(void *dbdata, const char *name, const char *client) {
|
||||
isc_result_t result;
|
||||
bdbhpt_instance_t *db = (bdbhpt_instance_t *)dbdata;
|
||||
DBT key, data;
|
||||
|
||||
/* check to see if we are authoritative for the zone first. */
|
||||
#if DLZ_DLOPEN_VERSION >= 3
|
||||
result = dlz_findzonedb(dbdata, name, NULL, NULL);
|
||||
#else /* if DLZ_DLOPEN_VERSION >= 3 */
|
||||
result = dlz_findzonedb(dbdata, name);
|
||||
#endif /* if DLZ_DLOPEN_VERSION >= 3 */
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return ISC_R_NOTFOUND;
|
||||
}
|
||||
|
||||
memset(&key, 0, sizeof(DBT));
|
||||
key.flags = DB_DBT_MALLOC;
|
||||
key.data = strdup(name);
|
||||
if (key.data == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto xfr_cleanup;
|
||||
}
|
||||
key.size = strlen(key.data);
|
||||
|
||||
memset(&data, 0, sizeof(DBT));
|
||||
data.flags = DB_DBT_MALLOC;
|
||||
data.data = strdup(client);
|
||||
if (data.data == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto xfr_cleanup;
|
||||
}
|
||||
data.size = strlen(data.data);
|
||||
|
||||
switch (db->client->get(db->client, NULL, &key, &data, DB_GET_BOTH)) {
|
||||
case DB_NOTFOUND:
|
||||
result = ISC_R_NOTFOUND;
|
||||
break;
|
||||
case 0:
|
||||
result = ISC_R_SUCCESS;
|
||||
break;
|
||||
default:
|
||||
result = ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
xfr_cleanup:
|
||||
/* free any memory duplicate string in the key field */
|
||||
if (key.data != NULL) {
|
||||
free(key.data);
|
||||
}
|
||||
|
||||
/* free any memory allocated to the data field. */
|
||||
if (data.data != NULL) {
|
||||
free(data.data);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*%
|
||||
* Perform a zone transfer
|
||||
*
|
||||
* BDB does not allow a secondary index on a database that allows
|
||||
* duplicates. We have a few options:
|
||||
*
|
||||
* 1) kill speed by having lookup method use a secondary db which
|
||||
* is associated to the primary DB with the DNS data. Then have
|
||||
* another secondary db for zone transfer which also points to
|
||||
* the dns_data primary. NO - The point of this driver is
|
||||
* lookup performance.
|
||||
*
|
||||
* 2) Blow up database size by storing DNS data twice. Once for
|
||||
* the lookup (dns_data) database, and a second time for the zone
|
||||
* transfer (dns_xfr) database. NO - That would probably require
|
||||
* a larger cache to provide good performance. Also, that would
|
||||
* make the DB larger on disk potentially slowing it as well.
|
||||
*
|
||||
* 3) Loop through the dns_xfr database with a cursor to get
|
||||
* all the different hosts in a zone. Then use the zone & host
|
||||
* together to lookup the data in the dns_data database. YES -
|
||||
* This may slow down zone xfr's a little, but that's ok they
|
||||
* don't happen as often and don't need to be as fast. We can
|
||||
* also use this table when deleting a zone (The BDB driver
|
||||
* is read only - the delete would be used during replication
|
||||
* updates by a separate process).
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes) {
|
||||
isc_result_t result = ISC_R_NOTFOUND;
|
||||
bdbhpt_instance_t *db = (bdbhpt_instance_t *)dbdata;
|
||||
DBC *xfr_cursor = NULL;
|
||||
DBC *dns_cursor = NULL;
|
||||
DBT xfr_key, xfr_data, dns_key, dns_data;
|
||||
int xfr_flags;
|
||||
int dns_flags;
|
||||
int bdbhptres;
|
||||
bdbhpt_parsed_data_t pd;
|
||||
char *tmp = NULL, *tmp_zone, *tmp_zone_host = NULL;
|
||||
|
||||
memset(&xfr_key, 0, sizeof(DBT));
|
||||
memset(&xfr_data, 0, sizeof(DBT));
|
||||
memset(&dns_key, 0, sizeof(DBT));
|
||||
memset(&dns_data, 0, sizeof(DBT));
|
||||
|
||||
xfr_key.data = tmp_zone = strdup(zone);
|
||||
if (xfr_key.data == NULL) {
|
||||
return ISC_R_NOMEMORY;
|
||||
}
|
||||
|
||||
xfr_key.size = strlen(xfr_key.data);
|
||||
|
||||
/* get a cursor to loop through dns_xfr table */
|
||||
if (db->xfr->cursor(db->xfr, NULL, &xfr_cursor, 0) != 0) {
|
||||
result = ISC_R_FAILURE;
|
||||
goto allnodes_cleanup;
|
||||
}
|
||||
|
||||
/* get a cursor to loop through dns_data table */
|
||||
if (db->data->cursor(db->data, NULL, &dns_cursor, 0) != 0) {
|
||||
result = ISC_R_FAILURE;
|
||||
goto allnodes_cleanup;
|
||||
}
|
||||
|
||||
xfr_flags = DB_SET;
|
||||
|
||||
/* loop through xfr table for specified zone. */
|
||||
while ((bdbhptres = xfr_cursor->c_get(xfr_cursor, &xfr_key, &xfr_data,
|
||||
xfr_flags)) == 0)
|
||||
{
|
||||
xfr_flags = DB_NEXT_DUP;
|
||||
|
||||
/* +1 to allow for space between zone and host names */
|
||||
dns_key.size = xfr_data.size + xfr_key.size + 1;
|
||||
|
||||
/* +1 to allow for null term at end of string. */
|
||||
dns_key.data = tmp_zone_host = malloc(dns_key.size + 1);
|
||||
if (dns_key.data == NULL) {
|
||||
goto allnodes_cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* construct search key for dns_data.
|
||||
* zone_name(a space)host_name
|
||||
*/
|
||||
strcpy(dns_key.data, zone);
|
||||
strcat(dns_key.data, " ");
|
||||
strncat(dns_key.data, xfr_data.data, xfr_data.size);
|
||||
|
||||
dns_flags = DB_SET;
|
||||
|
||||
while ((bdbhptres = dns_cursor->c_get(dns_cursor, &dns_key,
|
||||
&dns_data, dns_flags)) ==
|
||||
0)
|
||||
{
|
||||
dns_flags = DB_NEXT_DUP;
|
||||
|
||||
/* +1 to allow for null term at end of string. */
|
||||
tmp = realloc(tmp, dns_data.size + 1);
|
||||
if (tmp == NULL) {
|
||||
goto allnodes_cleanup;
|
||||
}
|
||||
|
||||
/* copy data to tmp string, and append null term. */
|
||||
strncpy(tmp, dns_data.data, dns_data.size);
|
||||
tmp[dns_data.size] = '\0';
|
||||
|
||||
/* split string into dns data parts. */
|
||||
if (bdbhpt_parse_data(db->log, tmp, &pd) !=
|
||||
ISC_R_SUCCESS)
|
||||
{
|
||||
goto allnodes_cleanup;
|
||||
}
|
||||
result = db->putnamedrr(allnodes, pd.host, pd.type,
|
||||
pd.ttl, pd.data);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto allnodes_cleanup;
|
||||
}
|
||||
} /* end inner while loop */
|
||||
|
||||
/* clean up memory */
|
||||
if (tmp_zone_host != NULL) {
|
||||
free(tmp_zone_host);
|
||||
tmp_zone_host = NULL;
|
||||
}
|
||||
} /* end outer while loop */
|
||||
|
||||
allnodes_cleanup:
|
||||
/* free any memory */
|
||||
if (tmp != NULL) {
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
if (tmp_zone_host != NULL) {
|
||||
free(tmp_zone_host);
|
||||
}
|
||||
|
||||
if (tmp_zone != NULL) {
|
||||
free(tmp_zone);
|
||||
}
|
||||
|
||||
/* get rid of cursors */
|
||||
if (xfr_cursor != NULL) {
|
||||
xfr_cursor->c_close(xfr_cursor);
|
||||
}
|
||||
|
||||
if (dns_cursor != NULL) {
|
||||
dns_cursor->c_close(dns_cursor);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*%
|
||||
* Performs bdbhpt cleanup.
|
||||
* Used by bdbhpt_create if there is an error starting up.
|
||||
* Used by bdbhpt_destroy when the driver is shutting down.
|
||||
*/
|
||||
static void
|
||||
bdbhpt_cleanup(bdbhpt_instance_t *db) {
|
||||
/* close databases */
|
||||
if (db->data != NULL) {
|
||||
db->data->close(db->data, 0);
|
||||
}
|
||||
if (db->xfr != NULL) {
|
||||
db->xfr->close(db->xfr, 0);
|
||||
}
|
||||
if (db->zone != NULL) {
|
||||
db->zone->close(db->zone, 0);
|
||||
}
|
||||
if (db->client != NULL) {
|
||||
db->client->close(db->client, 0);
|
||||
}
|
||||
|
||||
/* close environment */
|
||||
if (db->dbenv != NULL) {
|
||||
db->dbenv->close(db->dbenv, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we handle a given zone
|
||||
*/
|
||||
#if DLZ_DLOPEN_VERSION < 3
|
||||
isc_result_t
|
||||
dlz_findzonedb(void *dbdata, const char *name)
|
||||
#else /* if DLZ_DLOPEN_VERSION < 3 */
|
||||
isc_result_t
|
||||
dlz_findzonedb(void *dbdata, const char *name, dns_clientinfomethods_t *methods,
|
||||
dns_clientinfo_t *clientinfo)
|
||||
#endif /* if DLZ_DLOPEN_VERSION < 3 */
|
||||
{
|
||||
isc_result_t result;
|
||||
bdbhpt_instance_t *db = (bdbhpt_instance_t *)dbdata;
|
||||
DBT key, data;
|
||||
|
||||
memset(&key, 0, sizeof(DBT));
|
||||
memset(&data, 0, sizeof(DBT));
|
||||
data.flags = DB_DBT_MALLOC;
|
||||
|
||||
#if DLZ_DLOPEN_VERSION >= 3
|
||||
UNUSED(methods);
|
||||
UNUSED(clientinfo);
|
||||
#endif /* if DLZ_DLOPEN_VERSION >= 3 */
|
||||
|
||||
key.data = strdup(name);
|
||||
|
||||
if (key.data == NULL) {
|
||||
return ISC_R_NOMEMORY;
|
||||
}
|
||||
|
||||
/*
|
||||
* reverse string to take advantage of BDB locality of reference
|
||||
* if we need further lookups because the zone doesn't match the
|
||||
* first time.
|
||||
*/
|
||||
key.data = bdbhpt_strrev(key.data);
|
||||
key.size = strlen(key.data);
|
||||
|
||||
switch (db->zone->get(db->zone, NULL, &key, &data, 0)) {
|
||||
case DB_NOTFOUND:
|
||||
result = ISC_R_NOTFOUND;
|
||||
break;
|
||||
case 0:
|
||||
result = ISC_R_SUCCESS;
|
||||
break;
|
||||
default:
|
||||
result = ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
/* free any memory duplicate string in the key field */
|
||||
if (key.data != NULL) {
|
||||
free(key.data);
|
||||
}
|
||||
|
||||
/* free any memory allocated to the data field. */
|
||||
if (data.data != NULL) {
|
||||
free(data.data);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up one record in the database.
|
||||
*
|
||||
*/
|
||||
#if DLZ_DLOPEN_VERSION == 1
|
||||
isc_result_t
|
||||
dlz_lookup(const char *zone, const char *name, void *dbdata,
|
||||
dns_sdlzlookup_t *lookup)
|
||||
#else /* if DLZ_DLOPEN_VERSION == 1 */
|
||||
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 /* if DLZ_DLOPEN_VERSION == 1 */
|
||||
{
|
||||
isc_result_t result = ISC_R_NOTFOUND;
|
||||
bdbhpt_instance_t *db = (bdbhpt_instance_t *)dbdata;
|
||||
DBC *data_cursor = NULL;
|
||||
DBT key, data;
|
||||
int bdbhptres;
|
||||
int flags;
|
||||
|
||||
bdbhpt_parsed_data_t pd;
|
||||
char *tmp = NULL;
|
||||
char *keyStr = NULL;
|
||||
|
||||
#if DLZ_DLOPEN_VERSION >= 2
|
||||
UNUSED(methods);
|
||||
UNUSED(clientinfo);
|
||||
#endif /* if DLZ_DLOPEN_VERSION >= 2 */
|
||||
|
||||
memset(&key, 0, sizeof(DBT));
|
||||
memset(&data, 0, sizeof(DBT));
|
||||
|
||||
key.size = strlen(zone) + strlen(name) + 1;
|
||||
|
||||
/* allocate mem for key */
|
||||
key.data = keyStr = malloc((key.size + 1) * sizeof(char));
|
||||
|
||||
if (keyStr == NULL) {
|
||||
return ISC_R_NOMEMORY;
|
||||
}
|
||||
|
||||
strcpy(keyStr, zone);
|
||||
strcat(keyStr, " ");
|
||||
strcat(keyStr, name);
|
||||
|
||||
/* get a cursor to loop through data */
|
||||
if (db->data->cursor(db->data, NULL, &data_cursor, 0) != 0) {
|
||||
result = ISC_R_FAILURE;
|
||||
goto lookup_cleanup;
|
||||
}
|
||||
|
||||
result = ISC_R_NOTFOUND;
|
||||
|
||||
flags = DB_SET;
|
||||
while ((bdbhptres = data_cursor->c_get(data_cursor, &key, &data,
|
||||
flags)) == 0)
|
||||
{
|
||||
flags = DB_NEXT_DUP;
|
||||
tmp = realloc(tmp, data.size + 1);
|
||||
if (tmp == NULL) {
|
||||
goto lookup_cleanup;
|
||||
}
|
||||
|
||||
strncpy(tmp, data.data, data.size);
|
||||
tmp[data.size] = '\0';
|
||||
|
||||
if (bdbhpt_parse_data(db->log, tmp, &pd) != ISC_R_SUCCESS) {
|
||||
goto lookup_cleanup;
|
||||
}
|
||||
|
||||
result = db->putrr(lookup, pd.type, pd.ttl, pd.data);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto lookup_cleanup;
|
||||
}
|
||||
} /* end while loop */
|
||||
|
||||
lookup_cleanup:
|
||||
/* get rid of cursor */
|
||||
if (data_cursor != NULL) {
|
||||
data_cursor->c_close(data_cursor);
|
||||
}
|
||||
|
||||
free(keyStr);
|
||||
if (tmp != NULL) {
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*%
|
||||
* Initialises, sets flags and then opens Berkeley databases.
|
||||
*/
|
||||
static isc_result_t
|
||||
bdbhpt_opendb(log_t *log, DB_ENV *db_env, DBTYPE db_type, DB **db,
|
||||
const char *db_name, char *db_file, int flags) {
|
||||
int result;
|
||||
|
||||
/* Initialise the database. */
|
||||
if ((result = db_create(db, db_env, 0)) != 0) {
|
||||
log(ISC_LOG_ERROR,
|
||||
"bdbhpt_dynamic: could not initialize %s database. "
|
||||
"BerkeleyDB error: %s",
|
||||
db_name, db_strerror(result));
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
/* set database flags. */
|
||||
if ((result = (*db)->set_flags(*db, flags)) != 0) {
|
||||
log(ISC_LOG_ERROR,
|
||||
"bdbhpt_dynamic: could not set flags for %s database. "
|
||||
"BerkeleyDB error: %s",
|
||||
db_name, db_strerror(result));
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
/* open the database. */
|
||||
if ((result = (*db)->open(*db, NULL, db_file, db_name, db_type,
|
||||
DB_RDONLY | bdbhpt_threads, 0)) != 0)
|
||||
{
|
||||
log(ISC_LOG_ERROR,
|
||||
"bdbhpt_dynamic: could not open %s database in %s. "
|
||||
"BerkeleyDB error: %s",
|
||||
db_name, db_file, db_strerror(result));
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called to initialize the driver
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata,
|
||||
...) {
|
||||
isc_result_t result;
|
||||
int bdbhptres;
|
||||
int bdbFlags = 0;
|
||||
bdbhpt_instance_t *db = NULL;
|
||||
|
||||
const char *helper_name;
|
||||
va_list ap;
|
||||
|
||||
UNUSED(dlzname);
|
||||
|
||||
/* Allocate memory for our db structures and helper functions */
|
||||
db = calloc(1, sizeof(struct bdbhpt_instance));
|
||||
if (db == NULL) {
|
||||
return ISC_R_NOMEMORY;
|
||||
}
|
||||
|
||||
/* Fill in the helper functions */
|
||||
va_start(ap, dbdata);
|
||||
while ((helper_name = va_arg(ap, const char *)) != NULL) {
|
||||
b9_add_helper(db, helper_name, va_arg(ap, void *));
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
/* verify we have 4 arg's passed to the driver */
|
||||
if (argc != 4) {
|
||||
db->log(ISC_LOG_ERROR,
|
||||
"bdbhpt_dynamic: please supply 3 command line args. "
|
||||
"You supplied: %s",
|
||||
argc);
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
switch ((char)*argv[1]) {
|
||||
/*
|
||||
* Transactional mode. Highest safety - lowest speed.
|
||||
*/
|
||||
case 'T':
|
||||
case 't':
|
||||
bdbFlags = DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_LOG |
|
||||
DB_INIT_TXN;
|
||||
db->log(ISC_LOG_INFO, "bdbhpt_dynamic: using transactional "
|
||||
"mode.");
|
||||
break;
|
||||
|
||||
/*
|
||||
* Concurrent mode. Lower safety (no rollback) -
|
||||
* higher speed.
|
||||
*/
|
||||
case 'C':
|
||||
case 'c':
|
||||
bdbFlags = DB_INIT_CDB | DB_INIT_MPOOL;
|
||||
db->log(ISC_LOG_INFO, "bdbhpt_dynamic: using concurrent mode.");
|
||||
break;
|
||||
|
||||
/*
|
||||
* Private mode. No inter-process communication & no locking.
|
||||
* Lowest safety - highest speed.
|
||||
*/
|
||||
case 'P':
|
||||
case 'p':
|
||||
bdbFlags = DB_PRIVATE | DB_INIT_MPOOL;
|
||||
db->log(ISC_LOG_INFO, "bdbhpt_dynamic: using private mode.");
|
||||
break;
|
||||
default:
|
||||
db->log(ISC_LOG_ERROR,
|
||||
"bdbhpt_dynamic: "
|
||||
"operating mode must be set to P or C or T. "
|
||||
"You specified '%s'",
|
||||
argv[1]);
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* create bdbhpt environment
|
||||
* Basically bdbhpt allocates and assigns memory to db->dbenv
|
||||
*/
|
||||
bdbhptres = db_env_create(&db->dbenv, 0);
|
||||
if (bdbhptres != 0) {
|
||||
db->log(ISC_LOG_ERROR,
|
||||
"bdbhpt_dynamic: db environment could not be created. "
|
||||
"BerkeleyDB error: %s",
|
||||
db_strerror(bdbhptres));
|
||||
result = ISC_R_FAILURE;
|
||||
goto init_cleanup;
|
||||
}
|
||||
|
||||
/* open bdbhpt environment */
|
||||
bdbhptres = db->dbenv->open(db->dbenv, argv[2],
|
||||
bdbFlags | bdbhpt_threads | DB_CREATE, 0);
|
||||
if (bdbhptres != 0) {
|
||||
db->log(ISC_LOG_ERROR,
|
||||
"bdbhpt_dynamic: "
|
||||
"db environment at '%s' could not be opened. "
|
||||
"BerkeleyDB error: %s",
|
||||
argv[2], db_strerror(bdbhptres));
|
||||
result = ISC_R_FAILURE;
|
||||
goto init_cleanup;
|
||||
}
|
||||
|
||||
/* open dlz_data database. */
|
||||
result = bdbhpt_opendb(db->log, db->dbenv, DB_UNKNOWN, &db->data,
|
||||
dlz_data, argv[3], DB_DUP | DB_DUPSORT);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto init_cleanup;
|
||||
}
|
||||
|
||||
/* open dlz_xfr database. */
|
||||
result = bdbhpt_opendb(db->log, db->dbenv, DB_UNKNOWN, &db->xfr,
|
||||
dlz_xfr, argv[3], DB_DUP | DB_DUPSORT);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto init_cleanup;
|
||||
}
|
||||
|
||||
/* open dlz_zone database. */
|
||||
result = bdbhpt_opendb(db->log, db->dbenv, DB_UNKNOWN, &db->zone,
|
||||
dlz_zone, argv[3], 0);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto init_cleanup;
|
||||
}
|
||||
|
||||
/* open dlz_client database. */
|
||||
result = bdbhpt_opendb(db->log, db->dbenv, DB_UNKNOWN, &db->client,
|
||||
dlz_client, argv[3], DB_DUP | DB_DUPSORT);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto init_cleanup;
|
||||
}
|
||||
|
||||
*dbdata = db;
|
||||
|
||||
db->log(ISC_LOG_INFO, "bdbhpt_dynamic: version %s, started",
|
||||
dlz_bdbhpt_dynamic_version);
|
||||
return ISC_R_SUCCESS;
|
||||
|
||||
init_cleanup:
|
||||
bdbhpt_cleanup(db);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Shut down the backend
|
||||
*/
|
||||
void
|
||||
dlz_destroy(void *dbdata) {
|
||||
struct bdbhpt_instance *db = (struct bdbhpt_instance *)dbdata;
|
||||
|
||||
db->log(ISC_LOG_INFO, "dlz_bdbhpt_dynamic (%s): shutting down",
|
||||
dlz_bdbhpt_dynamic_version);
|
||||
bdbhpt_cleanup((bdbhpt_instance_t *)dbdata);
|
||||
free(db);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 bdbhpt_instance *db, const char *helper_name, void *ptr) {
|
||||
if (strcmp(helper_name, "log") == 0) {
|
||||
db->log = (log_t *)ptr;
|
||||
}
|
||||
if (strcmp(helper_name, "putrr") == 0) {
|
||||
db->putrr = (dns_sdlz_putrr_t *)ptr;
|
||||
}
|
||||
if (strcmp(helper_name, "putnamedrr") == 0) {
|
||||
db->putnamedrr = (dns_sdlz_putnamedrr_t *)ptr;
|
||||
}
|
||||
if (strcmp(helper_name, "writeable_zone") == 0) {
|
||||
db->writeable_zone = (dns_dlz_writeablezone_t *)ptr;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
These files were used for testing on Ubuntu Linux using BDB 5.1 and
|
||||
BerkeleyDB 0.54 for perl.
|
||||
|
||||
- Populate the database from dns-data.txt for zone example.com:
|
||||
|
||||
perl bdbhpt-populate.pl \
|
||||
--bdb=test.db --input=dns-data.txt --zones=example.com
|
||||
|
||||
- Run "named -g -c named.conf"
|
||||
|
||||
BDB server is now loaded with example.com data from the file test.db
|
||||
|
|
@ -1,244 +0,0 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
use strict;
|
||||
use BerkeleyDB;
|
||||
use Getopt::Long;
|
||||
|
||||
my $opt = {};
|
||||
if (!GetOptions($opt, qw/bdb|b:s input|i:s zones|z:s help|h/)) {
|
||||
usage('GetOptions processing failed.');
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if ($opt->{help}) {
|
||||
usage();
|
||||
exit 0;
|
||||
}
|
||||
|
||||
my $db_file = $opt->{bdb};
|
||||
if (!defined $db_file || $db_file eq '') {
|
||||
usage('Please specify an output BerkeleyDB filename.');
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $input_file = $opt->{input};
|
||||
if (!defined $input_file || $input_file eq '') {
|
||||
usage('Please specify an input records file.');
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $zone_list = $opt->{zones};
|
||||
if (!defined $zone_list || $zone_list eq '') {
|
||||
usage('Please specify a space separated list of zones');
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $records = [];
|
||||
my $unique_names = [];
|
||||
populate_records(records=>$records, input_file=>$input_file, unique_names=>$unique_names);
|
||||
|
||||
my $flags = DB_CREATE;
|
||||
|
||||
my $dns_data = new BerkeleyDB::Hash
|
||||
-Filename => $db_file,
|
||||
-Flags => $flags,
|
||||
-Property => DB_DUP | DB_DUPSORT,
|
||||
-Subname => "dns_data"
|
||||
|| die "Cannot create dns_data: $BerkeleyDB::Error";
|
||||
|
||||
my $replId = 0;
|
||||
my @zones = split(/\s+/, $zone_list);
|
||||
foreach my $zone (@zones) {
|
||||
foreach my $r (@$records) {
|
||||
my $name = $r->{name};
|
||||
my $ttl = $r->{ttl};
|
||||
my $type = $r->{type};
|
||||
my $data = $r->{data};
|
||||
|
||||
$data =~ s/\%zone\%/$zone/g;
|
||||
$data =~ s/\%driver\%/bdbhpt-dynamic/g;
|
||||
|
||||
my $row_name = "$zone $name";
|
||||
my $row_value = "$replId $name $ttl $type $data";
|
||||
if ($dns_data->db_put($row_name, $row_value) != 0) {
|
||||
die "Cannot add record '$row_name' -> '$row_value' to dns_data: $BerkeleyDB::Error";
|
||||
}
|
||||
$replId++;
|
||||
}
|
||||
}
|
||||
|
||||
$dns_data->db_close();
|
||||
|
||||
my $dns_xfr = new BerkeleyDB::Hash
|
||||
-Filename => $db_file,
|
||||
-Flags => $flags,
|
||||
-Property => DB_DUP | DB_DUPSORT,
|
||||
-Subname => "dns_xfr"
|
||||
or die "Cannot create dns_xfr: $BerkeleyDB::Error";
|
||||
|
||||
foreach my $zone (@zones) {
|
||||
foreach my $name (@$unique_names) {
|
||||
if ($dns_xfr->db_put($zone, $name) != 0) {
|
||||
die "Cannot add record '$zone' -> '$name' to dns_xfr: $BerkeleyDB::Error";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$dns_xfr->db_close();
|
||||
|
||||
my $dns_client = new BerkeleyDB::Hash
|
||||
-Filename => $db_file,
|
||||
-Flags => $flags,
|
||||
-Property => DB_DUP | DB_DUPSORT,
|
||||
-Subname => "dns_client"
|
||||
or die "Cannot create dns_client: $BerkeleyDB::Error";
|
||||
|
||||
foreach my $zone (@zones) {
|
||||
my $ip = '127.0.0.1';
|
||||
if ($dns_client->db_put($zone, $ip) != 0) {
|
||||
die "Cannot add record '$zone' -> '$ip' to dns_client: $BerkeleyDB::Error";
|
||||
}
|
||||
}
|
||||
|
||||
$dns_client->db_close();
|
||||
|
||||
my $dns_zone = new BerkeleyDB::Btree
|
||||
-Filename => $db_file,
|
||||
-Flags => $flags,
|
||||
-Property => 0,
|
||||
-Subname => "dns_zone"
|
||||
or die "Cannot create dns_zone: $BerkeleyDB::Error";
|
||||
|
||||
foreach my $zone (@zones) {
|
||||
my $reversed_zone = reverse($zone);
|
||||
if ($dns_zone->db_put($reversed_zone, "1") != 0) {
|
||||
die "Cannot add record '$reversed_zone' -> '1' to dns_zone: $BerkeleyDB::Error";
|
||||
}
|
||||
};
|
||||
|
||||
$dns_zone->db_close();
|
||||
|
||||
exit 0;
|
||||
|
||||
sub usage {
|
||||
my ($message) = @_;
|
||||
if (defined $message && $message ne '') {
|
||||
print STDERR $message . "\n\n";
|
||||
}
|
||||
|
||||
print STDERR "usage: $0 --bdb=<bdb-file> --input=<input-file> --zones=<zone-list>\n\n";
|
||||
print STDERR "\tbdb-file: The output BerkeleyDB file you wish to create and use with bdbhpt-dynamic\n\n";
|
||||
print STDERR "\tinput-file: The input text-file containing records to populate within your zones\n\n";
|
||||
print STDERR "\tzone-list: The space-separated list of zones you wish to create\n\n";
|
||||
}
|
||||
|
||||
sub populate_records {
|
||||
my (%args) = @_;
|
||||
my $records = $args{records};
|
||||
my $input_file = $args{input_file};
|
||||
my $unique_names = $args{unique_names};
|
||||
|
||||
my %unique;
|
||||
|
||||
open(RECORDS, $input_file) || die "unable to open $input_file: $!";
|
||||
while (<RECORDS>) {
|
||||
chomp;
|
||||
s/\#.*$//;
|
||||
s/^\s+//;
|
||||
if ($_ eq '') {
|
||||
next;
|
||||
}
|
||||
my ($name, $ttl, $type, $data) = split(/\s+/, $_, 4);
|
||||
my $record = { name=>$name, ttl=>$ttl, type=>$type, data=>$data };
|
||||
if (validate_record($record)) {
|
||||
push @$records, $record;
|
||||
$unique{$name} = 1;
|
||||
}
|
||||
}
|
||||
close(RECORDS);
|
||||
|
||||
foreach my $name (sort keys %unique) {
|
||||
push @$unique_names, $name;
|
||||
}
|
||||
}
|
||||
|
||||
# This could probably do more in-depth tests, but these tests are better than nothing!
|
||||
sub validate_record {
|
||||
my ($r) = @_;
|
||||
|
||||
# http://en.wikipedia.org/wiki/List_of_DNS_record_types
|
||||
my @TYPES = qw/A AAAA AFSDB APL CERT CNAME DHCID DLV DNAME DNSKEY DS HIP IPSECKEY KEY KX LOC MX NAPTR NS NSEC NSEC3 NSEC3PARAM PTR RRSIG RP SIG SOA SPF SRV SSHFP TA TKEY TLSA TSIG TXT/;
|
||||
my $VALID_TYPE = {};
|
||||
foreach my $t (@TYPES) {
|
||||
$VALID_TYPE->{$t} = 1;
|
||||
}
|
||||
|
||||
if (!defined $r->{name} || $r->{name} eq '') {
|
||||
die "Record name must be set";
|
||||
}
|
||||
|
||||
if (!defined $r->{ttl} || $r->{ttl} eq '') {
|
||||
die "Record TTL must be set";
|
||||
}
|
||||
|
||||
if ($r->{ttl} =~ /\D/ || $r->{ttl} < 0) {
|
||||
die "Record TTL must be an integer 0 or greater";
|
||||
}
|
||||
|
||||
if (!defined $r->{type} || $r->{type} eq '') {
|
||||
die "Record type must be set";
|
||||
}
|
||||
|
||||
if (!$VALID_TYPE->{$r->{type}}) {
|
||||
die "Unsupported record type: $r->{type}";
|
||||
}
|
||||
|
||||
# Lets do some data validation for the records which will cause bind to crash if they're wrong
|
||||
if ($r->{type} eq 'SOA') {
|
||||
my $soa_error = "SOA records must take the form: 'server email refresh retry expire negative_cache_ttl'";
|
||||
my ($server, $email, $version, $refresh, $retry, $expire, $negative_cache_ttl) = split(/\s+/, $r->{data});
|
||||
if (!defined $server || $server eq '') {
|
||||
die "$soa_error, missing server";
|
||||
}
|
||||
if (!defined $email || $email eq '') {
|
||||
die "$soa_error, missing email";
|
||||
}
|
||||
if (!defined $refresh || $refresh eq '') {
|
||||
die "$soa_error, missing refresh";
|
||||
}
|
||||
if ($refresh =~ /\D/ || $refresh <= 0) {
|
||||
die "$soa_error, refresh must be an integer greater than 0";
|
||||
}
|
||||
if (!defined $retry || $retry eq '') {
|
||||
die "$soa_error, missing retry";
|
||||
}
|
||||
if ($retry =~ /\D/ || $retry <= 0) {
|
||||
die "$soa_error, retry must be an integer greater than 0";
|
||||
}
|
||||
if (!defined $expire || $expire eq '') {
|
||||
die "$soa_error, missing expire";
|
||||
}
|
||||
if ($expire =~ /\D/ || $expire <= 0) {
|
||||
die "$soa_error, expire must be an integer greater than 0";
|
||||
}
|
||||
if (!defined $negative_cache_ttl || $negative_cache_ttl eq '') {
|
||||
die "$soa_error, missing negative cache ttl";
|
||||
}
|
||||
if ($negative_cache_ttl =~ /\D/ || $negative_cache_ttl <= 0) {
|
||||
die "$soa_error, negative cache ttl must be an integer greater than 0";
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
# Name TTL Type Data
|
||||
@ 3600 SOA ns1.%zone%. root.%zone%. 2012071700 604800 86400 2419200 10800
|
||||
@ 3600 NS ns1.%zone%.
|
||||
@ 3600 MX 5 mx1.%zone%.
|
||||
@ 3600 MX 10 mx2.%zone%.
|
||||
@ 3600 TXT This zone brought to you by %driver%!
|
||||
jabber 3600 A 127.0.0.1
|
||||
mx1 3600 A 127.0.0.2
|
||||
mx2 3600 A 127.0.0.3
|
||||
jabber 3600 A 127.0.0.4
|
||||
ns1 3600 A 127.0.0.5
|
||||
ns1 3600 AAAA ::1
|
||||
voip 3600 A 127.0.0.6
|
||||
www 3600 CNAME www1.%zone%
|
||||
www1 3600 A 127.0.0.7
|
||||
_sip._udp 3600 SRV 5 0 5060 voip.%zone%.
|
||||
_jabber._tcp 3600 SRV 5 0 5269 jabber.%zone%.
|
||||
_xmpp-client._tcp 3600 SRV 5 0 5222 jabber.%zone%.
|
||||
_xmpp-server._tcp 3600 SRV 5 0 5269 jabber.%zone%.
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
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 "bdbhpt_dynamic" {
|
||||
database "dlopen ../dlz_bdbhpt_dynamic.so T . test.db";
|
||||
};
|
||||
|
|
@ -1,484 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0 and ISC
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
*
|
||||
* 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 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dlz_dbi.h>
|
||||
#include <dlz_list.h>
|
||||
#include <dlz_minimal.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) {
|
||||
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;
|
||||
bool foundzone = false;
|
||||
bool foundrecord = false;
|
||||
bool foundclient = false;
|
||||
char *temp_str = NULL;
|
||||
char *right_str = NULL;
|
||||
char *token = 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 */
|
||||
for (token = strtok_r(right_str, "$", &temp_str); token;
|
||||
token = strtok_r(NULL, "$", &temp_str))
|
||||
{
|
||||
/* 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->direct = 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(token);
|
||||
if (tseg->cmd == NULL) {
|
||||
/* no memory, clean everything up. */
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
/* tseg->cmd points directly to a string. */
|
||||
tseg->direct = 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 = false;
|
||||
foundzone = 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 = false;
|
||||
foundrecord = 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 = false;
|
||||
foundclient = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* we don't need temp_str any more */
|
||||
free(right_str);
|
||||
right_str = NULL;
|
||||
/*
|
||||
* 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 (right_str != NULL) {
|
||||
free(right_str);
|
||||
}
|
||||
|
||||
flag_fail:
|
||||
/* get rid of what was build of the query list */
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
qs = malloc(length + 1);
|
||||
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) {
|
||||
/* 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);
|
||||
}
|
||||
|
||||
char *
|
||||
get_parameter_value(const char *input, const char *key) {
|
||||
int keylen;
|
||||
char *keystart;
|
||||
char value[255];
|
||||
int i;
|
||||
|
||||
if (key == NULL || input == NULL || *input == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
keylen = strlen(key);
|
||||
|
||||
if (keylen < 1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
keystart = strstr(input, key);
|
||||
|
||||
if (keystart == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < 255; i++) {
|
||||
value[i] = keystart[keylen + i];
|
||||
if (isspace((unsigned char)value[i]) || value[i] == '\0') {
|
||||
value[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return strdup(value);
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
# Copyright Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
# Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
#
|
||||
# The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
|
||||
# conceived and contributed by Rob Butler.
|
||||
#
|
||||
# SPDX-License-Identifier: ISC and MPL-2.0
|
||||
#
|
||||
# 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.
|
||||
|
||||
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)
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "dir.h"
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "dlz_minimal.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;
|
||||
break;
|
||||
case ENOENT:
|
||||
result = ISC_R_FILENOTFOUND;
|
||||
break;
|
||||
case EACCES:
|
||||
case EPERM:
|
||||
result = ISC_R_NOPERM;
|
||||
break;
|
||||
case ENOMEM:
|
||||
result = ISC_R_NOMEMORY;
|
||||
break;
|
||||
default:
|
||||
result = ISC_R_UNEXPECTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <dlz_minimal.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);
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1 +0,0 @@
|
|||
../../../../.clang-format.headers
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
* Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0 and ISC
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <dlz_list.h>
|
||||
#include <dlz_minimal.h>
|
||||
#include <dlz_pthread.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* 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;
|
||||
bool 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);
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* 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 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#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)
|
||||
|
||||
#define DLZ_LIST_UNLINK(list, elt, link) \
|
||||
do { \
|
||||
if ((elt)->link.next != NULL) \
|
||||
(elt)->link.next->link.prev = (elt)->link.prev; \
|
||||
else \
|
||||
(list).tail = (elt)->link.prev; \
|
||||
if ((elt)->link.prev != NULL) \
|
||||
(elt)->link.prev->link.next = (elt)->link.next; \
|
||||
else \
|
||||
(list).head = (elt)->link.next; \
|
||||
(elt)->link.prev = (void *)(-1); \
|
||||
(elt)->link.next = (void *)(-1); \
|
||||
} while (0)
|
||||
|
|
@ -1,321 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* 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 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 header provides a minimal set of defines and typedefs needed
|
||||
* for building an external DLZ module for bind9. When creating a new
|
||||
* external DLZ driver, please copy this header into your own source
|
||||
* tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <inttypes.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
typedef unsigned int isc_result_t;
|
||||
typedef uint32_t dns_ttl_t;
|
||||
|
||||
/*
|
||||
* Define DLZ_DLOPEN_VERSION to different values to use older versions
|
||||
* of the interface
|
||||
*/
|
||||
#ifndef DLZ_DLOPEN_VERSION
|
||||
#define DLZ_DLOPEN_VERSION 3
|
||||
#define DLZ_DLOPEN_AGE 0
|
||||
#endif /* ifndef DLZ_DLOPEN_VERSION */
|
||||
|
||||
/* 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
|
||||
#define ISC_R_NOMEMORY 1
|
||||
#define ISC_R_NOPERM 6
|
||||
#define ISC_R_NOSPACE 19
|
||||
#define ISC_R_NOTFOUND 23
|
||||
#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
|
||||
|
||||
/* log levels */
|
||||
#define ISC_LOG_INFO (-1)
|
||||
#define ISC_LOG_NOTICE (-2)
|
||||
#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)
|
||||
|
||||
#define UNCONST(ptr) ((void *)(uintptr_t)(ptr))
|
||||
|
||||
#if !defined(__has_c_attribute)
|
||||
#define __has_c_attribute(x) 0
|
||||
#endif /* if !defined(__has_c_attribute) */
|
||||
|
||||
#if __has_c_attribute(fallthrough)
|
||||
#define FALLTHROUGH [[fallthrough]]
|
||||
#elif __GNUC__ >= 7 && !defined(__clang__)
|
||||
#define FALLTHROUGH __attribute__((fallthrough))
|
||||
#else
|
||||
/* clang-format off */
|
||||
#define FALLTHROUGH do {} while (0) /* FALLTHROUGH */
|
||||
/* clang-format on */
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define UNREACHABLE() __builtin_unreachable()
|
||||
#else
|
||||
#define UNREACHABLE() abort()
|
||||
#endif
|
||||
|
||||
/* opaque structures */
|
||||
typedef void *dns_sdlzlookup_t;
|
||||
typedef void *dns_sdlzallnodes_t;
|
||||
typedef void *dns_view_t;
|
||||
typedef void *dns_dlzdb_t;
|
||||
|
||||
#if DLZ_DLOPEN_VERSION > 1
|
||||
/*
|
||||
* Method and type definitions needed for retrieval of client info
|
||||
* from the caller.
|
||||
*/
|
||||
typedef struct isc_sockaddr {
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in6 sin6;
|
||||
struct sockaddr_un sunix;
|
||||
} type;
|
||||
unsigned int length;
|
||||
void *link;
|
||||
} isc_sockaddr_t;
|
||||
|
||||
typedef struct isc_netaddr {
|
||||
unsigned int family;
|
||||
union {
|
||||
struct in_addr in;
|
||||
struct in6_addr in6;
|
||||
char un[sizeof(((struct sockaddr_un *)0)->sun_path)];
|
||||
} type;
|
||||
uint32_t zone;
|
||||
} isc_netaddr_t;
|
||||
|
||||
typedef struct dns_ecs {
|
||||
isc_netaddr_t addr;
|
||||
uint8_t source;
|
||||
uint8_t scope;
|
||||
} dns_ecs_t;
|
||||
|
||||
#define DNS_CLIENTINFO_VERSION 3
|
||||
typedef struct dns_clientinfo {
|
||||
uint16_t version;
|
||||
void *data;
|
||||
void *dbversion;
|
||||
dns_ecs_t ecs;
|
||||
} dns_clientinfo_t;
|
||||
|
||||
typedef isc_result_t (*dns_clientinfo_sourceip_t)(dns_clientinfo_t *client,
|
||||
isc_sockaddr_t **addrp);
|
||||
|
||||
typedef isc_result_t (*dns_clientinfo_version_t)(dns_clientinfo_t *client,
|
||||
void **addrp);
|
||||
|
||||
#define DNS_CLIENTINFOMETHODS_VERSION 2
|
||||
#define DNS_CLIENTINFOMETHODS_AGE 1
|
||||
typedef struct dns_clientinfomethods {
|
||||
uint16_t version;
|
||||
uint16_t age;
|
||||
dns_clientinfo_sourceip_t sourceip;
|
||||
} dns_clientinfomethods_t;
|
||||
#endif /* DLZ_DLOPEN_VERSION > 1 */
|
||||
|
||||
#define DNS_ECS_FORMATSIZE \
|
||||
sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:XXX.XXX.XXX.XXX%SSSSSSSSSS" \
|
||||
"/NNN/NNN")
|
||||
|
||||
/*
|
||||
* Method definitions for callbacks provided by the dlopen driver
|
||||
*/
|
||||
typedef void
|
||||
log_t(int level, const char *fmt, ...);
|
||||
|
||||
typedef isc_result_t
|
||||
dns_sdlz_putrr_t(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
|
||||
const char *data);
|
||||
|
||||
typedef isc_result_t
|
||||
dns_sdlz_putnamedrr_t(dns_sdlzallnodes_t *allnodes, const char *name,
|
||||
const char *type, dns_ttl_t ttl, const char *data);
|
||||
|
||||
#if DLZ_DLOPEN_VERSION < 3
|
||||
typedef isc_result_t
|
||||
dns_dlz_writeablezone_t(dns_view_t *view, const char *zone_name);
|
||||
#else /* DLZ_DLOPEN_VERSION >= 3 */
|
||||
typedef isc_result_t
|
||||
dns_dlz_writeablezone_t(dns_view_t *view, dns_dlzdb_t *dlzdb,
|
||||
const char *zone_name);
|
||||
#endif /* DLZ_DLOPEN_VERSION */
|
||||
|
||||
/*
|
||||
* prototypes for the functions you can include in your module
|
||||
*/
|
||||
|
||||
/*
|
||||
* dlz_version() is required for all DLZ external drivers. It should
|
||||
* return DLZ_DLOPEN_VERSION. 'flags' is updated to indicate capabilities
|
||||
* of the module. In particular, if the module is thread-safe then it
|
||||
* sets 'flags' to include DNS_SDLZFLAG_THREADSAFE. Other capability
|
||||
* flags may be added in the future.
|
||||
*/
|
||||
int
|
||||
dlz_version(unsigned int *flags);
|
||||
|
||||
/*
|
||||
* dlz_create() is required for all DLZ external drivers.
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata,
|
||||
...);
|
||||
|
||||
/*
|
||||
* dlz_destroy() is optional, and will be called when the driver is
|
||||
* unloaded if supplied
|
||||
*/
|
||||
void
|
||||
dlz_destroy(void *dbdata);
|
||||
|
||||
/*
|
||||
* dlz_findzonedb is required for all DLZ external drivers
|
||||
*/
|
||||
#if DLZ_DLOPEN_VERSION < 3
|
||||
isc_result_t
|
||||
dlz_findzonedb(void *dbdata, const char *name);
|
||||
#else /* DLZ_DLOPEN_VERSION >= 3 */
|
||||
isc_result_t
|
||||
dlz_findzonedb(void *dbdata, const char *name, dns_clientinfomethods_t *methods,
|
||||
dns_clientinfo_t *clientinfo);
|
||||
#endif /* DLZ_DLOPEN_VERSION */
|
||||
|
||||
/*
|
||||
* dlz_lookup is required for all DLZ external drivers
|
||||
*/
|
||||
#if DLZ_DLOPEN_VERSION == 1
|
||||
isc_result_t
|
||||
dlz_lookup(const char *zone, const char *name, void *dbdata,
|
||||
dns_sdlzlookup_t *lookup);
|
||||
#else /* DLZ_DLOPEN_VERSION > 1 */
|
||||
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 /* 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
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_allowzonexfr(void *dbdata, const char *name, const char *client);
|
||||
|
||||
/*
|
||||
* dlz_allnodes() is optional, but must be supplied if supply a
|
||||
* dlz_allowzonexfr() function
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes);
|
||||
|
||||
/*
|
||||
* dlz_newversion() is optional. It should be supplied if you want to
|
||||
* support dynamic updates.
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_newversion(const char *zone, void *dbdata, void **versionp);
|
||||
|
||||
/*
|
||||
* dlz_closeversion() is optional, but must be supplied if you supply a
|
||||
* dlz_newversion() function
|
||||
*/
|
||||
void
|
||||
dlz_closeversion(const char *zone, bool commit, void *dbdata, void **versionp);
|
||||
|
||||
/*
|
||||
* dlz_configure() is optional, but must be supplied if you want to support
|
||||
* dynamic updates
|
||||
*/
|
||||
#if DLZ_DLOPEN_VERSION < 3
|
||||
isc_result_t
|
||||
dlz_configure(dns_view_t *view, void *dbdata);
|
||||
#else /* DLZ_DLOPEN_VERSION >= 3 */
|
||||
isc_result_t
|
||||
dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, void *dbdata);
|
||||
#endif /* DLZ_DLOPEN_VERSION */
|
||||
|
||||
/*
|
||||
* dlz_ssumatch() is optional, but must be supplied if you want to support
|
||||
* dynamic updates
|
||||
*/
|
||||
bool
|
||||
dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr,
|
||||
const char *type, const char *key, uint32_t keydatalen,
|
||||
uint8_t *keydata, void *dbdata);
|
||||
|
||||
/*
|
||||
* dlz_addrdataset() is optional, but must be supplied if you want to
|
||||
* support dynamic updates
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_addrdataset(const char *name, const char *rdatastr, void *dbdata,
|
||||
void *version);
|
||||
|
||||
/*
|
||||
* dlz_subrdataset() is optional, but must be supplied if you want to
|
||||
* support dynamic updates
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_subrdataset(const char *name, const char *rdatastr, void *dbdata,
|
||||
void *version);
|
||||
|
||||
/*
|
||||
* dlz_delrdataset() is optional, but must be supplied if you want to
|
||||
* support dynamic updates
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_delrdataset(const char *name, const char *type, void *dbdata,
|
||||
void *version);
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* 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 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <pthread.h>
|
||||
#define dlz_mutex_t pthread_mutex_t
|
||||
#define dlz_mutex_init pthread_mutex_init
|
||||
#define dlz_mutex_destroy pthread_mutex_destroy
|
||||
#define dlz_mutex_lock pthread_mutex_lock
|
||||
#define dlz_mutex_trylock pthread_mutex_trylock
|
||||
#define dlz_mutex_unlock pthread_mutex_unlock
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
# Copyright Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
# Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
#
|
||||
# The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
|
||||
# conceived and contributed by Rob Butler.
|
||||
#
|
||||
# SPDX-License-Identifier: ISC and MPL-2.0
|
||||
#
|
||||
# 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.
|
||||
|
||||
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)
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,10 +0,0 @@
|
|||
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
|
||||
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
#
|
||||
#
|
||||
# 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 ) MAY ( description ) )
|
||||
|
||||
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 ) MAY ( description ) )
|
||||
|
||||
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 ) )
|
||||
|
||||
objectclass ( 1.3.6.1.4.1.18420.1.2.130
|
||||
NAME 'dlzDNameRecord'
|
||||
DESC 'DNS DName record'
|
||||
SUP dlzGenericRecord STRUCTURAL )
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
# 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: dlzHostName=cname,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzHost
|
||||
dlzHostName: cname
|
||||
|
||||
dn: dlzHostName=dname,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzHost
|
||||
dlzHostName: dname
|
||||
|
||||
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
|
||||
|
||||
dn: dlzRecordID=16,dlzHostName=cname,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzCNameRecord
|
||||
dlzRecordID: 16
|
||||
dlzHostName: cname
|
||||
dlzType: cname
|
||||
dlzData: www
|
||||
dlzTTL: 10
|
||||
|
||||
dn: dlzRecordID=17,dlzHostName=dname,dlzZoneName=example.com,ou=dns,o=bind-dlz
|
||||
objectclass: dlzDNameRecord
|
||||
dlzRecordID: 17
|
||||
dlzHostName: dname
|
||||
dlzType: dname
|
||||
dlzData: example.net.
|
||||
dlzTTL: 10
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
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$))";
|
||||
};
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
# 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
|
||||
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
# Copyright Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
# Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
#
|
||||
# The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
|
||||
# conceived and contributed by Rob Butler.
|
||||
#
|
||||
# SPDX-License-Identifier: ISC and MPL-2.0
|
||||
#
|
||||
# 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.
|
||||
|
||||
prefix = /usr
|
||||
libdir = $(prefix)/lib/bind9
|
||||
|
||||
CFLAGS += -fPIC -g -I../include $(shell mysql_config --cflags)
|
||||
MYSQL_LIBS=$(shell mysql_config --libs)
|
||||
|
||||
all: dlz_mysql_dynamic.so
|
||||
|
||||
dlz_dbi.o: ../common/dlz_dbi.c
|
||||
$(CC) $(CFLAGS) -c ../common/dlz_dbi.c
|
||||
|
||||
dlz_mysql_dynamic.so: dlz_mysql_dynamic.c dlz_dbi.o
|
||||
$(CC) $(CFLAGS) -shared -o dlz_mysql_dynamic.so \
|
||||
dlz_mysql_dynamic.c dlz_dbi.o $(MYSQL_LIBS)
|
||||
|
||||
clean:
|
||||
rm -f dlz_mysql_dynamic.so *.o
|
||||
|
||||
install: dlz_mysql_dynamic.so
|
||||
mkdir -p $(DESTDIR)$(libdir)
|
||||
install dlz_mysql_dynamic.so $(DESTDIR)$(libdir)
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +0,0 @@
|
|||
These files were used for testing on Ubuntu Linux using MySQL
|
||||
|
||||
- Install MySQL: sudo apt-get install mysql-server
|
||||
- Run "mysql --user=USER --password=PASSWORD < dlz.schema" to set up database
|
||||
- Run "mysql --user=USER --password=PASSWORD < dlz.data" to populate it
|
||||
- update named.conf with correct USER and PASSWORD
|
||||
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
use BindDB;
|
||||
INSERT INTO `records` (`id`, `zone`, `ttl`, `type`, `host`, `mx_priority`, `data`, `primary_ns`, `resp_contact`, `serial`, `refresh`, `retry`, `expire`, `minimum`) VALUES
|
||||
(1, 'example.com', 86400, 'SOA', '@', NULL, NULL, 'ns1.example.com.', 'info.example.com.', 2011043001, 10800, 7200, 604800, 86400),
|
||||
(2, 'example.com', 86400, 'NS', '@', NULL, 'ns1.example.com.', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(3, 'example.com', 86400, 'NS', '@', NULL, 'ns2.example.com.', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(4, 'example.com', 86400, 'MX', '@', 10, 'mail.example.com.', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(5, 'example.com', 86400, 'A', '@', NULL, '192.168.0.2', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(6, 'example.com', 86400, 'CNAME', 'www', NULL, '@', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(7, 'example.com', 86400, 'A', 'ns1', NULL, '192.168.0.111', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(8, 'example.com', 86400, 'A', 'ns2', NULL, '192.168.0.222', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(9, 'example.com', 86400, 'A', 'mail', NULL, '192.168.0.3', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
(10, 'example.com', 86400, 'TXT', '@', NULL, 'v=spf1 ip:192.168.0.3 ~all', NULL, NULL, NULL, NULL, NULL, NULL, NULL)
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
CREATE DATABASE `BindDB` DEFAULT CHARACTER SET latin1;
|
||||
USE `BindDB`;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `records` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`zone` varchar(255) NOT NULL,
|
||||
`ttl` int(11) NOT NULL DEFAULT '86400',
|
||||
`type` varchar(255) NOT NULL,
|
||||
`host` varchar(255) NOT NULL DEFAULT '@',
|
||||
`mx_priority` int(11) DEFAULT NULL,
|
||||
`data` text,
|
||||
`primary_ns` varchar(255) DEFAULT NULL,
|
||||
`resp_contact` varchar(255) DEFAULT NULL,
|
||||
`serial` bigint(20) DEFAULT NULL,
|
||||
`refresh` int(11) DEFAULT NULL,
|
||||
`retry` int(11) DEFAULT NULL,
|
||||
`expire` int(11) DEFAULT NULL,
|
||||
`minimum` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `type` (`type`),
|
||||
KEY `host` (`host`),
|
||||
KEY `zone` (`zone`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `xfr` (
|
||||
`zone` varchar(255) NOT NULL,
|
||||
`client` varchar(255) NOT NULL,
|
||||
KEY `zone` (`zone`),
|
||||
KEY `client` (`client`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
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_mysql_dynamic.so
|
||||
{
|
||||
host=127.0.0.1 port=3306 socket=/tmp/mysql.sock
|
||||
dbname=BindDB user=USER pass=PASSWORD threads=2
|
||||
}
|
||||
{SELECT zone FROM records WHERE zone = '$zone$'}
|
||||
{SELECT ttl, type, mx_priority, IF(type = 'TXT', CONCAT('\"',data,'\"'), data) AS data FROM records WHERE zone = '$zone$' AND host = '$record$' AND type <> 'SOA' AND type <> 'NS'}
|
||||
{SELECT ttl, type, data, primary_ns, resp_contact, serial, refresh, retry, expire, minimum FROM records WHERE zone = '$zone$' AND (type = 'SOA' OR type='NS')}
|
||||
{SELECT ttl, type, host, mx_priority, IF(type = 'TXT', CONCAT('\"',data,'\"'), data) AS data, resp_contact, serial, refresh, retry, expire, minimum FROM records WHERE zone = '$zone$' AND type <> 'SOA' AND type <> 'NS'}
|
||||
{SELECT zone FROM xfr where zone='$zone$' AND client = '$client$'}";
|
||||
};
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
# Copyright Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
# Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
#
|
||||
# The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
|
||||
# conceived and contributed by Rob Butler.
|
||||
#
|
||||
# SPDX-License-Identifier: ISC and MPL-2.0
|
||||
#
|
||||
# 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.
|
||||
|
||||
prefix = /usr
|
||||
libdir = $(prefix)/lib/bind9
|
||||
|
||||
CFLAGS += -fPIC -g -I../include $(shell mysql_config --cflags)
|
||||
MYSQL_LIBS=$(shell mysql_config --libs)
|
||||
|
||||
all: dlz_mysqldyn_mod.so
|
||||
|
||||
dlz_dbi.o: ../common/dlz_dbi.c
|
||||
$(CC) $(CFLAGS) -c ../common/dlz_dbi.c
|
||||
|
||||
dlz_mysqldyn_mod.so: dlz_mysqldyn_mod.c dlz_dbi.o
|
||||
$(CC) $(CFLAGS) -shared -o dlz_mysqldyn_mod.so \
|
||||
dlz_mysqldyn_mod.c dlz_dbi.o $(MYSQL_LIBS)
|
||||
|
||||
clean:
|
||||
rm -f dlz_mysqldyn_mod.so *.o
|
||||
|
||||
install: dlz_mysqldyn_mod.so
|
||||
mkdir -p $(DESTDIR)$(libdir)
|
||||
install dlz_mysqldyn_mod.so $(DESTDIR)$(libdir)
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
<!--
|
||||
Copyright Internet Systems Consortium, Inc. ("ISC")
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
|
||||
The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
|
||||
conceived and contributed by Rob Butler.
|
||||
|
||||
SPDX-License-Identifier: ISC and MPL-2.0
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
BIND 9 DLZ MySQL module with support for dynamic DNS (DDNS)
|
||||
|
||||
Adapted from code contributed by Marty Lee, Maui Systems Ltd.
|
||||
|
||||
This is a dynamically loadable zone (DLZ) plugin that uses a fixed-
|
||||
schema MySQL database for back-end storage. It allows zone data
|
||||
to be updated via dynamic DNS updates, and sends DNS NOTIFY packets
|
||||
to other name servers when appropriate.
|
||||
|
||||
The database for this module uses the following schema:
|
||||
|
||||
CREATE TABLE `Zones` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`domain` varchar(128) NOT NULL DEFAULT '',
|
||||
`host` varchar(128) NOT NULL DEFAULT '',
|
||||
`admin` varchar(128) NOT NULL DEFAULT '',
|
||||
`serial` int(11) NOT NULL DEFAULT '1',
|
||||
`expire` int(11) NOT NULL DEFAULT '86400',
|
||||
`refresh` int(11) NOT NULL DEFAULT '86400',
|
||||
`retry` int(11) NOT NULL DEFAULT '86400',
|
||||
`minimum` int(11) NOT NULL DEFAULT '86400',
|
||||
`ttl` int(11) NOT NULL DEFAULT '86400',
|
||||
`writeable` tinyint(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `domain_idx` (`domain`)
|
||||
);
|
||||
|
||||
CREATE TABLE `ZoneData` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`zone_id` int(11) NOT NULL,
|
||||
`name` varchar(128) NOT NULL DEFAULT '',
|
||||
`type` varchar(16) NOT NULL DEFAULT '',
|
||||
`ttl` int(11) NOT NULL DEFAULT '86400',
|
||||
`data` varchar(128) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `zone_idx` (`zone_id`),
|
||||
KEY `name_idx` (`zone_id`, `name`),
|
||||
KEY `type_idx` (`type`)
|
||||
);
|
||||
|
||||
'Zones' contains information about specific zones:
|
||||
- domain: the zone name
|
||||
- admin: the zone administrator
|
||||
- serial, expire, reresh, retry, minimum: values in the SOA record
|
||||
- ttl: default zone TTL
|
||||
- writeable: set to true if the zone can be updated via DDNS
|
||||
|
||||
'ZoneData' contains the individual records within the zone:
|
||||
- zone_id: the 'id' from the corresponding record in Zones
|
||||
- name: domain name, relative to the zone apex. (Data at the zone
|
||||
apex itself may use a blank name or "@".)
|
||||
- type: the RR type, expressed as text
|
||||
- ttl: the record's TTL
|
||||
- data: the records rdata, expressed as text.
|
||||
|
||||
To configure this module in named.conf:
|
||||
|
||||
dlz "mysqldlz" {
|
||||
database "dlopen <path to>/dlz_mysqldyn_mod.so <dbname> [dbhost [dbuser [dbpass]]]";
|
||||
};
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,11 +0,0 @@
|
|||
These files were used for testing on Ubuntu Linux using MySQL
|
||||
|
||||
To set up a test server:
|
||||
- Install MySQL: sudo apt-get install mysql-server
|
||||
- Run "mysql --user=USER --password=PASSWORD < dlz.schema" to set up database
|
||||
- Run "mysql --user=USER --password=PASSWORD < dlz.data" to populate it
|
||||
- Update named.conf with correct USER and PASSWORD
|
||||
- Generate a TSIG key: "ddns-confgen -qz example.com"
|
||||
|
||||
To query the database, use "dig -p 5300 @localhost"
|
||||
To send dynamic updates, use "nsupdate -p 5300 -k ddns.key"
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
use BindDB;
|
||||
insert into `Zones`
|
||||
( `id`, `domain`, `host`, `admin`, `serial`, `expire`,
|
||||
`refresh`, `retry`, `minimum`, `ttl`, `writeable`) VALUES
|
||||
(1, 'example.com', '@', 'info', 2014040100, 10800,
|
||||
7200, 604800, 86400, 86400, 1);
|
||||
|
||||
insert into `ZoneData`
|
||||
(`id`, `zone_id`, `name`, `type`, `data`) VALUES
|
||||
('', 1, '@', 'NS', 'ns1.example.com.'),
|
||||
('', 1, '@', 'NS', 'ns2.example.com.'),
|
||||
('', 1, '@', 'MX', '10 mail.example.com.'),
|
||||
('', 1, '@', 'A', '192.168.0.2'),
|
||||
('', 1, '@', 'TXT', '"v=spf1 ip:192.168.0.3 ~all"'),
|
||||
('', 1, 'www', 'CNAME', 'example.com.'),
|
||||
('', 1, 'mail', 'A', '192.168.0.3'),
|
||||
('', 1, 'ns1', 'A', '192.168.1.111'),
|
||||
('', 1, 'ns2', 'A', '192.168.1.222');
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
CREATE DATABASE `BindDB` DEFAULT CHARACTER SET latin1;
|
||||
USE `BindDB`;
|
||||
|
||||
CREATE TABLE `ZoneData` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`zone_id` int(11) NOT NULL,
|
||||
`name` varchar(128) NOT NULL DEFAULT '',
|
||||
`type` varchar(16) NOT NULL DEFAULT '',
|
||||
`data` varchar(128) NOT NULL DEFAULT '',
|
||||
`ttl` int(11) NOT NULL DEFAULT '86400',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `zone_idx` (`zone_id`),
|
||||
KEY `name_idx` (`zone_id`, `name`),
|
||||
KEY `type_idx` (`type`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
CREATE TABLE `Zones` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`domain` varchar(128) NOT NULL DEFAULT '',
|
||||
`host` varchar(128) NOT NULL DEFAULT '',
|
||||
`admin` varchar(128) NOT NULL DEFAULT '',
|
||||
`serial` int(11) NOT NULL DEFAULT '1',
|
||||
`expire` int(11) NOT NULL DEFAULT '86400',
|
||||
`refresh` int(11) NOT NULL DEFAULT '86400',
|
||||
`retry` int(11) NOT NULL DEFAULT '86400',
|
||||
`minimum` int(11) NOT NULL DEFAULT '86400',
|
||||
`ttl` int(11) NOT NULL DEFAULT '86400',
|
||||
`writeable` tinyint(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `domain_idx` (`domain`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
controls { };
|
||||
|
||||
options {
|
||||
directory ".";
|
||||
port 5300;
|
||||
pid-file "named.pid";
|
||||
session-keyfile "session.key";
|
||||
listen-on { any; };
|
||||
listen-on-v6 { none; };
|
||||
recursion no;
|
||||
};
|
||||
|
||||
include "ddns.key";
|
||||
|
||||
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_mysqldyn_mod.so BindDB localhost root password";
|
||||
};
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
# Copyright Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
# Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
# Copyright (C) John Eaglesham
|
||||
#
|
||||
# The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
|
||||
# conceived and contributed by Rob Butler.
|
||||
#
|
||||
# SPDX-License-Identifier: ISC and MPL-2.0
|
||||
#
|
||||
# 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.
|
||||
|
||||
# For building the dlz_perl_driver driver we don't use
|
||||
# the bind9 build structure as the aim is to provide an
|
||||
# perl_driver that is separable from the bind9 source tree
|
||||
|
||||
CFLAGS += -fPIC -O2 -I../include
|
||||
FLAGS_PERL ?= perl
|
||||
LIBNAME = dlz_perl_driver.so
|
||||
|
||||
all: $(LIBNAME)
|
||||
|
||||
dlz_perl_driver.o: dlz_perl_driver.c
|
||||
$(CC) $(CFLAGS) `${FLAGS_PERL} -MExtUtils::Embed -e ccopts` -c -o dlz_perl_driver.o dlz_perl_driver.c
|
||||
|
||||
|
||||
dlz_perl_callback_clientinfo.c: dlz_perl_callback_clientinfo.xs
|
||||
${FLAGS_PERL} `${FLAGS_PERL} -MConfig -le 'print $$Config{privlibexp}'`/ExtUtils/xsubpp -prototypes -typemap `${FLAGS_PERL} -MConfig -le 'print $$Config{privlibexp}'`/ExtUtils/typemap dlz_perl_callback_clientinfo.xs > dlz_perl_callback_clientinfo.c
|
||||
|
||||
dlz_perl_callback_clientinfo.o: dlz_perl_callback_clientinfo.c
|
||||
$(CC) $(CFLAGS) `${FLAGS_PERL} -MExtUtils::Embed -e ccopts` -c -o dlz_perl_callback_clientinfo.o dlz_perl_callback_clientinfo.c
|
||||
|
||||
|
||||
dlz_perl_callback.c: dlz_perl_callback.xs
|
||||
${FLAGS_PERL} `${FLAGS_PERL} -MConfig -le 'print $$Config{privlibexp}'`/ExtUtils/xsubpp -prototypes -typemap `${FLAGS_PERL} -MConfig -le 'print $$Config{privlibexp}'`/ExtUtils/typemap dlz_perl_callback.xs > dlz_perl_callback.c
|
||||
|
||||
dlz_perl_callback.o: dlz_perl_callback.c
|
||||
$(CC) $(CFLAGS) `${FLAGS_PERL} -MExtUtils::Embed -e ccopts` -c -o dlz_perl_callback.o dlz_perl_callback.c
|
||||
|
||||
|
||||
$(LIBNAME): dlz_perl_driver.o dlz_perl_callback_clientinfo.o dlz_perl_callback.o
|
||||
$(CC) $(LDFLAGS) -shared -o $(LIBNAME) dlz_perl_driver.o dlz_perl_callback_clientinfo.o dlz_perl_callback.o `${FLAGS_PERL} -MExtUtils::Embed -e ldopts`
|
||||
|
||||
clean:
|
||||
rm -f dlz_perl_driver.o dlz_perl_driver.so dlz_perl_callback_clientinfo.c dlz_perl_callback_clientinfo.o dlz_perl_callback.c dlz_perl_callback.o
|
||||
|
||||
install: dlz_perl_driver.so
|
||||
mkdir -p $(DESTDIR)$(libdir)
|
||||
install dlz_perl_driver.so $(DESTDIR)$(libdir)
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
<!--
|
||||
Copyright Internet Systems Consortium, Inc. ("ISC")
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
Copyright (C) John Eaglesham
|
||||
|
||||
The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
|
||||
conceived and contributed by Rob Butler.
|
||||
|
||||
SPDX-License-Identifier: ISC and MPL-2.0
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
|
||||
BIND 9 DLZ Perl module (bind-dlz-tools)
|
||||
|
||||
Written by John Eaglesham <dns@8192.net>
|
||||
|
||||
A dynamically loadable zone (DLZ) plugin embedding a Perl
|
||||
interpreter in BIND, allowing Perl scripts to be written to
|
||||
integrate with BIND and serve DNS data.
|
||||
|
||||
More information/updates at http://bind-dlz-tools.sourceforge.net/
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0 and ISC
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
* Copyright (C) John Eaglesham
|
||||
*
|
||||
* 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 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 "EXTERN.h"
|
||||
#include "perl.h"
|
||||
#include "XSUB.h"
|
||||
#include "dlz_perl_driver.h"
|
||||
|
||||
#include <dlz_minimal.h>
|
||||
|
||||
/* And some XS code. */
|
||||
MODULE = DLZ_Perl PACKAGE = DLZ_Perl
|
||||
|
||||
int
|
||||
LOG_INFO()
|
||||
CODE:
|
||||
RETVAL = ISC_LOG_INFO;
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
int
|
||||
LOG_NOTICE()
|
||||
CODE:
|
||||
RETVAL = ISC_LOG_NOTICE;
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
int
|
||||
LOG_WARNING()
|
||||
CODE:
|
||||
RETVAL = ISC_LOG_WARNING;
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
int
|
||||
LOG_ERROR()
|
||||
CODE:
|
||||
RETVAL = ISC_LOG_ERROR;
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
int
|
||||
LOG_CRITICAL()
|
||||
CODE:
|
||||
RETVAL = ISC_LOG_CRITICAL;
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
|
||||
void
|
||||
log(opaque, level, msg)
|
||||
IV opaque
|
||||
int level
|
||||
char *msg
|
||||
|
||||
PREINIT:
|
||||
log_t *log = (log_t *) opaque;
|
||||
|
||||
CODE:
|
||||
log( level, msg );
|
||||
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0 and ISC
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
* Copyright (C) John Eaglesham
|
||||
*
|
||||
* 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 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#define ADDR_BUF_LEN INET6_ADDRSTRLEN
|
||||
|
||||
#include "EXTERN.h"
|
||||
#include "perl.h"
|
||||
#include "XSUB.h"
|
||||
#include "dlz_perl_driver.h"
|
||||
|
||||
#include <dlz_minimal.h>
|
||||
|
||||
/* And some XS code. */
|
||||
MODULE = DLZ_Perl::clientinfo PACKAGE = DLZ_Perl::clientinfo
|
||||
|
||||
PROTOTYPES: DISABLE
|
||||
|
||||
void
|
||||
sourceip(opaque)
|
||||
SV *opaque
|
||||
|
||||
PREINIT:
|
||||
const char *ret;
|
||||
char addr_buf[ADDR_BUF_LEN];
|
||||
int port;
|
||||
isc_sockaddr_t *src;
|
||||
dlz_perl_clientinfo_opaque *ci;
|
||||
I32 wantarray = GIMME_V;
|
||||
|
||||
PPCODE:
|
||||
if (!SvTRUE(opaque) || !SvIOK(opaque)) XSRETURN_EMPTY;
|
||||
|
||||
/*
|
||||
* Safe, because Perl guarantees that an IV (the type we
|
||||
* pass into DLZ functions who pass it here) is able to
|
||||
* hold a pointer.
|
||||
*/
|
||||
ci = (dlz_perl_clientinfo_opaque *) SvIV(opaque);
|
||||
if (wantarray == G_VOID || ci->methods == NULL ||
|
||||
ci->methods->version - ci->methods->age <
|
||||
DNS_CLIENTINFOMETHODS_VERSION)
|
||||
XSRETURN_EMPTY;
|
||||
|
||||
ci->methods->sourceip(ci->clientinfo, &src);
|
||||
|
||||
switch (src->type.sa.sa_family) {
|
||||
case AF_INET:
|
||||
port = ntohs(src->type.sin.sin_port);
|
||||
ret = inet_ntop(AF_INET,
|
||||
&src->type.sin.sin_addr,
|
||||
addr_buf, ADDR_BUF_LEN);
|
||||
break;
|
||||
case AF_INET6:
|
||||
port = ntohs(src->type.sin6.sin6_port);
|
||||
ret = inet_ntop(AF_INET6,
|
||||
&src->type.sin6.sin6_addr,
|
||||
addr_buf, ADDR_BUF_LEN);
|
||||
break;
|
||||
default:
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
if (ret == NULL) XSRETURN_EMPTY;
|
||||
|
||||
XPUSHs(sv_2mortal(newSVpv(addr_buf, strlen(addr_buf))));
|
||||
if (wantarray == G_ARRAY) XPUSHs(sv_2mortal(newSViv(port)));
|
||||
|
||||
|
|
@ -1,715 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0 and ISC
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
* Copyright (C) John Eaglesham
|
||||
*
|
||||
* 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 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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_perl_driver.h"
|
||||
#include <EXTERN.h>
|
||||
#include <perl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dlz_minimal.h>
|
||||
|
||||
#define BUF_LEN 64 /* Should be big enough, right? hah */
|
||||
|
||||
/* Enable debug logging? */
|
||||
#if 0
|
||||
#define carp(...) cd->log(ISC_LOG_INFO, __VA_ARGS__);
|
||||
#else /* if 0 */
|
||||
#define carp(...)
|
||||
#endif /* if 0 */
|
||||
|
||||
#ifndef MULTIPLICITY
|
||||
/* This is a pretty terrible work-around for handling HUP/rndc reconfig, but
|
||||
* the way BIND/DLZ handles reloads causes it to create a second back end
|
||||
* before removing the first. In the case of a single global interpreter,
|
||||
* serious problems arise. We can hack around this, but it's much better to do
|
||||
* it properly and link against a perl compiled with multiplicity. */
|
||||
static PerlInterpreter *global_perl = NULL;
|
||||
static int global_perl_dont_free = 0;
|
||||
#endif /* ifndef MULTIPLICITY */
|
||||
|
||||
typedef struct config_data {
|
||||
PerlInterpreter *perl;
|
||||
char *perl_source;
|
||||
SV *perl_class;
|
||||
|
||||
/* Functions given to us by bind9 */
|
||||
log_t *log;
|
||||
dns_sdlz_putrr_t *putrr;
|
||||
dns_sdlz_putnamedrr_t *putnamedrr;
|
||||
dns_dlz_writeablezone_t *writeable_zone;
|
||||
} config_data_t;
|
||||
|
||||
/* Note, this code generates warnings due to lost type qualifiers. This code
|
||||
* is (almost) verbatim from perlembed, and is known to work correctly despite
|
||||
* the warnings.
|
||||
*/
|
||||
EXTERN_C void xs_init(pTHX);
|
||||
EXTERN_C void
|
||||
boot_DynaLoader(pTHX_ CV *cv);
|
||||
EXTERN_C void
|
||||
boot_DLZ_Perl__clientinfo(pTHX_ CV *cv);
|
||||
EXTERN_C void
|
||||
boot_DLZ_Perl(pTHX_ CV *cv);
|
||||
EXTERN_C void
|
||||
xs_init(pTHX) {
|
||||
const char *file = __FILE__;
|
||||
dXSUB_SYS;
|
||||
|
||||
/* DynaLoader is a special case */
|
||||
newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
|
||||
newXS("DLZ_Perl::clientinfo::bootstrap", boot_DLZ_Perl__clientinfo,
|
||||
file);
|
||||
newXS("DLZ_Perl::bootstrap", boot_DLZ_Perl, file);
|
||||
}
|
||||
|
||||
/*
|
||||
* methods
|
||||
*/
|
||||
|
||||
/*
|
||||
* remember a helper function, from the bind9 dlz_dlopen driver
|
||||
*/
|
||||
static void
|
||||
b9_add_helper(config_data_t *state, const char *helper_name, void *ptr) {
|
||||
if (strcmp(helper_name, "log") == 0) {
|
||||
state->log = ptr;
|
||||
}
|
||||
if (strcmp(helper_name, "putrr") == 0) {
|
||||
state->putrr = ptr;
|
||||
}
|
||||
if (strcmp(helper_name, "putnamedrr") == 0) {
|
||||
state->putnamedrr = ptr;
|
||||
}
|
||||
if (strcmp(helper_name, "writeable_zone") == 0) {
|
||||
state->writeable_zone = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
dlz_version(unsigned int *flags) {
|
||||
UNUSED(flags);
|
||||
return DLZ_DLOPEN_VERSION;
|
||||
}
|
||||
|
||||
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 retval;
|
||||
int rrcount, r;
|
||||
SV *record_ref;
|
||||
SV **rr_name;
|
||||
SV **rr_type;
|
||||
SV **rr_ttl;
|
||||
SV **rr_data;
|
||||
#ifdef MULTIPLICITY
|
||||
PerlInterpreter *my_perl = cd->perl;
|
||||
#endif /* ifdef MULTIPLICITY */
|
||||
dSP;
|
||||
|
||||
PERL_SET_CONTEXT(cd->perl);
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
|
||||
PUSHMARK(SP);
|
||||
XPUSHs(cd->perl_class);
|
||||
XPUSHs(sv_2mortal(newSVpv(zone, 0)));
|
||||
PUTBACK;
|
||||
|
||||
carp("DLZ Perl: Calling allnodes for zone %s", zone);
|
||||
rrcount = call_method("allnodes", G_ARRAY | G_EVAL);
|
||||
carp("DLZ Perl: Call to allnodes returned rrcount of %i", rrcount);
|
||||
|
||||
SPAGAIN;
|
||||
|
||||
if (SvTRUE(ERRSV)) {
|
||||
(void)POPs;
|
||||
cd->log(ISC_LOG_ERROR,
|
||||
"DLZ Perl: allnodes for zone %s died in eval: %s", zone,
|
||||
SvPV_nolen(ERRSV));
|
||||
retval = ISC_R_FAILURE;
|
||||
goto CLEAN_UP_AND_RETURN;
|
||||
}
|
||||
|
||||
if (!rrcount) {
|
||||
retval = ISC_R_NOTFOUND;
|
||||
goto CLEAN_UP_AND_RETURN;
|
||||
}
|
||||
|
||||
retval = ISC_R_SUCCESS;
|
||||
r = 0;
|
||||
while (r++ < rrcount) {
|
||||
record_ref = POPs;
|
||||
if ((!SvROK(record_ref)) ||
|
||||
(SvTYPE(SvRV(record_ref)) != SVt_PVAV))
|
||||
{
|
||||
cd->log(ISC_LOG_ERROR,
|
||||
"DLZ Perl: allnodes for zone %s "
|
||||
"returned an invalid value "
|
||||
"(expected array of arrayrefs)",
|
||||
zone);
|
||||
retval = ISC_R_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
record_ref = SvRV(record_ref);
|
||||
|
||||
rr_name = av_fetch((AV *)record_ref, 0, 0);
|
||||
rr_type = av_fetch((AV *)record_ref, 1, 0);
|
||||
rr_ttl = av_fetch((AV *)record_ref, 2, 0);
|
||||
rr_data = av_fetch((AV *)record_ref, 3, 0);
|
||||
|
||||
if (rr_name == NULL || rr_type == NULL || rr_ttl == NULL ||
|
||||
rr_data == NULL)
|
||||
{
|
||||
cd->log(ISC_LOG_ERROR,
|
||||
"DLZ Perl: allnodes for zone %s "
|
||||
"returned an array that was missing data",
|
||||
zone);
|
||||
retval = ISC_R_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
carp("DLZ Perl: Got record %s/%s = %s", SvPV_nolen(*rr_name),
|
||||
SvPV_nolen(*rr_type), SvPV_nolen(*rr_data));
|
||||
retval = cd->putnamedrr(allnodes, SvPV_nolen(*rr_name),
|
||||
SvPV_nolen(*rr_type), SvIV(*rr_ttl),
|
||||
SvPV_nolen(*rr_data));
|
||||
if (retval != ISC_R_SUCCESS) {
|
||||
cd->log(ISC_LOG_ERROR,
|
||||
"DLZ Perl: putnamedrr in allnodes "
|
||||
"for zone %s failed with code %i "
|
||||
"(did lookup return invalid record data?)",
|
||||
zone, retval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CLEAN_UP_AND_RETURN:
|
||||
PUTBACK;
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
|
||||
carp("DLZ Perl: Returning from allnodes, r = %i, retval = %i", r,
|
||||
retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dlz_allowzonexfr(void *dbdata, const char *name, const char *client) {
|
||||
config_data_t *cd = (config_data_t *)dbdata;
|
||||
int r;
|
||||
isc_result_t retval;
|
||||
#ifdef MULTIPLICITY
|
||||
PerlInterpreter *my_perl = cd->perl;
|
||||
#endif /* ifdef MULTIPLICITY */
|
||||
dSP;
|
||||
|
||||
PERL_SET_CONTEXT(cd->perl);
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
|
||||
PUSHMARK(SP);
|
||||
XPUSHs(cd->perl_class);
|
||||
XPUSHs(sv_2mortal(newSVpv(name, 0)));
|
||||
XPUSHs(sv_2mortal(newSVpv(client, 0)));
|
||||
PUTBACK;
|
||||
|
||||
r = call_method("allowzonexfr", G_SCALAR | G_EVAL);
|
||||
SPAGAIN;
|
||||
|
||||
if (SvTRUE(ERRSV)) {
|
||||
/*
|
||||
* On error there's an undef at the top of the stack. Pop
|
||||
* it away so we don't leave junk on the stack for the next
|
||||
* caller.
|
||||
*/
|
||||
(void)POPs;
|
||||
cd->log(ISC_LOG_ERROR,
|
||||
"DLZ Perl: allowzonexfr died in eval: %s",
|
||||
SvPV_nolen(ERRSV));
|
||||
retval = ISC_R_FAILURE;
|
||||
} else if (r == 0) {
|
||||
/* Client returned nothing -- zone not found. */
|
||||
retval = ISC_R_NOTFOUND;
|
||||
} else if (r > 1) {
|
||||
/* Once again, clean out the stack when possible. */
|
||||
while (r--) {
|
||||
POPi;
|
||||
}
|
||||
cd->log(ISC_LOG_ERROR, "DLZ Perl: allowzonexfr returned too "
|
||||
"many parameters!");
|
||||
retval = ISC_R_FAILURE;
|
||||
} else {
|
||||
/*
|
||||
* Client returned true/false -- we're authoritative for
|
||||
* the zone.
|
||||
*/
|
||||
r = POPi;
|
||||
if (r) {
|
||||
retval = ISC_R_SUCCESS;
|
||||
} else {
|
||||
retval = ISC_R_NOPERM;
|
||||
}
|
||||
}
|
||||
|
||||
PUTBACK;
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if DLZ_DLOPEN_VERSION < 3
|
||||
isc_result_t
|
||||
dlz_findzonedb(void *dbdata, const char *name)
|
||||
#else /* if DLZ_DLOPEN_VERSION < 3 */
|
||||
isc_result_t
|
||||
dlz_findzonedb(void *dbdata, const char *name, dns_clientinfomethods_t *methods,
|
||||
dns_clientinfo_t *clientinfo)
|
||||
#endif /* if DLZ_DLOPEN_VERSION < 3 */
|
||||
{
|
||||
config_data_t *cd = (config_data_t *)dbdata;
|
||||
int r;
|
||||
isc_result_t retval;
|
||||
#ifdef MULTIPLICITY
|
||||
PerlInterpreter *my_perl = cd->perl;
|
||||
#endif /* ifdef MULTIPLICITY */
|
||||
|
||||
#if DLZ_DLOPEN_VERSION >= 3
|
||||
UNUSED(methods);
|
||||
UNUSED(clientinfo);
|
||||
#endif /* if DLZ_DLOPEN_VERSION >= 3 */
|
||||
|
||||
dSP;
|
||||
carp("DLZ Perl: findzone looking for '%s'", name);
|
||||
|
||||
PERL_SET_CONTEXT(cd->perl);
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
|
||||
PUSHMARK(SP);
|
||||
XPUSHs(cd->perl_class);
|
||||
XPUSHs(sv_2mortal(newSVpv(name, 0)));
|
||||
PUTBACK;
|
||||
|
||||
r = call_method("findzone", G_SCALAR | G_EVAL);
|
||||
SPAGAIN;
|
||||
|
||||
if (SvTRUE(ERRSV)) {
|
||||
/*
|
||||
* On error there's an undef at the top of the stack. Pop
|
||||
* it away so we don't leave junk on the stack for the next
|
||||
* caller.
|
||||
*/
|
||||
(void)POPs;
|
||||
cd->log(ISC_LOG_ERROR, "DLZ Perl: findzone died in eval: %s",
|
||||
SvPV_nolen(ERRSV));
|
||||
retval = ISC_R_FAILURE;
|
||||
} else if (r == 0) {
|
||||
retval = ISC_R_FAILURE;
|
||||
} else if (r > 1) {
|
||||
/* Once again, clean out the stack when possible. */
|
||||
while (r--) {
|
||||
POPi;
|
||||
}
|
||||
cd->log(ISC_LOG_ERROR, "DLZ Perl: findzone returned too many "
|
||||
"parameters!");
|
||||
retval = ISC_R_FAILURE;
|
||||
} else {
|
||||
r = POPi;
|
||||
if (r) {
|
||||
retval = ISC_R_SUCCESS;
|
||||
} else {
|
||||
retval = ISC_R_NOTFOUND;
|
||||
}
|
||||
}
|
||||
|
||||
PUTBACK;
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if DLZ_DLOPEN_VERSION == 1
|
||||
isc_result_t
|
||||
dlz_lookup(const char *zone, const char *name, void *dbdata,
|
||||
dns_sdlzlookup_t *lookup)
|
||||
#else /* if DLZ_DLOPEN_VERSION == 1 */
|
||||
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 /* if DLZ_DLOPEN_VERSION == 1 */
|
||||
{
|
||||
isc_result_t retval;
|
||||
config_data_t *cd = (config_data_t *)dbdata;
|
||||
int rrcount, r;
|
||||
dlz_perl_clientinfo_opaque opaque;
|
||||
SV *record_ref;
|
||||
SV **rr_type;
|
||||
SV **rr_ttl;
|
||||
SV **rr_data;
|
||||
#ifdef MULTIPLICITY
|
||||
PerlInterpreter *my_perl = cd->perl;
|
||||
#endif /* ifdef MULTIPLICITY */
|
||||
|
||||
#if DLZ_DLOPEN_VERSION >= 2
|
||||
UNUSED(methods);
|
||||
UNUSED(clientinfo);
|
||||
#endif /* if DLZ_DLOPEN_VERSION >= 2 */
|
||||
|
||||
dSP;
|
||||
PERL_SET_CONTEXT(cd->perl);
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
|
||||
opaque.methods = methods;
|
||||
opaque.clientinfo = clientinfo;
|
||||
|
||||
PUSHMARK(SP);
|
||||
XPUSHs(cd->perl_class);
|
||||
XPUSHs(sv_2mortal(newSVpv(name, 0)));
|
||||
XPUSHs(sv_2mortal(newSVpv(zone, 0)));
|
||||
XPUSHs(sv_2mortal(newSViv((IV)&opaque)));
|
||||
PUTBACK;
|
||||
|
||||
carp("DLZ Perl: Searching for name %s in zone %s", name, zone);
|
||||
rrcount = call_method("lookup", G_ARRAY | G_EVAL);
|
||||
carp("DLZ Perl: Call to lookup returned %i", rrcount);
|
||||
|
||||
SPAGAIN;
|
||||
|
||||
if (SvTRUE(ERRSV)) {
|
||||
(void)POPs;
|
||||
cd->log(ISC_LOG_ERROR, "DLZ Perl: lookup died in eval: %s",
|
||||
SvPV_nolen(ERRSV));
|
||||
retval = ISC_R_FAILURE;
|
||||
goto CLEAN_UP_AND_RETURN;
|
||||
}
|
||||
|
||||
if (!rrcount) {
|
||||
retval = ISC_R_NOTFOUND;
|
||||
goto CLEAN_UP_AND_RETURN;
|
||||
}
|
||||
|
||||
retval = ISC_R_SUCCESS;
|
||||
r = 0;
|
||||
while (r++ < rrcount) {
|
||||
record_ref = POPs;
|
||||
if ((!SvROK(record_ref)) ||
|
||||
(SvTYPE(SvRV(record_ref)) != SVt_PVAV))
|
||||
{
|
||||
cd->log(ISC_LOG_ERROR, "DLZ Perl: lookup returned an "
|
||||
"invalid value (expected array "
|
||||
"of arrayrefs)!");
|
||||
retval = ISC_R_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
record_ref = SvRV(record_ref);
|
||||
|
||||
rr_type = av_fetch((AV *)record_ref, 0, 0);
|
||||
rr_ttl = av_fetch((AV *)record_ref, 1, 0);
|
||||
rr_data = av_fetch((AV *)record_ref, 2, 0);
|
||||
|
||||
if (rr_type == NULL || rr_ttl == NULL || rr_data == NULL) {
|
||||
cd->log(ISC_LOG_ERROR,
|
||||
"DLZ Perl: lookup for record %s in "
|
||||
"zone %s returned an array that was "
|
||||
"missing data",
|
||||
name, zone);
|
||||
retval = ISC_R_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
carp("DLZ Perl: Got record %s = %s", SvPV_nolen(*rr_type),
|
||||
SvPV_nolen(*rr_data));
|
||||
retval = cd->putrr(lookup, SvPV_nolen(*rr_type), SvIV(*rr_ttl),
|
||||
SvPV_nolen(*rr_data));
|
||||
|
||||
if (retval != ISC_R_SUCCESS) {
|
||||
cd->log(ISC_LOG_ERROR,
|
||||
"DLZ Perl: putrr for lookup of %s in "
|
||||
"zone %s failed with code %i "
|
||||
"(did lookup return invalid record data?)",
|
||||
name, zone, retval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CLEAN_UP_AND_RETURN:
|
||||
PUTBACK;
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
|
||||
carp("DLZ Perl: Returning from lookup, r = %i, retval = %i", r, retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static const char *
|
||||
#ifdef MULTIPLICITY
|
||||
missing_perl_method(const char *perl_class_name, PerlInterpreter *my_perl)
|
||||
#else /* ifdef MULTIPLICITY */
|
||||
missing_perl_method(const char *perl_class_name)
|
||||
#endif /* ifdef MULTIPLICITY */
|
||||
{
|
||||
char full_name[BUF_LEN];
|
||||
const char *methods[] = { "new", "findzone", "lookup", NULL };
|
||||
int i = 0;
|
||||
|
||||
while (methods[i] != NULL) {
|
||||
snprintf(full_name, BUF_LEN, "%s::%s", perl_class_name,
|
||||
methods[i]);
|
||||
|
||||
if (get_cv(full_name, 0) == NULL) {
|
||||
return methods[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata,
|
||||
...) {
|
||||
config_data_t *cd;
|
||||
char *perlrun[] = { (char *)"", NULL, (char *)"dlz perl", NULL };
|
||||
char *perl_class_name;
|
||||
int r;
|
||||
va_list ap;
|
||||
const char *helper_name;
|
||||
const char *missing_method_name;
|
||||
char *call_argv_args = NULL;
|
||||
#ifdef MULTIPLICITY
|
||||
PerlInterpreter *my_perl;
|
||||
#endif /* ifdef MULTIPLICITY */
|
||||
|
||||
cd = malloc(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);
|
||||
|
||||
if (argc < 2) {
|
||||
cd->log(ISC_LOG_ERROR,
|
||||
"DLZ Perl '%s': Missing script argument.", dlzname);
|
||||
free(cd);
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
if (argc < 3) {
|
||||
cd->log(ISC_LOG_ERROR,
|
||||
"DLZ Perl '%s': Missing class name argument.", dlzname);
|
||||
free(cd);
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
perl_class_name = argv[2];
|
||||
|
||||
cd->log(ISC_LOG_INFO, "DLZ Perl '%s': Loading '%s' from location '%s'",
|
||||
dlzname, perl_class_name, argv[1], argc);
|
||||
|
||||
#ifndef MULTIPLICITY
|
||||
if (global_perl) {
|
||||
/*
|
||||
* PERL_SET_CONTEXT not needed here as we're guaranteed to
|
||||
* have an implicit context thanks to an undefined
|
||||
* MULTIPLICITY.
|
||||
*/
|
||||
PL_perl_destruct_level = 1;
|
||||
perl_destruct(global_perl);
|
||||
perl_free(global_perl);
|
||||
global_perl = NULL;
|
||||
global_perl_dont_free = 1;
|
||||
}
|
||||
#endif /* ifndef MULTIPLICITY */
|
||||
|
||||
cd->perl = perl_alloc();
|
||||
if (cd->perl == NULL) {
|
||||
free(cd);
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
#ifdef MULTIPLICITY
|
||||
my_perl = cd->perl;
|
||||
#endif /* ifdef MULTIPLICITY */
|
||||
PERL_SET_CONTEXT(cd->perl);
|
||||
|
||||
/*
|
||||
* We will re-create the interpreter during an rndc reconfig, so we
|
||||
* must set this variable per perlembed in order to insure we can
|
||||
* clean up Perl at a later time.
|
||||
*/
|
||||
PL_perl_destruct_level = 1;
|
||||
perl_construct(cd->perl);
|
||||
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
|
||||
/* Prevent crashes from clients writing to $0 */
|
||||
PL_origalen = 1;
|
||||
|
||||
cd->perl_source = strdup(argv[1]);
|
||||
if (cd->perl_source == NULL) {
|
||||
free(cd);
|
||||
return ISC_R_NOMEMORY;
|
||||
}
|
||||
|
||||
perlrun[1] = cd->perl_source;
|
||||
if (perl_parse(cd->perl, xs_init, 3, perlrun, (char **)NULL)) {
|
||||
cd->log(ISC_LOG_ERROR,
|
||||
"DLZ Perl '%s': Failed to parse Perl script, aborting",
|
||||
dlzname);
|
||||
goto CLEAN_UP_PERL_AND_FAIL;
|
||||
}
|
||||
|
||||
/* Let Perl know about our callbacks. */
|
||||
call_argv("DLZ_Perl::clientinfo::bootstrap", G_DISCARD | G_NOARGS,
|
||||
&call_argv_args);
|
||||
call_argv("DLZ_Perl::bootstrap", G_DISCARD | G_NOARGS, &call_argv_args);
|
||||
|
||||
/*
|
||||
* Run the script. We don't really need to do this since we have
|
||||
* the init callback, but there's not really a downside either.
|
||||
*/
|
||||
if (perl_run(cd->perl)) {
|
||||
cd->log(ISC_LOG_ERROR,
|
||||
"DLZ Perl '%s': Script exited with an error, aborting",
|
||||
dlzname);
|
||||
goto CLEAN_UP_PERL_AND_FAIL;
|
||||
}
|
||||
|
||||
#ifdef MULTIPLICITY
|
||||
if ((missing_method_name = missing_perl_method(perl_class_name,
|
||||
my_perl)))
|
||||
#else /* ifdef MULTIPLICITY */
|
||||
if ((missing_method_name = missing_perl_method(perl_class_name)))
|
||||
#endif /* ifdef MULTIPLICITY */
|
||||
{
|
||||
cd->log(ISC_LOG_ERROR,
|
||||
"DLZ Perl '%s': Missing required function '%s', "
|
||||
"aborting",
|
||||
dlzname, missing_method_name);
|
||||
goto CLEAN_UP_PERL_AND_FAIL;
|
||||
}
|
||||
|
||||
dSP;
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
|
||||
PUSHMARK(SP);
|
||||
XPUSHs(sv_2mortal(newSVpv(perl_class_name, 0)));
|
||||
|
||||
/* Build flattened hash of config info. */
|
||||
XPUSHs(sv_2mortal(newSVpv("log_context", 0)));
|
||||
XPUSHs(sv_2mortal(newSViv((IV)cd->log)));
|
||||
|
||||
/* Argument to pass to new? */
|
||||
if (argc == 4) {
|
||||
XPUSHs(sv_2mortal(newSVpv("argv", 0)));
|
||||
XPUSHs(sv_2mortal(newSVpv(argv[3], 0)));
|
||||
}
|
||||
|
||||
PUTBACK;
|
||||
|
||||
r = call_method("new", G_EVAL | G_SCALAR);
|
||||
|
||||
SPAGAIN;
|
||||
|
||||
if (r) {
|
||||
cd->perl_class = SvREFCNT_inc(POPs);
|
||||
}
|
||||
|
||||
PUTBACK;
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
|
||||
if (SvTRUE(ERRSV)) {
|
||||
(void)POPs;
|
||||
cd->log(ISC_LOG_ERROR, "DLZ Perl '%s': new died in eval: %s",
|
||||
dlzname, SvPV_nolen(ERRSV));
|
||||
goto CLEAN_UP_PERL_AND_FAIL;
|
||||
}
|
||||
|
||||
if (!r || !sv_isobject(cd->perl_class)) {
|
||||
cd->log(ISC_LOG_ERROR,
|
||||
"DLZ Perl '%s': new failed to return a blessed object",
|
||||
dlzname);
|
||||
goto CLEAN_UP_PERL_AND_FAIL;
|
||||
}
|
||||
|
||||
*dbdata = cd;
|
||||
|
||||
#ifndef MULTIPLICITY
|
||||
global_perl = cd->perl;
|
||||
#endif /* ifndef MULTIPLICITY */
|
||||
return ISC_R_SUCCESS;
|
||||
|
||||
CLEAN_UP_PERL_AND_FAIL:
|
||||
PL_perl_destruct_level = 1;
|
||||
perl_destruct(cd->perl);
|
||||
perl_free(cd->perl);
|
||||
free(cd->perl_source);
|
||||
free(cd);
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
|
||||
void
|
||||
dlz_destroy(void *dbdata) {
|
||||
config_data_t *cd = (config_data_t *)dbdata;
|
||||
#ifdef MULTIPLICITY
|
||||
PerlInterpreter *my_perl = cd->perl;
|
||||
#endif /* ifdef MULTIPLICITY */
|
||||
|
||||
cd->log(ISC_LOG_INFO, "DLZ Perl: Unloading driver.");
|
||||
|
||||
#ifndef MULTIPLICITY
|
||||
if (!global_perl_dont_free) {
|
||||
#endif /* ifndef MULTIPLICITY */
|
||||
PERL_SET_CONTEXT(cd->perl);
|
||||
PL_perl_destruct_level = 1;
|
||||
perl_destruct(cd->perl);
|
||||
perl_free(cd->perl);
|
||||
#ifndef MULTIPLICITY
|
||||
global_perl_dont_free = 0;
|
||||
global_perl = NULL;
|
||||
}
|
||||
#endif /* ifndef MULTIPLICITY */
|
||||
|
||||
free(cd->perl_source);
|
||||
free(cd);
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0 and ISC
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
* Copyright (C) John Eaglesham
|
||||
*
|
||||
* 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 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <dlz_minimal.h>
|
||||
|
||||
/* This is the only part that differs from dlz_minimal.h. */
|
||||
typedef struct dlz_perl_clientinfo_opaque {
|
||||
dns_clientinfomethods_t *methods;
|
||||
dns_clientinfo_t *clientinfo;
|
||||
} dlz_perl_clientinfo_opaque;
|
||||
|
|
@ -1,185 +0,0 @@
|
|||
# Copyright Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
# Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
# Copyright (C) John Eaglesham
|
||||
#
|
||||
# The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
|
||||
# conceived and contributed by Rob Butler.
|
||||
#
|
||||
# SPDX-License-Identifier: ISC and MPL-2.0
|
||||
#
|
||||
# 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.
|
||||
package dlz_perl_example;
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Data::Dumper;
|
||||
$Data::Dumper::Sortkeys = 1;
|
||||
|
||||
# Constructor. Everything after the class name can be folded into a hash of
|
||||
# various options and settings. Right now only log_context and argv are
|
||||
# available.
|
||||
sub new {
|
||||
my ( $class, %config ) = @_;
|
||||
my $self = {};
|
||||
bless $self, $class;
|
||||
|
||||
$self->{log} = sub {
|
||||
my ( $level, $msg ) = @_;
|
||||
DLZ_Perl::log( $config{log_context}, $level, $msg );
|
||||
};
|
||||
|
||||
if ( $config{argv} ) { warn "Got argv: $config{argv}\n"; }
|
||||
|
||||
$self->{zones} = {
|
||||
'example.com' => {
|
||||
'@' => [
|
||||
{
|
||||
type => 'SOA',
|
||||
ttl => 86400,
|
||||
data =>
|
||||
'ns1.example.com. hostmaster.example.com. 12345 172800 900 1209600 3600',
|
||||
}
|
||||
],
|
||||
perlrr => [
|
||||
{
|
||||
type => 'A',
|
||||
ttl => 444,
|
||||
data => '1.1.1.1',
|
||||
},
|
||||
{
|
||||
type => 'A',
|
||||
ttl => 444,
|
||||
data => '1.1.1.2',
|
||||
}
|
||||
],
|
||||
perltime => [
|
||||
{
|
||||
code => sub {
|
||||
return ['TXT', '1', time()];
|
||||
},
|
||||
},
|
||||
],
|
||||
sourceip => [
|
||||
{
|
||||
code => sub {
|
||||
my ( $opaque ) = @_;
|
||||
# Passing anything other than the proper opaque value,
|
||||
# 0, or undef to this function will cause a crash (at
|
||||
# best!).
|
||||
my ( $addr, $port ) =
|
||||
DLZ_Perl::clientinfo::sourceip( $opaque );
|
||||
if ( !$addr ) { $addr = $port = 'unknown'; }
|
||||
return ['TXT', '1', $addr], ['TXT', '1', $port];
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
$self->{log}->(
|
||||
DLZ_Perl::LOG_INFO(),
|
||||
'DLZ Perl Script: Called init. Loaded zone data: '
|
||||
. Dumper( $self->{zones} )
|
||||
);
|
||||
return $self;
|
||||
}
|
||||
|
||||
# Do we have data for this zone? Expects a simple true or false return value.
|
||||
sub findzone {
|
||||
my ( $self, $zone ) = @_;
|
||||
$self->{log}->(
|
||||
DLZ_Perl::LOG_INFO(),
|
||||
"DLZ Perl Script: Called findzone, looking for zone $zone"
|
||||
);
|
||||
|
||||
return exists $self->{zones}->{$zone};
|
||||
}
|
||||
|
||||
# Return the data for a given record in a given zone. The final parameter is
|
||||
# an opaque value that can be passed to DLZ_Perl::clientinfo::sourceip to
|
||||
# retrieve the client source IP and port. Expected return value is an array
|
||||
# of array refs, with each array ref representing one record and containing
|
||||
# the type, ttl, and data in that order. Data is as it appears in a zone file.
|
||||
sub lookup {
|
||||
my ( $self, $name, $zone, $client_info ) = @_;
|
||||
$self->{log}->(
|
||||
DLZ_Perl::LOG_INFO(),
|
||||
"DLZ Perl Script: Called lookup, looking for record $name in zone $zone"
|
||||
);
|
||||
return unless $self->{zones}->{$zone}->{$name};
|
||||
|
||||
my @results;
|
||||
foreach my $rr ( @{ $self->{zones}->{$zone}->{$name} } ) {
|
||||
if ( $rr->{'code'} ) {
|
||||
my @r = $rr->{'code'}->( $client_info );
|
||||
if ( @r ) {
|
||||
push @results, @r;
|
||||
}
|
||||
} else {
|
||||
push @results, [$rr->{'type'}, $rr->{'ttl'}, $rr->{'data'}];
|
||||
}
|
||||
}
|
||||
|
||||
return @results;
|
||||
}
|
||||
|
||||
# Will we allow zone transfer for this client? Expects a simple true or false
|
||||
# return value.
|
||||
sub allowzonexfr {
|
||||
my ( $self, $zone, $client ) = @_;
|
||||
$self->{log}->(
|
||||
DLZ_Perl::LOG_INFO(),
|
||||
"DLZ Perl Script: Called allowzonexfr, looking for zone $zone for " .
|
||||
"client $client"
|
||||
);
|
||||
if ( $client eq '127.0.0.1' ) { return 1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Note the return AoA for this method differs from lookup in that it must
|
||||
# return the name of the record as well as the other data.
|
||||
sub allnodes {
|
||||
my ( $self, $zone ) = @_;
|
||||
my @results;
|
||||
$self->{log}->(
|
||||
DLZ_Perl::LOG_INFO(),
|
||||
"DLZ Perl Script: Called allnodes, looking for zone $zone"
|
||||
);
|
||||
|
||||
foreach my $name ( keys %{ $self->{zones}->{$zone} } ) {
|
||||
foreach my $rr ( @{ $self->{zones}->{$zone}->{$name} } ) {
|
||||
if ( $rr->{'code'} ) {
|
||||
my @r = $rr->{'code'}->();
|
||||
# The code returns an array of array refs without the name.
|
||||
# This makes things easy for lookup but hard here. We must
|
||||
# iterate over each array ref and inject the name into it.
|
||||
foreach my $a ( @r ) {
|
||||
unshift @{$a}, $name;
|
||||
}
|
||||
push @results, @r;
|
||||
} else {
|
||||
push @results,
|
||||
[$name, $rr->{'type'}, $rr->{'ttl'}, $rr->{'data'}];
|
||||
}
|
||||
}
|
||||
}
|
||||
return @results;
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
options {
|
||||
port 5300;
|
||||
pid-file "named.pid";
|
||||
session-keyfile "session.key";
|
||||
listen-on { 127.0.0.1; };
|
||||
listen-on-v6 { none; };
|
||||
recursion no;
|
||||
notify no;
|
||||
};
|
||||
|
||||
dlz "perl zone" {
|
||||
database "dlopen ../dlz_perl_driver.so dlz_perl_example.pm dlz_perl_example";
|
||||
};
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
# Copyright Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
# Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
#
|
||||
# The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
|
||||
# conceived and contributed by Rob Butler.
|
||||
#
|
||||
# SPDX-License-Identifier: ISC and MPL-2.0
|
||||
#
|
||||
# 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.
|
||||
|
||||
prefix = /usr
|
||||
libdir = $(prefix)/lib/bind9
|
||||
|
||||
CFLAGS += -fPIC -g -I../include
|
||||
SQLITE3_LIBS=-lsqlite3
|
||||
|
||||
all: dlz_sqlite3_dynamic.so
|
||||
|
||||
dlz_dbi.o: ../common/dlz_dbi.c
|
||||
$(CC) $(CFLAGS) -c ../common/dlz_dbi.c
|
||||
|
||||
dlz_sqlite3_dynamic.so: dlz_sqlite3_dynamic.c dlz_dbi.o
|
||||
$(CC) $(CFLAGS) -shared -o dlz_sqlite3_dynamic.so \
|
||||
dlz_sqlite3_dynamic.c dlz_dbi.o $(SQLITE3_LIBS)
|
||||
|
||||
clean:
|
||||
rm -f dlz_sqlite3_dynamic.so *.o
|
||||
|
||||
install: dlz_sqlite3_dynamic.so
|
||||
mkdir -p $(DESTDIR)$(libdir)
|
||||
install dlz_sqlite3_dynamic.so $(DESTDIR)$(libdir)
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,10 +0,0 @@
|
|||
These files were used for testing on Ubuntu Linux using SQLite3
|
||||
|
||||
- Install SQLite3: sudo apt-get install sqlite3 libsqlite3-dev
|
||||
- Build sqlite3 DLZ module
|
||||
- Run "sqlite3 BindDB < dlz.schema" to set up database
|
||||
- Run "sqlite3 BindDB < dlz.data" to populate it
|
||||
- Run "named -gc named.conf"
|
||||
- Send test queries, e.g "dig @localhost -p 5300 example.com",
|
||||
"dig @localhost -p 5300 axfr example.com" (AXFR should be
|
||||
allowed from 127.0.0.1 only).
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
INSERT INTO `records`
|
||||
(`zone`, `ttl`, `type`, `host`, `mx_priority`, `data`, `primary_ns`, `resp_contact`, `serial`, `refresh`, `retry`, `expire`, `minimum`)
|
||||
VALUES
|
||||
('example.com', 86400, 'SOA', '@', NULL, NULL, 'ns1.example.com.', 'info.example.com.', 2011043001, 10800, 7200, 604800, 86400),
|
||||
('example.com', 86400, 'NS', '@', NULL, 'ns1.example.com.', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
('example.com', 86400, 'NS', '@', NULL, 'ns2.example.com.', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
('example.com', 86400, 'MX', '@', 10, 'mail.example.com.', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
('example.com', 86400, 'A', '@', NULL, '192.168.0.2', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
('example.com', 86400, 'CNAME', 'www', NULL, '@', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
('example.com', 86400, 'A', 'ns1', NULL, '192.168.0.111', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
('example.com', 86400, 'A', 'ns2', NULL, '192.168.0.222', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
('example.com', 86400, 'A', 'mail', NULL, '192.168.0.3', NULL, NULL, NULL, NULL, NULL, NULL, NULL),
|
||||
('example.com', 86400, 'TXT', '@', NULL, 'v=spf1 ip:192.168.0.3 ~all', NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
INSERT INTO `xfr`
|
||||
(`zone`, `client`)
|
||||
VALUES
|
||||
('example.com', '127.0.0.1');
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
CREATE TABLE IF NOT EXISTS `records` (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`zone` CHAR(255) NOT NULL,
|
||||
`ttl` INT NOT NULL DEFAULT '86400',
|
||||
`type` CHAR(255) NOT NULL,
|
||||
`host` CHAR(255) NOT NULL DEFAULT '@',
|
||||
`mx_priority` INT DEFAULT NULL,
|
||||
`data` text,
|
||||
`primary_ns` CHAR(255) DEFAULT NULL,
|
||||
`resp_contact` CHAR(255) DEFAULT NULL,
|
||||
`serial` bigint DEFAULT NULL,
|
||||
`refresh` INT DEFAULT NULL,
|
||||
`retry` INT DEFAULT NULL,
|
||||
`expire` INT DEFAULT NULL,
|
||||
`minimum` INT DEFAULT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS record_type on records (type);
|
||||
CREATE INDEX IF NOT EXISTS record_host on records (host);
|
||||
CREATE INDEX IF NOT EXISTS record_zone on records (zone);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `xfr` (
|
||||
`zone` CHAR(255) NOT NULL,
|
||||
`client` CHAR(255) NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS xfr_zone on xfr (zone);
|
||||
CREATE INDEX IF NOT EXISTS xfr_client on xfr (client);
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
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_sqlite3_dynamic.so
|
||||
{
|
||||
dbname=BindDB threads=2
|
||||
}
|
||||
{SELECT zone FROM records WHERE zone = '$zone$'}
|
||||
{SELECT ttl, type, mx_priority, CASE WHEN type = 'TXT' THEN '\"' || data || '\"' ELSE data END AS data FROM records WHERE zone = '$zone$' AND host = '$record$' AND type <> 'SOA' AND type <> 'NS'}
|
||||
{SELECT ttl, type, data, primary_ns, resp_contact, serial, refresh, retry, expire, minimum FROM records WHERE zone = '$zone$' AND (type = 'SOA' OR type='NS')}
|
||||
{SELECT ttl, type, host, mx_priority, CASE WHEN type = 'TXT' THEN '\"' || data || '\"' ELSE data END AS data, resp_contact, serial, refresh, retry, expire, minimum FROM records WHERE zone = '$zone$' AND type <> 'SOA' AND type <> 'NS'}
|
||||
{SELECT zone FROM xfr where zone='$zone$' AND client = '$client$'}";
|
||||
};
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
# Copyright Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
# Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
# Copyright (C) Vadim Goncharov, Russia, vadim_nuclight@mail.ru.
|
||||
#
|
||||
# The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
|
||||
# conceived and contributed by Rob Butler.
|
||||
#
|
||||
# SPDX-License-Identifier: ISC and MPL-2.0
|
||||
#
|
||||
# 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.
|
||||
|
||||
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)
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
<!--
|
||||
Copyright Internet Systems Consortium, Inc. ("ISC")
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
Copyright (C) Vadim Goncharov, Russia, vadim_nuclight@mail.ru.
|
||||
|
||||
The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
|
||||
conceived and contributed by Rob Butler.
|
||||
|
||||
SPDX-License-Identifier: ISC and MPL-2.0
|
||||
|
||||
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 "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 matching 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.
|
||||
|
|
@ -1,763 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0 and ISC
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) Stichting NLnet, Netherlands, stichting@nlnet.nl.
|
||||
* Copyright (C) Vadim Goncharov, Russia, vadim_nuclight@mail.ru.
|
||||
*
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This provides the externally loadable wildcard DLZ module.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dlz_dbi.h>
|
||||
#include <dlz_list.h>
|
||||
#include <dlz_minimal.h>
|
||||
|
||||
/* 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;
|
||||
|
||||
cd->zone = UNCONST(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 /* if DLZ_DLOPEN_VERSION < 3 */
|
||||
isc_result_t
|
||||
dlz_findzonedb(void *dbdata, const char *name, dns_clientinfomethods_t *methods,
|
||||
dns_clientinfo_t *clientinfo)
|
||||
#endif /* if DLZ_DLOPEN_VERSION < 3 */
|
||||
{
|
||||
config_data_t *cd = (config_data_t *)dbdata;
|
||||
const char *p;
|
||||
|
||||
#if DLZ_DLOPEN_VERSION >= 3
|
||||
UNUSED(methods);
|
||||
UNUSED(clientinfo);
|
||||
#endif /* if DLZ_DLOPEN_VERSION >= 3 */
|
||||
|
||||
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 /* if DLZ_DLOPEN_VERSION == 1 */
|
||||
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 /* if DLZ_DLOPEN_VERSION == 1 */
|
||||
{
|
||||
isc_result_t result;
|
||||
config_data_t *cd = (config_data_t *)dbdata;
|
||||
char *querystring = NULL;
|
||||
const char *p;
|
||||
char *namebuf;
|
||||
nrr_t *nrec;
|
||||
|
||||
#if DLZ_DLOPEN_VERSION >= 2
|
||||
UNUSED(methods);
|
||||
UNUSED(clientinfo);
|
||||
#endif /* if DLZ_DLOPEN_VERSION >= 2 */
|
||||
|
||||
p = shortest_match(cd->zone_pattern, zone);
|
||||
if (p == NULL) {
|
||||
return ISC_R_NOTFOUND;
|
||||
}
|
||||
|
||||
cd->record = UNCONST(name);
|
||||
cd->zone = UNCONST(p);
|
||||
|
||||
if ((p != zone) && (strcmp(name, "@") == 0 || strcmp(name, zone) == 0))
|
||||
{
|
||||
size_t len = p - zone;
|
||||
namebuf = malloc(len);
|
||||
if (namebuf == NULL) {
|
||||
return ISC_R_NOMEMORY;
|
||||
}
|
||||
strncpy(namebuf, zone, len - 1);
|
||||
namebuf[len - 1] = '\0';
|
||||
cd->record = namebuf;
|
||||
} else if (p == zone) {
|
||||
cd->record = (char *)"@";
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
p = shortest_match(cd->zone_pattern, zone);
|
||||
if (p == NULL) {
|
||||
return ISC_R_NOTFOUND;
|
||||
}
|
||||
|
||||
cd->zone = UNCONST(p);
|
||||
|
||||
/* 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) {
|
||||
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;
|
||||
unsigned int i;
|
||||
int 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]);
|
||||
cd->axfr_pattern = strdup(argv[2]);
|
||||
if (cd->zone_pattern == NULL || cd->axfr_pattern == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
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;
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
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";
|
||||
};
|
||||
|
|
@ -16,9 +16,10 @@ Dynamically Loadable Zones (DLZ)
|
|||
|
||||
Dynamically Loadable Zones (DLZ) are an extension to BIND 9 that allows
|
||||
zone data to be retrieved directly from an external database. There is
|
||||
no required format or schema. DLZ modules exist for several different
|
||||
database backends, including MySQL and LDAP, and can be
|
||||
written for any other.
|
||||
no required format or schema.
|
||||
|
||||
There are number of contributed DLZ modules for several different database
|
||||
backends, including MySQL and LDAP, but they are not actively maintained.
|
||||
|
||||
The DLZ module provides data to :iscman:`named` in text
|
||||
format, which is then converted to DNS wire format by :iscman:`named`. This
|
||||
|
|
@ -86,11 +87,11 @@ backend storage of redirection rules:
|
|||
Sample DLZ Module
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
For guidance in the implementation of DLZ modules, the directory
|
||||
``contrib/dlz/example`` contains a basic dynamically linkable DLZ
|
||||
module - i.e., one which can be loaded at runtime by the "dlopen" DLZ
|
||||
driver. The example sets up a single zone, whose name is passed to the
|
||||
module as an argument in the :any:`dlz` statement:
|
||||
For guidance in the implementation of DLZ modules, the ``example``
|
||||
directory in the [gitlab.isc.org/isc-projects/dlz-modules](https://gitlab.isc.org/isc-projects/dlz-modules/-/tree/main/example?ref_type=heads)
|
||||
contains a basic dynamically linkable DLZ module - i.e., one which can be loaded
|
||||
at runtime by the "dlopen" DLZ driver. The example sets up a single zone, whose
|
||||
name is passed to the module as an argument in the :any:`dlz` statement:
|
||||
|
||||
::
|
||||
|
||||
|
|
@ -124,6 +125,8 @@ records for a particular name depending on the network from which the
|
|||
query arrived.
|
||||
|
||||
Documentation of the DLZ module API can be found in
|
||||
``contrib/dlz/example/README``. This directory also contains the header
|
||||
file ``dlz_minimal.h``, which defines the API and should be included by
|
||||
any dynamically linkable DLZ module.
|
||||
[README](https://gitlab.isc.org/isc-projects/dlz-modules/-/raw/main/example/README). This
|
||||
repository also contains the header file
|
||||
[dlz_minimal.h](https://gitlab.isc.org/isc-projects/dlz-modules/-/raw/main/modules/include/dlz_minimal.h),
|
||||
which defines the API and should be included by any dynamically linkable DLZ
|
||||
module.
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ ISC_LANG_BEGINDECLS
|
|||
#define DNS_CLIENTINFO_VERSION 3
|
||||
/*
|
||||
* Any updates to this structure should also be applied in
|
||||
* contrib/modules/dlz/dlz_minmal.h.
|
||||
* https://gitlab.isc.org/isc-projects/dlz-modules/-/raw/main/modules/include/dlz_minimal.h
|
||||
*/
|
||||
typedef struct dns_clientinfo {
|
||||
uint16_t version;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
/*
|
||||
* Any updates to this structure should also be applied in
|
||||
* contrib/modules/dlz/dlz_minmal.h.
|
||||
* https://gitlab.isc.org/isc-projects/dlz-modules/-/raw/main/modules/include/dlz_minimal.h
|
||||
*/
|
||||
struct dns_ecs {
|
||||
isc_netaddr_t addr;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ ISC_LANG_BEGINDECLS
|
|||
|
||||
/*
|
||||
* Any updates to this structure should also be applied in
|
||||
* contrib/modules/dlz/dlz_minmal.h.
|
||||
* https://gitlab.isc.org/isc-projects/dlz-modules/-/raw/main/modules/include/dlz_minimal.h
|
||||
*/
|
||||
struct isc_netaddr {
|
||||
unsigned int family;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
/*
|
||||
* Any updates to this structure should also be applied in
|
||||
* contrib/modules/dlz/dlz_minmal.h.
|
||||
* https://gitlab.isc.org/isc-projects/dlz-modules/-/raw/main/modules/include/dlz_minimal.h
|
||||
*/
|
||||
struct isc_sockaddr {
|
||||
union {
|
||||
|
|
|
|||
Loading…
Reference in a new issue