2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 01:59:26 +00:00

[master] pass client info to DLZ findzone method

3434.   [bug]           Pass client info to the DLZ findzone() entry
                        point in addition to lookup().  This makes it
                        possible for a database to answer differently
                        whether it's authoritative for a name depending
                        on the address of the client.  [RT #31775]
This commit is contained in:
Evan Hunt 2012-12-06 12:59:36 -08:00
parent 177be355d4
commit abff0f462a
25 changed files with 487 additions and 273 deletions

View File

@ -1,3 +1,9 @@
3434. [bug] Pass client info to the DLZ findzone() entry
point in addition to lookup(). This makes it
possible for a database to answer differently
whether it's authoritative for a name depending
on the address of the client. [RT #31775]
3433. [bug] dlz_findzone() did not correctly handle
ISC_R_NOMORE. [RT #31172]

View File

@ -1066,8 +1066,14 @@ query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
if (zonelabels < namelabels &&
!ISC_LIST_EMPTY(client->view->dlz_searched))
{
tresult = dns_dlzfindzone(client->view, name,
zonelabels, &tdbp);
dns_clientinfomethods_t cm;
dns_clientinfo_t ci;
dns_clientinfomethods_init(&cm, ns_client_sourceip);
dns_clientinfo_init(&ci, client);
tresult = dns_view_searchdlz(client->view, name,
zonelabels, &cm, &ci, &tdbp);
/* If we successful, we found a better match. */
if (tresult == ISC_R_SUCCESS) {
/*

View File

@ -161,7 +161,9 @@ dlopen_dlz_authority(const char *zone, void *driverarg, void *dbdata,
}
static isc_result_t
dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name)
dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name,
dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo)
{
dlopen_data_t *cd = (dlopen_data_t *) dbdata;
isc_result_t result;
@ -169,7 +171,7 @@ dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name)
UNUSED(driverarg);
MAYBE_LOCK(cd);
result = cd->dlz_findzonedb(cd->dbdata, name);
result = cd->dlz_findzonedb(cd->dbdata, name, methods, clientinfo);
MAYBE_UNLOCK(cd);
return (result);
}
@ -289,6 +291,7 @@ dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[],
dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE);
if (cd->dlz_create == NULL ||
cd->dlz_version == NULL ||
cd->dlz_lookup == NULL ||
cd->dlz_findzonedb == NULL)
{

View File

@ -277,6 +277,7 @@ dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[],
dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE);
if (cd->dlz_create == NULL ||
cd->dlz_version == NULL ||
cd->dlz_lookup == NULL ||
cd->dlz_findzonedb == NULL)
{

View File

@ -318,11 +318,26 @@ dlz_destroy(void *dbdata) {
* See if we handle a given zone
*/
isc_result_t
dlz_findzonedb(void *dbdata, const char *name) {
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];
strcpy(addrbuf, "unknown");
if (methods != NULL &&
methods->sourceip != NULL &&
methods->version - methods->age >= DNS_CLIENTINFOMETHODS_VERSION)
{
methods->sourceip(clientinfo, &src);
fmt_address(src, addrbuf, sizeof(addrbuf));
}
fprintf(stderr, "findzonedb: connection from: %s\n", addrbuf);
state->log(ISC_LOG_INFO,
"dlz_example: dlz_findzonedb called with name '%s'"
"dlz_example: dlz_findzonedb called with name '%s' "
"in zone DB '%s'", name, state->zone_name);
/*
@ -335,6 +350,14 @@ dlz_findzonedb(void *dbdata, const char *name) {
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);
@ -342,7 +365,10 @@ dlz_findzonedb(void *dbdata, const char *name) {
}
/*
* Look up 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, to test the use of 'methods' and 'clientinfo'
*/
isc_result_t
dlz_lookup(const char *zone, const char *name, void *dbdata,
@ -371,6 +397,7 @@ dlz_lookup(const char *zone, const char *name, void *dbdata,
char buf[100];
strcpy(buf, "unknown");
if (methods != NULL &&
methods->sourceip != NULL &&
methods->version - methods->age >=
DNS_CLIENTINFOMETHODS_VERSION)
{
@ -378,7 +405,7 @@ dlz_lookup(const char *zone, const char *name, void *dbdata,
fmt_address(src, buf, sizeof(buf));
}
fprintf(stderr, "connection from: %s\n", buf);
fprintf(stderr, "lookup: connection from: %s\n", buf);
found = ISC_TRUE;
result = state->putrr(lookup, "TXT", 0, buf);
@ -412,7 +439,7 @@ dlz_allowzonexfr(void *dbdata, const char *name, const char *client) {
UNUSED(client);
/* Just say yes for all our zones */
return (dlz_findzonedb(dbdata, name));
return (dlz_findzonedb(dbdata, name, NULL, NULL));
}
/*

View File

@ -112,11 +112,28 @@ ret=0
echo "I:testing correct behavior with findzone returning ISC_R_NOMORE"
$DIG $DIGOPTS +noall a test.example.com > /dev/null 2>&1 || ret=1
# we should only find one logged lookup per searched DLZ database
lines=`grep "dlz_findzonedb.*example\.com.*example.nil" ns1/named.run | wc -l`
lines=`grep "dlz_findzonedb.*test\.example\.com.*example.nil" ns1/named.run | wc -l`
[ $lines -eq 1 ] || ret=1
lines=`grep "dlz_findzonedb.*example\.com.*alternate.nil" ns1/named.run | wc -l`
lines=`grep "dlz_findzonedb.*test\.example\.com.*alternate.nil" ns1/named.run | wc -l`
[ $lines -eq 1 ] || ret=1
[ "$ret" -eq 0 ] || echo "I:failed"
status=`expr $status + $ret`
ret=0
echo "I:testing findzone can return different results per client"
$DIG $DIGOPTS -b 10.53.0.1 +noall a test.example.net > /dev/null 2>&1 || ret=1
# we should only find one logged lookup per searched DLZ database
lines=`grep "dlz_findzonedb.*example\.net.*example.nil" ns1/named.run | wc -l`
[ $lines -eq 1 ] || ret=1
lines=`grep "dlz_findzonedb.*example\.net.*alternate.nil" ns1/named.run | wc -l`
[ $lines -eq 1 ] || ret=1
$DIG $DIGOPTS -b 10.53.0.2 +noall a test.example.net > /dev/null 2>&1 || ret=1
# we should find several logged lookups this time
lines=`grep "dlz_findzonedb.*example\.net.*example.nil" ns1/named.run | wc -l`
[ $lines -gt 2 ] || ret=1
lines=`grep "dlz_findzonedb.*example\.net.*alternate.nil" ns1/named.run | wc -l`
[ $lines -gt 2 ] || ret=1
[ "$ret" -eq 0 ] || echo "I:failed"
status=`expr $status + $ret`
exit $status

View File

@ -114,7 +114,8 @@ typedef struct parsed_data {
/* forward reference */
static isc_result_t
bdb_findzone(void *driverarg, void *dbdata, const char *name);
bdb_findzone(void *driverarg, void *dbdata, const char *name,
dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo);
/*%
* Parses the DBT from the Berkeley DB into a parsed_data record
@ -226,7 +227,7 @@ bdb_allowzonexfr(void *driverarg, void *dbdata, const char *name,
DBT key, data;
/* check to see if we are authoritative for the zone first. */
result = bdb_findzone(driverarg, dbdata, name);
result = bdb_findzone(driverarg, dbdata, name, NULL, NULL);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOTFOUND);
@ -393,7 +394,8 @@ bdb_cleanup(bdb_instance_t *db) {
}
static isc_result_t
bdb_findzone(void *driverarg, void *dbdata, const char *name)
bdb_findzone(void *driverarg, void *dbdata, const char *name,
dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
{
isc_result_t result;
@ -402,6 +404,8 @@ bdb_findzone(void *driverarg, void *dbdata, const char *name)
DBT key, data;
UNUSED(driverarg);
UNUSED(methods);
UNUSED(clientinfo);
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));

View File

@ -112,7 +112,8 @@ typedef struct bdbhpt_parsed_data {
/* forward reference */
static isc_result_t
bdbhpt_findzone(void *driverarg, void *dbdata, const char *name);
bdbhpt_findzone(void *driverarg, void *dbdata, const char *name,
dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo);
/*%
* Reverses a string in place.
@ -252,7 +253,7 @@ bdbhpt_allowzonexfr(void *driverarg, void *dbdata, const char *name,
DBT key, data;
/* check to see if we are authoritative for the zone first. */
result = bdbhpt_findzone(driverarg, dbdata, name);
result = bdbhpt_findzone(driverarg, dbdata, name, NULL, NULL);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOTFOUND);
@ -483,7 +484,8 @@ bdbhpt_cleanup(bdbhpt_instance_t *db) {
}
static isc_result_t
bdbhpt_findzone(void *driverarg, void *dbdata, const char *name)
bdbhpt_findzone(void *driverarg, void *dbdata, const char *name,
dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
{
isc_result_t result;
@ -491,6 +493,8 @@ bdbhpt_findzone(void *driverarg, void *dbdata, const char *name)
DBT key, data;
UNUSED(driverarg);
UNUSED(methods);
UNUSED(clientinfo);
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));

View File

@ -749,7 +749,8 @@ fs_allnodes(const char *zone, void *driverarg, void *dbdata,
}
static isc_result_t
fs_findzone(void *driverarg, void *dbdata, const char *name)
fs_findzone(void *driverarg, void *dbdata, const char *name,
dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
{
isc_result_t result;
@ -758,6 +759,8 @@ fs_findzone(void *driverarg, void *dbdata, const char *name)
path = NULL;
UNUSED(driverarg);
UNUSED(methods);
UNUSED(clientinfo);
if (create_path(name, NULL, NULL, (config_data_t *) dbdata,
&path) != ISC_R_SUCCESS) {

View File

@ -117,7 +117,9 @@ typedef struct {
/* forward references */
static isc_result_t
dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name);
dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name,
dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo);
static void
dlz_ldap_destroy(void *driverarg, void *dbdata);
@ -878,7 +880,7 @@ dlz_ldap_allowzonexfr(void *driverarg, void *dbdata, const char *name,
UNUSED(driverarg);
/* check to see if we are authoritative for the zone first */
result = dlz_ldap_findzone(driverarg, dbdata, name);
result = dlz_ldap_findzone(driverarg, dbdata, name, NULL, NULL);
if (result != ISC_R_SUCCESS) {
return (result);
}
@ -905,8 +907,13 @@ dlz_ldap_authority(const char *zone, void *driverarg, void *dbdata,
}
static isc_result_t
dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name) {
dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name,
dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo)
{
UNUSED(driverarg);
UNUSED(methods);
UNUSED(clientinfo);
return (ldap_get_results(name, NULL, NULL, FINDZONE, dbdata, NULL));
}

View File

@ -503,13 +503,16 @@ mysql_process_rs(dns_sdlzlookup_t *lookup, MYSQL_RES *rs)
/*% determine if the zone is supported by (in) the database */
static isc_result_t
mysql_findzone(void *driverarg, void *dbdata, const char *name)
mysql_findzone(void *driverarg, void *dbdata, const char *name,
dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
{
isc_result_t result;
MYSQL_RES *rs = NULL;
my_ulonglong rows;
UNUSED(driverarg);
UNUSED(methods);
UNUSED(clientinfo);
/* run the query and get the result set from the database. */
result = mysql_get_resultset(name, NULL, NULL, FINDZONE, dbdata, &rs);
@ -550,7 +553,7 @@ mysql_allowzonexfr(void *driverarg, void *dbdata, const char *name,
UNUSED(driverarg);
/* first check if the zone is supported by the database. */
result = mysql_findzone(driverarg, dbdata, name);
result = mysql_findzone(driverarg, dbdata, name, NULL, NULL);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOTFOUND);

View File

@ -963,13 +963,16 @@ odbc_process_rs(dns_sdlzlookup_t *lookup, dbinstance_t *dbi)
/*% determine if the zone is supported by (in) the database */
static isc_result_t
odbc_findzone(void *driverarg, void *dbdata, const char *name)
odbc_findzone(void *driverarg, void *dbdata, const char *name,
dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
{
isc_result_t result;
dbinstance_t *dbi = NULL;
UNUSED(driverarg);
UNUSED(methods);
UNUSED(clientinfo);
/* run the query and get the result set from the database. */
/* if result != ISC_R_SUCCESS cursor and mutex already cleaned up. */
@ -1007,7 +1010,7 @@ odbc_allowzonexfr(void *driverarg, void *dbdata, const char *name,
UNUSED(driverarg);
/* first check if the zone is supported by the database. */
result = odbc_findzone(driverarg, dbdata, name);
result = odbc_findzone(driverarg, dbdata, name, NULL, NULL);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOTFOUND);

View File

@ -770,12 +770,17 @@ postgres_process_rs(dns_sdlzlookup_t *lookup, PGresult *rs)
/*% determine if the zone is supported by (in) the database */
static isc_result_t
postgres_findzone(void *driverarg, void *dbdata, const char *name)
postgres_findzone(void *driverarg, void *dbdata, const char *name,
dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo)
{
isc_result_t result;
PGresult *rs = NULL;
unsigned int rows;
UNUSED(driverarg);
UNUSED(methods);
UNUSED(clientinfo);
/* run the query and get the result set from the database. */
result = postgres_get_resultset(name, NULL, NULL,
@ -814,7 +819,7 @@ postgres_allowzonexfr(void *driverarg, void *dbdata, const char *name,
UNUSED(driverarg);
/* first check if the zone is supported by the database. */
result = postgres_findzone(driverarg, dbdata, name);
result = postgres_findzone(driverarg, dbdata, name, NULL, NULL);
if (result != ISC_R_SUCCESS)
return (ISC_R_NOTFOUND);

View File

@ -147,12 +147,16 @@ stub_dlz_authority(const char *zone, void *driverarg, void *dbdata,
}
static isc_result_t
stub_dlz_findzonedb(void *driverarg, void *dbdata, const char *name)
stub_dlz_findzonedb(void *driverarg, void *dbdata, const char *name,
dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo)
{
config_data_t *cd;
UNUSED(driverarg);
UNUSED(methods);
UNUSED(clientinfo);
cd = (config_data_t *) dbdata;

View File

@ -37,6 +37,13 @@
#define STRTOK_R(a, b, c) strtok(a, b)
#endif
#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];
@ -104,13 +111,22 @@ add_name(struct dlz_example_data *state, struct record *list,
i = first_empty;
}
if (i == MAX_RECORDS) {
state->log(ISC_LOG_ERROR, "dlz_example: out of record space");
if (state->log != NULL)
state->log(ISC_LOG_ERROR,
"dlz_example: out of record space");
return (ISC_R_FAILURE);
}
strcpy(list[i].name, name);
strcpy(list[i].type, type);
strcpy(list[i].data, data);
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));
strncpy(list[i].type, type, sizeof(list[i].type));
strncpy(list[i].data, data, sizeof(list[i].data));
list[i].ttl = ttl;
return (ISC_R_SUCCESS);
}
@ -195,7 +211,6 @@ b9_add_helper(struct dlz_example_data *state,
state->writeable_zone = (dns_dlz_writeablezone_t *)ptr;
}
/*
* Called to initialize the driver
*/
@ -208,6 +223,8 @@ dlz_create(const char *dlzname, unsigned int argc, char *argv[],
va_list ap;
char soa_data[200];
const char *extra;
isc_result_t result;
int n;
UNUSED(dlzname);
@ -218,24 +235,36 @@ dlz_create(const char *dlzname, unsigned int argc, char *argv[],
/* 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*));
b9_add_helper(state, helper_name, va_arg(ap, void *));
}
va_end(ap);
if (argc < 2) {
state->log(ISC_LOG_ERROR,
"dlz_example: please specify a zone name");
if (state->log != NULL)
state->log(ISC_LOG_ERROR,
"dlz_example: please specify a zone name");
dlz_destroy(state);
return (ISC_R_FAILURE);
}
state->zone_name = strdup(argv[1]);
if (state->zone_name == NULL) {
free(state);
return (ISC_R_NOMEMORY);
}
if (strcmp(state->zone_name, ".") == 0)
extra = ".root";
else
extra = ".";
sprintf(soa_data, "%s hostmaster%s%s 123 900 600 86400 3600",
state->zone_name, extra, state->zone_name);
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)n >= sizeof(soa_data))
CHECK(ISC_R_NOSPACE);
add_name(state, &state->current[0], state->zone_name,
"soa", 3600, soa_data);
@ -244,12 +273,17 @@ dlz_create(const char *dlzname, unsigned int argc, char *argv[],
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);
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);
}
/*
@ -259,9 +293,10 @@ 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);
if (state->log != NULL)
state->log(ISC_LOG_INFO,
"dlz_example: shutting down zone %s",
state->zone_name);
free(state->zone_name);
free(state);
}
@ -271,8 +306,45 @@ dlz_destroy(void *dbdata) {
* See if we handle a given zone
*/
isc_result_t
dlz_findzonedb(void *dbdata, const char *name) {
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];
strcpy(addrbuf, "unknown");
if (methods != NULL &&
methods->sourceip != NULL &&
methods->version - methods->age >= DNS_CLIENTINFOMETHODS_VERSION)
{
methods->sourceip(clientinfo, &src);
fmt_address(src, addrbuf, sizeof(addrbuf));
}
fprintf(stderr, "findzonedb: connection from: %s\n", 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);
@ -296,20 +368,25 @@ dlz_lookup(const char *zone, const char *name, void *dbdata,
struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
isc_boolean_t found = ISC_FALSE;
isc_sockaddr_t *src;
char full_name[100];
char full_name[256];
int i;
UNUSED(zone);
if (strcmp(name, "@") == 0)
strcpy(full_name, state->zone_name);
else
sprintf(full_name, "%s.%s", name, state->zone_name);
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 (strcmp(name, "source-addr") == 0) {
char buf[100];
strcpy(buf, "unknown");
if (methods != NULL &&
methods->sourceip != NULL &&
methods->version - methods->age >=
DNS_CLIENTINFOMETHODS_VERSION)
{
@ -317,7 +394,7 @@ dlz_lookup(const char *zone, const char *name, void *dbdata,
fmt_address(src, buf, sizeof(buf));
}
fprintf(stderr, "connection from: %s\n", buf);
fprintf(stderr, "lookup: connection from: %s\n", buf);
found = ISC_TRUE;
result = state->putrr(lookup, "TXT", 0, buf);
@ -351,7 +428,7 @@ dlz_allowzonexfr(void *dbdata, const char *name, const char *client) {
UNUSED(client);
/* Just say yes for all our zones */
return (dlz_findzonedb(dbdata, name));
return (dlz_findzonedb(dbdata, name, NULL, NULL));
}
/*
@ -364,6 +441,9 @@ dlz_allnodes(const char *zone, void *dbdata, dns_sdlzallnodes_t *allnodes) {
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) {
@ -389,9 +469,10 @@ 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);
if (state->log != NULL)
state->log(ISC_LOG_INFO,
"dlz_example: transaction already "
"started for zone %s", zone);
return (ISC_R_FAILURE);
}
@ -411,9 +492,9 @@ dlz_closeversion(const char *zone, isc_boolean_t commit,
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);
if (state->log != NULL)
state->log(ISC_LOG_INFO, "dlz_example: transaction not "
"started for zone %s", zone);
*versionp = NULL;
return;
}
@ -424,31 +505,31 @@ dlz_closeversion(const char *zone, isc_boolean_t commit,
if (commit) {
int i;
state->log(ISC_LOG_INFO,
"dlz_example: committing transaction on zone %s",
zone);
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->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);
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->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);
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 {
state->log(ISC_LOG_INFO,
"dlz_example: cancelling transaction on zone %s",
zone);
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));
@ -459,30 +540,31 @@ dlz_closeversion(const char *zone, isc_boolean_t commit,
* Configure a writeable zone
*/
isc_result_t
dlz_configure(dns_view_t *view, void *dbdata) {
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");
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");
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, view->dlzdatabase,
state->zone_name);
result = state->writeable_zone(view, dlzdb, state->zone_name);
if (result != ISC_R_SUCCESS) {
state->log(ISC_LOG_ERROR,
"dlz_example: failed to configure zone %s",
state->zone_name);
if (state->log != NULL)
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);
if (state->log != NULL)
state->log(ISC_LOG_INFO, "dlz_example: configured writeable "
"zone %s", state->zone_name);
return (ISC_R_SUCCESS);
}
@ -503,14 +585,14 @@ dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr,
UNUSED(keydata);
if (strncmp(name, "deny.", 5) == 0) {
state->log(ISC_LOG_INFO,
"dlz_example: denying update of name=%s by %s",
name, signer);
if (state->log != NULL)
state->log(ISC_LOG_INFO, "dlz_example: denying update "
"of name=%s by %s", name, signer);
return (ISC_FALSE);
}
state->log(ISC_LOG_INFO,
"dlz_example: allowing update of name=%s by %s",
name, signer);
if (state->log != NULL)
state->log(ISC_LOG_INFO, "dlz_example: allowing update of "
"name=%s by %s", name, signer);
return (ISC_TRUE);
}
@ -519,13 +601,16 @@ 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);
char *full_name, *dclass, *type, *data, *ttlstr, *buf;
isc_result_t result;
#if defined(WIN32) || defined(_REENTRANT)
char *saveptr = NULL;
#endif
buf = strdup(rdatastr);
if (buf == NULL)
return (ISC_R_FAILURE);
/*
* The format is:
* FULLNAME\tTTL\tDCLASS\tTYPE\tDATA
@ -536,28 +621,32 @@ modrdataset(struct dlz_example_data *state, const char *name,
full_name = STRTOK_R(buf, "\t", &saveptr);
if (full_name == NULL)
return (ISC_R_FAILURE);
goto error;
ttlstr = STRTOK_R(NULL, "\t", &saveptr);
if (ttlstr == NULL)
return (ISC_R_FAILURE);
goto error;
dclass = STRTOK_R(NULL, "\t", &saveptr);
if (dclass == NULL)
return (ISC_R_FAILURE);
goto error;
type = STRTOK_R(NULL, "\t", &saveptr);
if (type == NULL)
return (ISC_R_FAILURE);
goto error;
data = STRTOK_R(NULL, "\t", &saveptr);
if (data == NULL)
return (ISC_R_FAILURE);
goto error;
result = add_name(state, list, name, type,
strtoul(ttlstr, NULL, 10), data);
free(buf);
return (result);
error:
free(buf);
return (ISC_R_FAILURE);
}
@ -570,9 +659,9 @@ dlz_addrdataset(const char *name, const char *rdatastr,
if (version != (void *) &state->transaction_started)
return (ISC_R_FAILURE);
state->log(ISC_LOG_INFO,
"dlz_example: adding rdataset %s '%s'",
name, rdatastr);
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]));
}
@ -586,9 +675,9 @@ dlz_subrdataset(const char *name, const char *rdatastr,
if (version != (void *) &state->transaction_started)
return (ISC_R_FAILURE);
state->log(ISC_LOG_INFO,
"dlz_example: subtracting rdataset %s '%s'",
name, rdatastr);
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]));
}
@ -603,9 +692,9 @@ dlz_delrdataset(const char *name, const char *type,
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);
if (state->log != NULL)
state->log(ISC_LOG_INFO, "dlz_example: deleting rdataset %s "
"of type %s", name, type);
return (ISC_R_SUCCESS);
}

View File

@ -36,7 +36,7 @@ typedef unsigned int isc_result_t;
typedef int isc_boolean_t;
typedef uint32_t dns_ttl_t;
#define DLZ_DLOPEN_VERSION 2
#define DLZ_DLOPEN_VERSION 3
/* return this in flags to dlz_version() if thread safe */
#define DNS_SDLZFLAG_THREADSAFE 0x00000001U
@ -45,8 +45,10 @@ typedef uint32_t dns_ttl_t;
#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
/* boolean values */
@ -67,6 +69,7 @@ typedef uint32_t dns_ttl_t;
typedef void *dns_sdlzlookup_t;
typedef void *dns_sdlzallnodes_t;
typedef void *dns_view_t;
typedef void *dns_dlzdb_t;
/*
* Method and type definitions needed for retrieval of client info
@ -120,9 +123,9 @@ typedef isc_result_t dns_sdlz_putnamedrr_t(dns_sdlzallnodes_t *allnodes,
const char *data);
typedef isc_result_t dns_dlz_writeablezone_t(dns_view_t *view,
dns_dlzdb_t *dlzdb,
const char *zone_name);
/*
* prototypes for the functions you can include in your module
*/
@ -156,7 +159,9 @@ dlz_destroy(void *dbdata);
* dlz_findzonedb is required for all DLZ external drivers
*/
isc_result_t
dlz_findzonedb(void *dbdata, const char *name);
dlz_findzonedb(void *dbdata, const char *name,
dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo);
/*
* dlz_lookup is required for all DLZ external drivers
@ -202,7 +207,7 @@ dlz_closeversion(const char *zone, isc_boolean_t commit, void *dbdata,
* dynamic updates
*/
isc_result_t
dlz_configure(dns_view_t *view, void *dbdata);
dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, void *dbdata);
/*
* dlz_ssumatch() is optional, but must be supplied if you want to support

View File

@ -273,92 +273,6 @@ dns_dlzdestroy(dns_dlzdb_t **dbp) {
*dbp = NULL;
}
isc_result_t
dns_dlzfindzone(dns_view_t *view, dns_name_t *name,
unsigned int minlabels, dns_db_t **dbp)
{
dns_fixedname_t fname;
dns_name_t *zonename;
unsigned int namelabels;
unsigned int i;
isc_result_t result;
dns_dlzfindzone_t findzone;
dns_dlzdb_t *dlzdb;
dns_db_t *db, *best = NULL;
/*
* Performs checks to make sure data is as we expect it to be.
*/
REQUIRE(view != NULL);
REQUIRE(name != NULL);
REQUIRE(dbp != NULL && *dbp == NULL);
/* setup a "fixed" dns name */
dns_fixedname_init(&fname);
zonename = dns_fixedname_name(&fname);
/* count the number of labels in the name */
namelabels = dns_name_countlabels(name);
for (dlzdb = ISC_LIST_HEAD(view->dlz_searched);
dlzdb != NULL;
dlzdb = ISC_LIST_NEXT(dlzdb, link))
{
REQUIRE(DNS_DLZ_VALID(dlzdb));
/*
* loop through starting with the longest domain name and
* trying shorter names portions of the name until we find a
* match, have an error, or are below the 'minlabels'
* threshold. minlabels is 0, if neither the standard
* database nor any previous DLZ database had a zone name
* match. Otherwise minlabels is the number of labels
* in that name. We need to beat that for a "better"
* match for this DLZ database to be authoritative.
*/
for (i = namelabels; i > minlabels && i > 1; i--) {
if (i == namelabels) {
result = dns_name_copy(name, zonename, NULL);
if (result != ISC_R_SUCCESS)
return (result);
} else
dns_name_split(name, i, NULL, zonename);
/* ask SDLZ driver if the zone is supported */
db = NULL;
findzone = dlzdb->implementation->methods->findzone;
result = (*findzone)(dlzdb->implementation->driverarg,
dlzdb->dbdata, dlzdb->mctx,
view->rdclass, zonename, &db);
if (result != ISC_R_NOTFOUND) {
if (best != NULL)
dns_db_detach(&best);
if (result == ISC_R_SUCCESS) {
INSIST(db != NULL);
dns_db_attach(db, &best);
dns_db_detach(&db);
minlabels = i;
} else {
if (db != NULL)
dns_db_detach(&db);
break;
}
} else if (db != NULL)
dns_db_detach(&db);
}
}
if (best != NULL) {
dns_db_attach(best, dbp);
dns_db_detach(&best);
return (ISC_R_SUCCESS);
}
return (ISC_R_NOTFOUND);
}
/*%
* Registers a DLZ driver. This basically just adds the dlz
* driver to the list of available drivers in the dlz_implementations list.

View File

@ -84,6 +84,7 @@
***** Imports
*****/
#include <dns/clientinfo.h>
#include <dns/name.h>
#include <dns/types.h>
#include <dns/view.h>
@ -140,10 +141,11 @@ typedef void
typedef isc_result_t
(*dns_dlzfindzone_t)(void *driverarg, void *dbdata, isc_mem_t *mctx,
dns_rdataclass_t rdclass, dns_name_t *name,
dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo,
dns_db_t **dbp);
/*%<
* Method prototype. Drivers implementing the DLZ interface MUST
* supply a find zone method. This method is called when the DNS
* server is performing a query. The find zone method will be called
@ -265,15 +267,6 @@ dns_dlzdestroy(dns_dlzdb_t **dbp);
* methods, this function will call it.
*/
isc_result_t
dns_dlzfindzone(dns_view_t *view, dns_name_t *name,
unsigned int minlabels, dns_db_t **dbp);
/*%<
* This method is called when the DNS server is performing a query.
* It will call the DLZ driver's find zone method.
*/
isc_result_t
dns_dlzregister(const char *drivername, const dns_dlzmethods_t *methods,
void *driverarg, isc_mem_t *mctx,

View File

@ -30,142 +30,144 @@ ISC_LANG_BEGINDECLS
* for the entry points of an external DLZ module for bind9.
*/
#define DLZ_DLOPEN_VERSION 2
#define DLZ_DLOPEN_VERSION 3
/*
* dlz_dlopen_version() is required for all DLZ external drivers. It
* should return DLZ_DLOPEN_VERSION
*/
typedef int dlz_dlopen_version_t (unsigned int *flags);
typedef int dlz_dlopen_version_t(unsigned int *flags);
/*
* dlz_dlopen_create() is required for all DLZ external drivers.
*/
typedef isc_result_t dlz_dlopen_create_t (const char *dlzname,
unsigned int argc,
char *argv[],
void **dbdata,
...);
typedef isc_result_t dlz_dlopen_create_t(const char *dlzname,
unsigned int argc,
char *argv[],
void **dbdata,
...);
/*
* dlz_dlopen_destroy() is optional, and will be called when the
* driver is unloaded if supplied
*/
typedef void dlz_dlopen_destroy_t (void *dbdata);
typedef void dlz_dlopen_destroy_t(void *dbdata);
/*
* dlz_dlopen_findzonedb() is required for all DLZ external drivers
*/
typedef isc_result_t dlz_dlopen_findzonedb_t (void *dbdata,
const char *name);
typedef isc_result_t dlz_dlopen_findzonedb_t(void *dbdata,
const char *name,
dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo);
/*
* dlz_dlopen_lookup() is required for all DLZ external drivers
*/
typedef isc_result_t dlz_dlopen_lookup_t (const char *zone,
const char *name,
void *dbdata,
dns_sdlzlookup_t *lookup,
dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo);
typedef isc_result_t dlz_dlopen_lookup_t(const char *zone,
const char *name,
void *dbdata,
dns_sdlzlookup_t *lookup,
dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo);
/*
* dlz_dlopen_authority is optional() if dlz_dlopen_lookup()
* supplies authority information for the dns record
*/
typedef isc_result_t dlz_dlopen_authority_t (const char *zone,
void *dbdata,
dns_sdlzlookup_t *lookup);
typedef isc_result_t dlz_dlopen_authority_t(const char *zone,
void *dbdata,
dns_sdlzlookup_t *lookup);
/*
* dlz_dlopen_allowzonexfr() is optional, and should be supplied if
* you want to support zone transfers
*/
typedef isc_result_t dlz_dlopen_allowzonexfr_t (void *dbdata,
const char *name,
const char *client);
typedef isc_result_t dlz_dlopen_allowzonexfr_t(void *dbdata,
const char *name,
const char *client);
/*
* dlz_dlopen_allnodes() is optional, but must be supplied if supply a
* dlz_dlopen_allowzonexfr() function
*/
typedef isc_result_t dlz_dlopen_allnodes_t (const char *zone,
void *dbdata,
dns_sdlzallnodes_t *allnodes);
typedef isc_result_t dlz_dlopen_allnodes_t(const char *zone,
void *dbdata,
dns_sdlzallnodes_t *allnodes);
/*
* dlz_dlopen_newversion() is optional. It should be supplied if you
* want to support dynamic updates.
*/
typedef isc_result_t dlz_dlopen_newversion_t (const char *zone,
void *dbdata,
void **versionp);
typedef isc_result_t dlz_dlopen_newversion_t(const char *zone,
void *dbdata,
void **versionp);
/*
* dlz_closeversion() is optional, but must be supplied if you supply
* a dlz_newversion() function
*/
typedef void dlz_dlopen_closeversion_t (const char *zone,
isc_boolean_t commit,
void *dbdata,
void **versionp);
typedef void dlz_dlopen_closeversion_t(const char *zone,
isc_boolean_t commit,
void *dbdata,
void **versionp);
/*
* dlz_dlopen_configure() is optional, but must be supplied if you
* want to support dynamic updates
*/
typedef isc_result_t dlz_dlopen_configure_t (dns_view_t *view,
dns_dlzdb_t *dlzdb,
void *dbdata);
typedef isc_result_t dlz_dlopen_configure_t(dns_view_t *view,
dns_dlzdb_t *dlzdb,
void *dbdata);
/*
* dlz_dlopen_setclientcallback() is optional, but must be supplied if you
* want to retrieve information about the client (e.g., source address)
* before sending a replay.
*/
typedef isc_result_t dlz_dlopen_setclientcallback_t (dns_view_t *view,
void *dbdata);
typedef isc_result_t dlz_dlopen_setclientcallback_t(dns_view_t *view,
void *dbdata);
/*
* dlz_dlopen_ssumatch() is optional, but must be supplied if you want
* to support dynamic updates
*/
typedef isc_boolean_t dlz_dlopen_ssumatch_t (const char *signer,
const char *name,
const char *tcpaddr,
const char *type,
const char *key,
isc_uint32_t keydatalen,
unsigned char *keydata,
void *dbdata);
typedef isc_boolean_t dlz_dlopen_ssumatch_t(const char *signer,
const char *name,
const char *tcpaddr,
const char *type,
const char *key,
isc_uint32_t keydatalen,
unsigned char *keydata,
void *dbdata);
/*
* dlz_dlopen_addrdataset() is optional, but must be supplied if you
* want to support dynamic updates
*/
typedef isc_result_t dlz_dlopen_addrdataset_t (const char *name,
const char *rdatastr,
void *dbdata,
void *version);
typedef isc_result_t dlz_dlopen_addrdataset_t(const char *name,
const char *rdatastr,
void *dbdata,
void *version);
/*
* dlz_dlopen_subrdataset() is optional, but must be supplied if you
* want to support dynamic updates
*/
typedef isc_result_t dlz_dlopen_subrdataset_t (const char *name,
const char *rdatastr,
void *dbdata,
void *version);
typedef isc_result_t dlz_dlopen_subrdataset_t(const char *name,
const char *rdatastr,
void *dbdata,
void *version);
/*
* dlz_dlopen_delrdataset() is optional, but must be supplied if you
* want to support dynamic updates
*/
typedef isc_result_t dlz_dlopen_delrdataset_t (const char *name,
const char *type,
void *dbdata,
void *version);
typedef isc_result_t dlz_dlopen_delrdataset_t(const char *name,
const char *type,
void *dbdata,
void *version);
ISC_LANG_ENDDECLS

View File

@ -152,8 +152,9 @@ typedef void (*dns_sdlzdestroy_t)(void *driverarg, void *dbdata);
*/
typedef isc_result_t
(*dns_sdlzfindzone_t)(void *driverarg, void *dbdata, const char *name);
(*dns_sdlzfindzone_t)(void *driverarg, void *dbdata, const char *name,
dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo);
/*%<
* Method prototype. Drivers implementing the SDLZ interface MUST
* supply a find zone method. This method is called when the DNS

View File

@ -72,6 +72,7 @@
#include <isc/stdtime.h>
#include <dns/acl.h>
#include <dns/clientinfo.h>
#include <dns/fixedname.h>
#include <dns/rdatastruct.h>
#include <dns/rpz.h>
@ -1136,6 +1137,29 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
void
dns_view_restorekeyring(dns_view_t *view);
isc_result_t
dns_view_searchdlz(dns_view_t *view, dns_name_t *name,
unsigned int minlabels,
dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo,
dns_db_t **dbp);
/*%<
* Search through the DLZ database(s) in view->dlz_searched to find
* one that can answer a query for 'name', using the DLZ driver's
* findzone method. If successful, '*dbp' is set to point to the
* DLZ database.
*
* Returns:
* \li ISC_R_SUCCESS
* \li ISC_R_NOTFOUND
*
* Requires:
* \li 'view' is valid.
* \li 'name' is not NULL.
* \li 'dbp' is not NULL and *dbp is NULL.
*/
ISC_LANG_ENDDECLS
#endif /* DNS_VIEW_H */

View File

@ -1628,7 +1628,10 @@ dns_sdlzdestroy(void *driverdata, void **dbdata) {
static isc_result_t
dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
dns_rdataclass_t rdclass, dns_name_t *name, dns_db_t **dbp)
dns_rdataclass_t rdclass, dns_name_t *name,
dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo,
dns_db_t **dbp)
{
isc_buffer_t b;
char namestr[DNS_NAME_MAXTEXT + 1];
@ -1656,7 +1659,8 @@ dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
/* Call SDLZ driver's find zone method */
MAYBE_LOCK(imp);
result = imp->methods->findzone(imp->driverarg, dbdata, namestr);
result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
methods, clientinfo);
MAYBE_UNLOCK(imp);
/*

View File

@ -1868,3 +1868,91 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
UNUSED(cfg_destroy);
#endif
}
isc_result_t
dns_view_searchdlz(dns_view_t *view, dns_name_t *name, unsigned int minlabels,
dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo,
dns_db_t **dbp)
{
dns_fixedname_t fname;
dns_name_t *zonename;
unsigned int namelabels;
unsigned int i;
isc_result_t result;
dns_dlzfindzone_t findzone;
dns_dlzdb_t *dlzdb;
dns_db_t *db, *best = NULL;
/*
* Performs checks to make sure data is as we expect it to be.
*/
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(name != NULL);
REQUIRE(dbp != NULL && *dbp == NULL);
/* setup a "fixed" dns name */
dns_fixedname_init(&fname);
zonename = dns_fixedname_name(&fname);
/* count the number of labels in the name */
namelabels = dns_name_countlabels(name);
for (dlzdb = ISC_LIST_HEAD(view->dlz_searched);
dlzdb != NULL;
dlzdb = ISC_LIST_NEXT(dlzdb, link))
{
REQUIRE(DNS_DLZ_VALID(dlzdb));
/*
* loop through starting with the longest domain name and
* trying shorter names portions of the name until we find a
* match, have an error, or are below the 'minlabels'
* threshold. minlabels is 0, if neither the standard
* database nor any previous DLZ database had a zone name
* match. Otherwise minlabels is the number of labels
* in that name. We need to beat that for a "better"
* match for this DLZ database to be authoritative.
*/
for (i = namelabels; i > minlabels && i > 1; i--) {
if (i == namelabels) {
result = dns_name_copy(name, zonename, NULL);
if (result != ISC_R_SUCCESS)
return (result);
} else
dns_name_split(name, i, NULL, zonename);
/* ask SDLZ driver if the zone is supported */
db = NULL;
findzone = dlzdb->implementation->methods->findzone;
result = (*findzone)(dlzdb->implementation->driverarg,
dlzdb->dbdata, dlzdb->mctx,
view->rdclass, zonename,
methods, clientinfo, &db);
if (result != ISC_R_NOTFOUND) {
if (best != NULL)
dns_db_detach(&best);
if (result == ISC_R_SUCCESS) {
INSIST(db != NULL);
dns_db_attach(db, &best);
dns_db_detach(&db);
minlabels = i;
} else {
if (db != NULL)
dns_db_detach(&db);
break;
}
} else if (db != NULL)
dns_db_detach(&db);
}
}
if (best != NULL) {
dns_db_attach(best, dbp);
dns_db_detach(&best);
return (ISC_R_SUCCESS);
}
return (ISC_R_NOTFOUND);
}

View File

@ -203,7 +203,6 @@ dns_dlzallowzonexfr
dns_dlzconfigure
dns_dlzcreate
dns_dlzdestroy
dns_dlzfindzone
dns_dlzregister
dns_dlzstrtoargv
dns_dlzunregister
@ -774,6 +773,7 @@ dns_view_issecuredomain
dns_view_load
dns_view_loadnew
dns_view_restorekeyring
dns_view_searchdlz
dns_view_setcache
dns_view_setcache2
dns_view_setdstport

View File

@ -1670,7 +1670,8 @@ zone_load(dns_zone_t *zone, unsigned int flags) {
findzone = dlzdb->implementation->methods->findzone;
result = (*findzone)(dlzdb->implementation->driverarg,
dlzdb->dbdata, dlzdb->mctx,
zone->view->rdclass, &zone->origin, &db);
zone->view->rdclass, &zone->origin,
NULL, NULL, &db);
if (result != ISC_R_NOTFOUND) {
if (zone->db != NULL)
zone_detachdb(zone);