mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-29 21:47:59 +00:00
3176. [doc] Corrected example code and added a README to the
sample external DLZ module in contrib/dlz/example. [RT #26215]
This commit is contained in:
parent
ada40193c8
commit
9336f01769
4
CHANGES
4
CHANGES
@ -1,3 +1,7 @@
|
||||
3176. [doc] Corrected example code and added a README to the
|
||||
sample external DLZ module in contrib/dlz/example.
|
||||
[RT #26215]
|
||||
|
||||
3175. [bug] Fix how DNSSEC positive wildcard responses from a
|
||||
NSEC3 signed zone are validated. Stop sending a
|
||||
unnecessary NSEC3 record when generating such
|
||||
|
180
contrib/dlz/example/README
Normal file
180
contrib/dlz/example/README
Normal file
@ -0,0 +1,180 @@
|
||||
OVERVIEW:
|
||||
|
||||
DLZ (Dynamically Loadable Zones) is an extention 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.
|
||||
|
||||
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
|
||||
master configuration, with slaves retrieving zone updates via AXFR.
|
||||
(Note, however, that DLZ has no built-in support for DNS notify; slaves
|
||||
are not automatically informed of changes to the zones in the database.)
|
||||
|
||||
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.)
|
||||
|
||||
IMPLEMENTATION NOTES:
|
||||
|
||||
The minimal set of type definitions, prototypes, and macros needed
|
||||
for implementing a DLZ driver is in 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 writable_zone(dns_view_t *view, const char *zone_name);
|
||||
|
||||
Allows the DLZ module to inform named that a given zone can recieve
|
||||
DDNS updates.
|
||||
|
||||
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 dlz_minimal.h and
|
||||
is currently 2. '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);
|
||||
|
||||
Required for all external DLZ modules. This indicates whether the
|
||||
DLZ module can answer for a given zone. Returns ISC_R_SUCCESS if
|
||||
so, otherwise ISC_R_NOTFOUND.
|
||||
|
||||
- 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, isc_boolean_t 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.
|
||||
|
||||
- isc_boolean_t 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,42 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Andrew Tridgell
|
||||
* Copyright (C) 2011 Internet Systems Consortium, Inc. ("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.
|
||||
* 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 THE AUTHOR
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
/* $Id: dlz_example.c,v 1.3 2011/10/20 22:01:48 each Exp $ */
|
||||
|
||||
/*
|
||||
this provides a very simple example of an external loadable DLZ
|
||||
driver, with update support
|
||||
* This provides a very simple example of an external loadable DLZ
|
||||
* driver, with update support.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "dlz_minimal.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define STRTOK_R(a, b, c) strtok_s(a, b, c)
|
||||
#elif defined(_REENTRANT)
|
||||
#define STRTOK_R(a, b, c) strtok_r(a, b, c)
|
||||
#else
|
||||
#define STRTOK_R(a, b, c) strtok(a, b)
|
||||
#endif
|
||||
|
||||
/* for this simple example, use fixed sized strings */
|
||||
/* For this simple example, use fixed sized strings */
|
||||
struct record {
|
||||
char name[100];
|
||||
char type[10];
|
||||
char data[200];
|
||||
uint32_t ttl;
|
||||
dns_ttl_t ttl;
|
||||
};
|
||||
|
||||
#define MAX_RECORDS 100
|
||||
@ -44,50 +50,49 @@ struct record {
|
||||
struct dlz_example_data {
|
||||
char *zone_name;
|
||||
|
||||
/* an example driver doesn't need good memory management :-) */
|
||||
/* 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;
|
||||
isc_boolean_t transaction_started;
|
||||
|
||||
/* helper functions from the dlz_dlopen driver */
|
||||
void (*log)(int level, const char *fmt, ...);
|
||||
isc_result_t (*putrr)(dns_sdlzlookup_t *handle, const char *type,
|
||||
dns_ttl_t ttl, const char *data);
|
||||
isc_result_t (*putnamedrr)(dns_sdlzlookup_t *handle, const char *name,
|
||||
const char *type, dns_ttl_t ttl, const char *data);
|
||||
isc_result_t (*writeable_zone)(dns_view_t *view, const char *zone_name);
|
||||
/* 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)
|
||||
{
|
||||
static isc_boolean_t
|
||||
single_valued(const char *type) {
|
||||
const char *single[] = { "soa", "cname", NULL };
|
||||
int i;
|
||||
for (i=0; single[i]; i++) {
|
||||
|
||||
for (i = 0; single[i]; i++) {
|
||||
if (strcasecmp(single[i], type) == 0) {
|
||||
return true;
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
add a record to a list
|
||||
* 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,
|
||||
uint32_t ttl, const char *data)
|
||||
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);
|
||||
isc_boolean_t single = single_valued(type);
|
||||
int first_empty = -1;
|
||||
|
||||
for (i=0; i<MAX_RECORDS; i++) {
|
||||
if (first_empty == -1 && strlen(list[i].name) == 0) {
|
||||
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)
|
||||
if (strcasecmp(list[i].name, name) != 0)
|
||||
continue;
|
||||
if (strcasecmp(list[i].type, type) != 0)
|
||||
continue;
|
||||
@ -100,24 +105,28 @@ static isc_result_t add_name(struct dlz_example_data *state,
|
||||
}
|
||||
if (i == MAX_RECORDS) {
|
||||
state->log(ISC_LOG_ERROR, "dlz_example: out of record space");
|
||||
return ISC_R_FAILURE;
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
strcpy(list[i].name, name);
|
||||
strcpy(list[i].type, type);
|
||||
strcpy(list[i].data, data);
|
||||
list[i].ttl = ttl;
|
||||
return ISC_R_SUCCESS;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
delete a record from a list
|
||||
* 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,
|
||||
uint32_t ttl, const char *data)
|
||||
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;
|
||||
for (i=0; i<MAX_RECORDS; 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 &&
|
||||
@ -126,59 +135,86 @@ static isc_result_t del_name(struct dlz_example_data *state,
|
||||
}
|
||||
}
|
||||
if (i == MAX_RECORDS) {
|
||||
return ISC_R_NOTFOUND;
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
memset(&list[i], 0, sizeof(struct record));
|
||||
return ISC_R_SUCCESS;
|
||||
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
|
||||
* Return the version of the API
|
||||
*/
|
||||
int dlz_version(unsigned int *flags)
|
||||
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)
|
||||
{
|
||||
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 = 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;
|
||||
}
|
||||
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 initialise the driver
|
||||
* Called to initialize the driver
|
||||
*/
|
||||
isc_result_t dlz_create(const char *dlzname, unsigned int argc, char *argv[],
|
||||
void **dbdata, ...)
|
||||
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];
|
||||
|
||||
state = calloc(1, sizeof(struct dlz_example_data));
|
||||
if (state == NULL) {
|
||||
return ISC_R_NOMEMORY;
|
||||
}
|
||||
UNUSED(dlzname);
|
||||
|
||||
/* fill in the helper functions */
|
||||
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*));
|
||||
@ -186,8 +222,9 @@ isc_result_t dlz_create(const char *dlzname, unsigned int argc, char *argv[],
|
||||
va_end(ap);
|
||||
|
||||
if (argc < 2) {
|
||||
state->log(ISC_LOG_ERROR, "dlz_example: please specify a zone name");
|
||||
return ISC_R_FAILURE;
|
||||
state->log(ISC_LOG_ERROR,
|
||||
"dlz_example: please specify a zone name");
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
state->zone_name = strdup(argv[1]);
|
||||
@ -195,169 +232,218 @@ isc_result_t dlz_create(const char *dlzname, unsigned int argc, char *argv[],
|
||||
sprintf(soa_data, "%s hostmaster.%s 123 900 600 86400 3600",
|
||||
state->zone_name, state->zone_name);
|
||||
|
||||
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");
|
||||
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");
|
||||
|
||||
state->log(ISC_LOG_INFO, "dlz_example: started for zone %s", state->zone_name);
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: started for zone %s",
|
||||
state->zone_name);
|
||||
|
||||
*dbdata = state;
|
||||
return ISC_R_SUCCESS;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
shutdown the backend
|
||||
* Shut down the backend
|
||||
*/
|
||||
void dlz_destroy(void *dbdata)
|
||||
{
|
||||
void
|
||||
dlz_destroy(void *dbdata) {
|
||||
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
||||
state->log(ISC_LOG_INFO, "dlz_example: shutting down zone %s", state->zone_name);
|
||||
|
||||
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
|
||||
* See if we handle a given zone
|
||||
*/
|
||||
isc_result_t dlz_findzonedb(void *dbdata, const char *name)
|
||||
{
|
||||
isc_result_t
|
||||
dlz_findzonedb(void *dbdata, const char *name) {
|
||||
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
||||
if (strcasecmp(state->zone_name, name) == 0) {
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
return ISC_R_NOTFOUND;
|
||||
|
||||
if (strcasecmp(state->zone_name, name) == 0)
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
lookup one record
|
||||
* Look up one record in the sample database.
|
||||
*
|
||||
* If the queryname is "source-addr", we add a TXT record containing
|
||||
* the address of the client; this demonstrates the use of 'methods'
|
||||
* and 'clientinfo'.
|
||||
*/
|
||||
isc_result_t dlz_lookup(const char *zone, const char *name,
|
||||
void *dbdata, dns_sdlzlookup_t *lookup)
|
||||
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;
|
||||
int i;
|
||||
bool found = false;
|
||||
isc_boolean_t found = ISC_FALSE;
|
||||
isc_sockaddr_t *src;
|
||||
char full_name[100];
|
||||
|
||||
if (strcmp(name, "@") == 0) {
|
||||
int i;
|
||||
|
||||
UNUSED(zone);
|
||||
|
||||
if (strcmp(name, "@") == 0)
|
||||
strcpy(full_name, state->zone_name);
|
||||
} else {
|
||||
else
|
||||
sprintf(full_name, "%s.%s", name, state->zone_name);
|
||||
|
||||
if (strcmp(name, "source-addr") == 0) {
|
||||
char buf[100];
|
||||
strcpy(buf, "unknown");
|
||||
if (methods != NULL &&
|
||||
methods->version - methods->age >=
|
||||
DNS_CLIENTINFOMETHODS_VERSION)
|
||||
{
|
||||
methods->sourceip(clientinfo, &src);
|
||||
fmt_address(src, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
fprintf(stderr, "connection from: %s\n", buf);
|
||||
|
||||
found = ISC_TRUE;
|
||||
result = state->putrr(lookup, "TXT", 0, buf);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
}
|
||||
for (i=0; i<MAX_RECORDS; i++) {
|
||||
|
||||
for (i = 0; i < MAX_RECORDS; i++) {
|
||||
if (strcasecmp(state->current[i].name, full_name) == 0) {
|
||||
isc_result_t result;
|
||||
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;
|
||||
}
|
||||
found = ISC_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;
|
||||
|
||||
if (!found)
|
||||
return (ISC_R_NOTFOUND);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
see if a zone transfer is allowed
|
||||
* See if a zone transfer is allowed
|
||||
*/
|
||||
isc_result_t dlz_allowzonexfr(void *dbdata, const char *name, const char *client)
|
||||
{
|
||||
/* just say yes for all our zones */
|
||||
return dlz_findzonedb(dbdata, name);
|
||||
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));
|
||||
}
|
||||
|
||||
/*
|
||||
perform a zone transfer
|
||||
* Perform a zone transfer
|
||||
*/
|
||||
isc_result_t dlz_allnodes(const char *zone, void *dbdata,
|
||||
dns_sdlzallnodes_t *allnodes)
|
||||
{
|
||||
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;
|
||||
|
||||
for (i=0; i<MAX_RECORDS; i++) {
|
||||
UNUSED(zone);
|
||||
|
||||
for (i = 0; i < MAX_RECORDS; i++) {
|
||||
isc_result_t result;
|
||||
if (strlen(state->current[i].name) == 0) {
|
||||
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;
|
||||
}
|
||||
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;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
start a transaction
|
||||
* Start a transaction
|
||||
*/
|
||||
isc_result_t dlz_newversion(const char *zone, void *dbdata, void **versionp)
|
||||
{
|
||||
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) {
|
||||
state->log(ISC_LOG_INFO, "dlz_example: transaction already started for zone %s", zone);
|
||||
return ISC_R_FAILURE;
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: transaction already "
|
||||
"started for zone %s", zone);
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
state->transaction_started = true;
|
||||
|
||||
state->transaction_started = ISC_TRUE;
|
||||
*versionp = (void *) &state->transaction_started;
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
end a transaction
|
||||
* End a transaction
|
||||
*/
|
||||
void dlz_closeversion(const char *zone, isc_boolean_t commit, void *dbdata, void **versionp)
|
||||
void
|
||||
dlz_closeversion(const char *zone, isc_boolean_t commit,
|
||||
void *dbdata, void **versionp)
|
||||
{
|
||||
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
||||
|
||||
if (!state->transaction_started) {
|
||||
state->log(ISC_LOG_INFO, "dlz_example: transaction not started for zone %s", zone);
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: transaction not started for zone %s",
|
||||
zone);
|
||||
*versionp = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
state->transaction_started = false;
|
||||
state->transaction_started = ISC_FALSE;
|
||||
|
||||
*versionp = NULL;
|
||||
|
||||
if (commit) {
|
||||
int i;
|
||||
state->log(ISC_LOG_INFO, "dlz_example: committing transaction on zone %s", zone);
|
||||
for (i=0; i<MAX_RECORDS; i++) {
|
||||
if (strlen(state->adds[i].name) > 0) {
|
||||
add_name(state, &state->current[0],
|
||||
state->adds[i].name,
|
||||
state->adds[i].type,
|
||||
state->adds[i].ttl,
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: committing transaction on zone %s",
|
||||
zone);
|
||||
for (i = 0; i < MAX_RECORDS; i++) {
|
||||
if (strlen(state->adds[i].name) > 0U) {
|
||||
add_name(state, &state->current[0],
|
||||
state->adds[i].name,
|
||||
state->adds[i].type,
|
||||
state->adds[i].ttl,
|
||||
state->adds[i].data);
|
||||
}
|
||||
}
|
||||
for (i=0; i<MAX_RECORDS; i++) {
|
||||
if (strlen(state->deletes[i].name) > 0) {
|
||||
del_name(state, &state->current[0],
|
||||
state->deletes[i].name,
|
||||
state->deletes[i].type,
|
||||
state->deletes[i].ttl,
|
||||
for (i = 0; i < MAX_RECORDS; i++) {
|
||||
if (strlen(state->deletes[i].name) > 0U) {
|
||||
del_name(state, &state->current[0],
|
||||
state->deletes[i].name,
|
||||
state->deletes[i].type,
|
||||
state->deletes[i].ttl,
|
||||
state->deletes[i].data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
state->log(ISC_LOG_INFO, "dlz_example: cancelling transaction on zone %s", zone);
|
||||
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));
|
||||
@ -365,118 +451,155 @@ void dlz_closeversion(const char *zone, isc_boolean_t commit, void *dbdata, void
|
||||
|
||||
|
||||
/*
|
||||
configure a writeable zone
|
||||
* Configure a writeable zone
|
||||
*/
|
||||
isc_result_t dlz_configure(dns_view_t *view, void *dbdata)
|
||||
{
|
||||
isc_result_t
|
||||
dlz_configure(dns_view_t *view, void *dbdata) {
|
||||
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
|
||||
isc_result_t result;
|
||||
|
||||
|
||||
state->log(ISC_LOG_INFO, "dlz_example: starting configure");
|
||||
if (state->writeable_zone == NULL) {
|
||||
state->log(ISC_LOG_INFO, "dlz_example: no writeable_zone method available");
|
||||
return ISC_R_FAILURE;
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: no writeable_zone method available");
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
result = state->writeable_zone(view, state->zone_name);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
state->log(ISC_LOG_ERROR, "dlz_example: failed to configure zone %s", state->zone_name);
|
||||
return result;
|
||||
state->log(ISC_LOG_ERROR,
|
||||
"dlz_example: failed to configure zone %s",
|
||||
state->zone_name);
|
||||
return (result);
|
||||
}
|
||||
|
||||
state->log(ISC_LOG_INFO, "dlz_example: configured writeable zone %s", state->zone_name);
|
||||
return ISC_R_SUCCESS;
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: configured writeable zone %s",
|
||||
state->zone_name);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
authorize a zone update
|
||||
* Authorize a zone update
|
||||
*/
|
||||
isc_boolean_t 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)
|
||||
isc_boolean_t
|
||||
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) {
|
||||
state->log(ISC_LOG_INFO, "dlz_example: denying update of name=%s by %s",
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: denying update of name=%s by %s",
|
||||
name, signer);
|
||||
return false;
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
state->log(ISC_LOG_INFO, "dlz_example: allowing update of name=%s by %s",
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: allowing update of name=%s by %s",
|
||||
name, signer);
|
||||
return true;
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
|
||||
static isc_result_t modrdataset(struct dlz_example_data *state, const char *name, const char *rdatastr,
|
||||
struct record *list)
|
||||
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;
|
||||
char *buf = strdup(rdatastr);
|
||||
isc_result_t result;
|
||||
#if defined(WIN32) || defined(_REENTRANT)
|
||||
char *saveptr = NULL;
|
||||
#endif
|
||||
|
||||
/*
|
||||
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
|
||||
* 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) return ISC_R_FAILURE;
|
||||
ttlstr = strtok_r(NULL, "\t", &saveptr);
|
||||
if (ttlstr == NULL) return ISC_R_FAILURE;
|
||||
dclass = strtok_r(NULL, "\t", &saveptr);
|
||||
if (dclass == NULL) return ISC_R_FAILURE;
|
||||
type = strtok_r(NULL, "\t", &saveptr);
|
||||
if (type == NULL) return ISC_R_FAILURE;
|
||||
data = strtok_r(NULL, "\t", &saveptr);
|
||||
if (data == NULL) return ISC_R_FAILURE;
|
||||
full_name = STRTOK_R(buf, "\t", &saveptr);
|
||||
if (full_name == NULL)
|
||||
return (ISC_R_FAILURE);
|
||||
|
||||
result = add_name(state, list, name, type, strtoul(ttlstr, NULL, 10), data);
|
||||
ttlstr = STRTOK_R(NULL, "\t", &saveptr);
|
||||
if (ttlstr == NULL)
|
||||
return (ISC_R_FAILURE);
|
||||
|
||||
dclass = STRTOK_R(NULL, "\t", &saveptr);
|
||||
if (dclass == NULL)
|
||||
return (ISC_R_FAILURE);
|
||||
|
||||
type = STRTOK_R(NULL, "\t", &saveptr);
|
||||
if (type == NULL)
|
||||
return (ISC_R_FAILURE);
|
||||
|
||||
data = STRTOK_R(NULL, "\t", &saveptr);
|
||||
if (data == NULL)
|
||||
return (ISC_R_FAILURE);
|
||||
|
||||
result = add_name(state, list, name, type,
|
||||
strtoul(ttlstr, NULL, 10), data);
|
||||
free(buf);
|
||||
return result;
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, void *dbdata, void *version)
|
||||
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 (version != (void *) &state->transaction_started)
|
||||
return (ISC_R_FAILURE);
|
||||
|
||||
state->log(ISC_LOG_INFO, "dlz_example: adding rdataset %s '%s'", name, rdatastr);
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: adding rdataset %s '%s'",
|
||||
name, rdatastr);
|
||||
|
||||
return modrdataset(state, name, rdatastr, &state->adds[0]);
|
||||
return (modrdataset(state, name, rdatastr, &state->adds[0]));
|
||||
}
|
||||
|
||||
isc_result_t dlz_subrdataset(const char *name, const char *rdatastr, void *dbdata, void *version)
|
||||
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 (version != (void *) &state->transaction_started)
|
||||
return (ISC_R_FAILURE);
|
||||
|
||||
state->log(ISC_LOG_INFO, "dlz_example: subtracting rdataset %s '%s'", name, rdatastr);
|
||||
|
||||
return modrdataset(state, name, rdatastr, &state->deletes[0]);
|
||||
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)
|
||||
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 (version != (void *) &state->transaction_started)
|
||||
return (ISC_R_FAILURE);
|
||||
|
||||
state->log(ISC_LOG_INFO, "dlz_example: deleting rdataset %s of type %s", name, type);
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
state->log(ISC_LOG_INFO,
|
||||
"dlz_example: deleting rdataset %s of type %s",
|
||||
name, type);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Andrew Tridgell
|
||||
* Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the
|
||||
@ -17,13 +17,23 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef ISC_PLATFORM_HAVESYSUNH
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
typedef unsigned int isc_result_t;
|
||||
typedef bool isc_boolean_t;
|
||||
typedef int isc_boolean_t;
|
||||
typedef uint32_t dns_ttl_t;
|
||||
|
||||
#define DLZ_DLOPEN_VERSION 2
|
||||
@ -37,6 +47,10 @@ typedef uint32_t dns_ttl_t;
|
||||
#define ISC_R_NOTFOUND 23
|
||||
#define ISC_R_FAILURE 25
|
||||
|
||||
/* boolean values */
|
||||
#define ISC_TRUE 1
|
||||
#define ISC_FALSE 0
|
||||
|
||||
/* log levels */
|
||||
#define ISC_LOG_INFO (-1)
|
||||
#define ISC_LOG_NOTICE (-2)
|
||||
@ -44,20 +58,80 @@ typedef uint32_t dns_ttl_t;
|
||||
#define ISC_LOG_ERROR (-4)
|
||||
#define ISC_LOG_CRITICAL (-5)
|
||||
|
||||
/* some opaque structures */
|
||||
/* other useful definitions */
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
/* opaque structures */
|
||||
typedef void *dns_sdlzlookup_t;
|
||||
typedef void *dns_sdlzallnodes_t;
|
||||
typedef void *dns_view_t;
|
||||
typedef void *dns_dlzclientcallback_t;
|
||||
|
||||
/*
|
||||
* prototypes for the functions you can include in your driver
|
||||
* 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;
|
||||
#ifdef ISC_PLATFORM_HAVESYSUNH
|
||||
struct sockaddr_un sunix;
|
||||
#endif
|
||||
} type;
|
||||
unsigned int length;
|
||||
void * link;
|
||||
} isc_sockaddr_t;
|
||||
|
||||
#define DNS_CLIENTINFO_VERSION 1
|
||||
typedef struct dns_clientinfo {
|
||||
uint16_t version;
|
||||
void *data;
|
||||
} dns_clientinfo_t;
|
||||
|
||||
typedef isc_result_t (*dns_clientinfo_sourceip_t)(dns_clientinfo_t *client,
|
||||
isc_sockaddr_t **addrp);
|
||||
|
||||
#define DNS_CLIENTINFOMETHODS_VERSION 1
|
||||
#define DNS_CLIENTINFOMETHODS_AGE 0
|
||||
|
||||
typedef struct dns_clientinfomethods {
|
||||
uint16_t version;
|
||||
uint16_t age;
|
||||
dns_clientinfo_sourceip_t sourceip;
|
||||
} dns_clientinfomethods_t;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
typedef isc_result_t dns_dlz_writeablezone_t(dns_view_t *view,
|
||||
const char *zone_name);
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
* 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);
|
||||
@ -87,7 +161,9 @@ dlz_findzonedb(void *dbdata, const char *name);
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_lookup(const char *zone, const char *name, void *dbdata,
|
||||
dns_sdlzlookup_t *lookup);
|
||||
dns_sdlzlookup_t *lookup,
|
||||
dns_clientinfomethods_t *methods,
|
||||
dns_clientinfo_t *clientinfo);
|
||||
|
||||
/*
|
||||
* dlz_allowzonexfr() is optional, and should be supplied if you want to
|
||||
@ -126,13 +202,6 @@ dlz_closeversion(const char *zone, isc_boolean_t commit, void *dbdata,
|
||||
isc_result_t
|
||||
dlz_configure(dns_view_t *view, void *dbdata);
|
||||
|
||||
/*
|
||||
* dlz_setclientcallback() is optional, but must be supplied if you want
|
||||
* to retrieve information about the client before sending a reply.
|
||||
*/
|
||||
isc_result_t
|
||||
dlz_setclientcallback(dns_dlzclientcallback_t callback);
|
||||
|
||||
/*
|
||||
* dlz_ssumatch() is optional, but must be supplied if you want to support
|
||||
* dynamic updates
|
||||
|
50
contrib/dlz/example/named.conf
Normal file
50
contrib/dlz/example/named.conf
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: named.conf,v 1.2 2011/10/20 22:01:48 each Exp $ */
|
||||
|
||||
/*
|
||||
* 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 retreives 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;
|
||||
};
|
||||
|
||||
dlz "example" {
|
||||
database "dlopen ./dlz_example.so example.nil";
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user