2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 05:28:00 +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 3433. [bug] dlz_findzone() did not correctly handle
ISC_R_NOMORE. [RT #31172] 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 && if (zonelabels < namelabels &&
!ISC_LIST_EMPTY(client->view->dlz_searched)) !ISC_LIST_EMPTY(client->view->dlz_searched))
{ {
tresult = dns_dlzfindzone(client->view, name, dns_clientinfomethods_t cm;
zonelabels, &tdbp); 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 we successful, we found a better match. */
if (tresult == ISC_R_SUCCESS) { 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 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; dlopen_data_t *cd = (dlopen_data_t *) dbdata;
isc_result_t result; isc_result_t result;
@ -169,7 +171,7 @@ dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name)
UNUSED(driverarg); UNUSED(driverarg);
MAYBE_LOCK(cd); MAYBE_LOCK(cd);
result = cd->dlz_findzonedb(cd->dbdata, name); result = cd->dlz_findzonedb(cd->dbdata, name, methods, clientinfo);
MAYBE_UNLOCK(cd); MAYBE_UNLOCK(cd);
return (result); 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); dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE);
if (cd->dlz_create == NULL || if (cd->dlz_create == NULL ||
cd->dlz_version == NULL ||
cd->dlz_lookup == NULL || cd->dlz_lookup == NULL ||
cd->dlz_findzonedb == 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); dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE);
if (cd->dlz_create == NULL || if (cd->dlz_create == NULL ||
cd->dlz_version == NULL ||
cd->dlz_lookup == NULL || cd->dlz_lookup == NULL ||
cd->dlz_findzonedb == NULL) cd->dlz_findzonedb == NULL)
{ {

View File

@ -318,11 +318,26 @@ dlz_destroy(void *dbdata) {
* See if we handle a given zone * See if we handle a given zone
*/ */
isc_result_t 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; 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, 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); "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) if (strcasecmp(name, "test.example.com") == 0)
return (ISC_R_NOMORE); 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) if (strcasecmp(state->zone_name, name) == 0)
return (ISC_R_SUCCESS); 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 isc_result_t
dlz_lookup(const char *zone, const char *name, void *dbdata, 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]; char buf[100];
strcpy(buf, "unknown"); strcpy(buf, "unknown");
if (methods != NULL && if (methods != NULL &&
methods->sourceip != NULL &&
methods->version - methods->age >= methods->version - methods->age >=
DNS_CLIENTINFOMETHODS_VERSION) DNS_CLIENTINFOMETHODS_VERSION)
{ {
@ -378,7 +405,7 @@ dlz_lookup(const char *zone, const char *name, void *dbdata,
fmt_address(src, buf, sizeof(buf)); fmt_address(src, buf, sizeof(buf));
} }
fprintf(stderr, "connection from: %s\n", buf); fprintf(stderr, "lookup: connection from: %s\n", buf);
found = ISC_TRUE; found = ISC_TRUE;
result = state->putrr(lookup, "TXT", 0, buf); result = state->putrr(lookup, "TXT", 0, buf);
@ -412,7 +439,7 @@ dlz_allowzonexfr(void *dbdata, const char *name, const char *client) {
UNUSED(client); UNUSED(client);
/* Just say yes for all our zones */ /* 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" echo "I:testing correct behavior with findzone returning ISC_R_NOMORE"
$DIG $DIGOPTS +noall a test.example.com > /dev/null 2>&1 || ret=1 $DIG $DIGOPTS +noall a test.example.com > /dev/null 2>&1 || ret=1
# we should only find one logged lookup per searched DLZ database # 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 -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 [ $lines -eq 1 ] || ret=1
[ "$ret" -eq 0 ] || echo "I:failed" [ "$ret" -eq 0 ] || echo "I:failed"
status=`expr $status + $ret` 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 exit $status

View File

@ -114,7 +114,8 @@ typedef struct parsed_data {
/* forward reference */ /* forward reference */
static isc_result_t 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 * 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; DBT key, data;
/* check to see if we are authoritative for the zone first. */ /* 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) if (result != ISC_R_SUCCESS)
return (ISC_R_NOTFOUND); return (ISC_R_NOTFOUND);
@ -393,7 +394,8 @@ bdb_cleanup(bdb_instance_t *db) {
} }
static isc_result_t 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; isc_result_t result;
@ -402,6 +404,8 @@ bdb_findzone(void *driverarg, void *dbdata, const char *name)
DBT key, data; DBT key, data;
UNUSED(driverarg); UNUSED(driverarg);
UNUSED(methods);
UNUSED(clientinfo);
memset(&key, 0, sizeof(DBT)); memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT)); memset(&data, 0, sizeof(DBT));

View File

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

View File

@ -117,7 +117,9 @@ typedef struct {
/* forward references */ /* forward references */
static isc_result_t 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 static void
dlz_ldap_destroy(void *driverarg, void *dbdata); dlz_ldap_destroy(void *driverarg, void *dbdata);
@ -878,7 +880,7 @@ dlz_ldap_allowzonexfr(void *driverarg, void *dbdata, const char *name,
UNUSED(driverarg); UNUSED(driverarg);
/* check to see if we are authoritative for the zone first */ /* 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) { if (result != ISC_R_SUCCESS) {
return (result); return (result);
} }
@ -905,8 +907,13 @@ dlz_ldap_authority(const char *zone, void *driverarg, void *dbdata,
} }
static isc_result_t 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(driverarg);
UNUSED(methods);
UNUSED(clientinfo);
return (ldap_get_results(name, NULL, NULL, FINDZONE, dbdata, NULL)); 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 */ /*% determine if the zone is supported by (in) the database */
static isc_result_t 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; isc_result_t result;
MYSQL_RES *rs = NULL; MYSQL_RES *rs = NULL;
my_ulonglong rows; my_ulonglong rows;
UNUSED(driverarg); UNUSED(driverarg);
UNUSED(methods);
UNUSED(clientinfo);
/* run the query and get the result set from the database. */ /* run the query and get the result set from the database. */
result = mysql_get_resultset(name, NULL, NULL, FINDZONE, dbdata, &rs); 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); UNUSED(driverarg);
/* first check if the zone is supported by the database. */ /* 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) if (result != ISC_R_SUCCESS)
return (ISC_R_NOTFOUND); 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 */ /*% determine if the zone is supported by (in) the database */
static isc_result_t 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; isc_result_t result;
dbinstance_t *dbi = NULL; dbinstance_t *dbi = NULL;
UNUSED(driverarg); UNUSED(driverarg);
UNUSED(methods);
UNUSED(clientinfo);
/* run the query and get the result set from the database. */ /* run the query and get the result set from the database. */
/* if result != ISC_R_SUCCESS cursor and mutex already cleaned up. */ /* 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); UNUSED(driverarg);
/* first check if the zone is supported by the database. */ /* 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) if (result != ISC_R_SUCCESS)
return (ISC_R_NOTFOUND); 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 */ /*% determine if the zone is supported by (in) the database */
static isc_result_t 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; isc_result_t result;
PGresult *rs = NULL; PGresult *rs = NULL;
unsigned int rows; unsigned int rows;
UNUSED(driverarg); UNUSED(driverarg);
UNUSED(methods);
UNUSED(clientinfo);
/* run the query and get the result set from the database. */ /* run the query and get the result set from the database. */
result = postgres_get_resultset(name, NULL, NULL, result = postgres_get_resultset(name, NULL, NULL,
@ -814,7 +819,7 @@ postgres_allowzonexfr(void *driverarg, void *dbdata, const char *name,
UNUSED(driverarg); UNUSED(driverarg);
/* first check if the zone is supported by the database. */ /* 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) if (result != ISC_R_SUCCESS)
return (ISC_R_NOTFOUND); return (ISC_R_NOTFOUND);

View File

@ -147,12 +147,16 @@ stub_dlz_authority(const char *zone, void *driverarg, void *dbdata,
} }
static isc_result_t 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; config_data_t *cd;
UNUSED(driverarg); UNUSED(driverarg);
UNUSED(methods);
UNUSED(clientinfo);
cd = (config_data_t *) dbdata; cd = (config_data_t *) dbdata;

View File

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

View File

@ -36,7 +36,7 @@ typedef unsigned int isc_result_t;
typedef int isc_boolean_t; typedef int isc_boolean_t;
typedef uint32_t dns_ttl_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 */ /* return this in flags to dlz_version() if thread safe */
#define DNS_SDLZFLAG_THREADSAFE 0x00000001U #define DNS_SDLZFLAG_THREADSAFE 0x00000001U
@ -45,8 +45,10 @@ typedef uint32_t dns_ttl_t;
#define ISC_R_SUCCESS 0 #define ISC_R_SUCCESS 0
#define ISC_R_NOMEMORY 1 #define ISC_R_NOMEMORY 1
#define ISC_R_NOPERM 6 #define ISC_R_NOPERM 6
#define ISC_R_NOSPACE 19
#define ISC_R_NOTFOUND 23 #define ISC_R_NOTFOUND 23
#define ISC_R_FAILURE 25 #define ISC_R_FAILURE 25
#define ISC_R_NOTIMPLEMENTED 27
#define ISC_R_NOMORE 29 #define ISC_R_NOMORE 29
/* boolean values */ /* boolean values */
@ -67,6 +69,7 @@ typedef uint32_t dns_ttl_t;
typedef void *dns_sdlzlookup_t; typedef void *dns_sdlzlookup_t;
typedef void *dns_sdlzallnodes_t; typedef void *dns_sdlzallnodes_t;
typedef void *dns_view_t; typedef void *dns_view_t;
typedef void *dns_dlzdb_t;
/* /*
* Method and type definitions needed for retrieval of client info * 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); const char *data);
typedef isc_result_t dns_dlz_writeablezone_t(dns_view_t *view, typedef isc_result_t dns_dlz_writeablezone_t(dns_view_t *view,
dns_dlzdb_t *dlzdb,
const char *zone_name); const char *zone_name);
/* /*
* prototypes for the functions you can include in your module * 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 * dlz_findzonedb is required for all DLZ external drivers
*/ */
isc_result_t 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 * 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 * dynamic updates
*/ */
isc_result_t 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 * 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; *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 * Registers a DLZ driver. This basically just adds the dlz
* driver to the list of available drivers in the dlz_implementations list. * driver to the list of available drivers in the dlz_implementations list.

View File

@ -84,6 +84,7 @@
***** Imports ***** Imports
*****/ *****/
#include <dns/clientinfo.h>
#include <dns/name.h> #include <dns/name.h>
#include <dns/types.h> #include <dns/types.h>
#include <dns/view.h> #include <dns/view.h>
@ -140,10 +141,11 @@ typedef void
typedef isc_result_t typedef isc_result_t
(*dns_dlzfindzone_t)(void *driverarg, void *dbdata, isc_mem_t *mctx, (*dns_dlzfindzone_t)(void *driverarg, void *dbdata, isc_mem_t *mctx,
dns_rdataclass_t rdclass, dns_name_t *name, dns_rdataclass_t rdclass, dns_name_t *name,
dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo,
dns_db_t **dbp); dns_db_t **dbp);
/*%< /*%<
* Method prototype. Drivers implementing the DLZ interface MUST * Method prototype. Drivers implementing the DLZ interface MUST
* supply a find zone method. This method is called when the DNS * supply a find zone method. This method is called when the DNS
* server is performing a query. The find zone method will be called * 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. * 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 isc_result_t
dns_dlzregister(const char *drivername, const dns_dlzmethods_t *methods, dns_dlzregister(const char *drivername, const dns_dlzmethods_t *methods,
void *driverarg, isc_mem_t *mctx, void *driverarg, isc_mem_t *mctx,

View File

@ -30,18 +30,18 @@ ISC_LANG_BEGINDECLS
* for the entry points of an external DLZ module for bind9. * 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 * dlz_dlopen_version() is required for all DLZ external drivers. It
* should return DLZ_DLOPEN_VERSION * 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. * dlz_dlopen_create() is required for all DLZ external drivers.
*/ */
typedef isc_result_t dlz_dlopen_create_t (const char *dlzname, typedef isc_result_t dlz_dlopen_create_t(const char *dlzname,
unsigned int argc, unsigned int argc,
char *argv[], char *argv[],
void **dbdata, void **dbdata,
@ -51,18 +51,20 @@ typedef isc_result_t dlz_dlopen_create_t (const char *dlzname,
* dlz_dlopen_destroy() is optional, and will be called when the * dlz_dlopen_destroy() is optional, and will be called when the
* driver is unloaded if supplied * 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 * dlz_dlopen_findzonedb() is required for all DLZ external drivers
*/ */
typedef isc_result_t dlz_dlopen_findzonedb_t (void *dbdata, typedef isc_result_t dlz_dlopen_findzonedb_t(void *dbdata,
const char *name); const char *name,
dns_clientinfomethods_t *methods,
dns_clientinfo_t *clientinfo);
/* /*
* dlz_dlopen_lookup() is required for all DLZ external drivers * dlz_dlopen_lookup() is required for all DLZ external drivers
*/ */
typedef isc_result_t dlz_dlopen_lookup_t (const char *zone, typedef isc_result_t dlz_dlopen_lookup_t(const char *zone,
const char *name, const char *name,
void *dbdata, void *dbdata,
dns_sdlzlookup_t *lookup, dns_sdlzlookup_t *lookup,
@ -73,7 +75,7 @@ typedef isc_result_t dlz_dlopen_lookup_t (const char *zone,
* dlz_dlopen_authority is optional() if dlz_dlopen_lookup() * dlz_dlopen_authority is optional() if dlz_dlopen_lookup()
* supplies authority information for the dns record * supplies authority information for the dns record
*/ */
typedef isc_result_t dlz_dlopen_authority_t (const char *zone, typedef isc_result_t dlz_dlopen_authority_t(const char *zone,
void *dbdata, void *dbdata,
dns_sdlzlookup_t *lookup); dns_sdlzlookup_t *lookup);
@ -81,7 +83,7 @@ typedef isc_result_t dlz_dlopen_authority_t (const char *zone,
* dlz_dlopen_allowzonexfr() is optional, and should be supplied if * dlz_dlopen_allowzonexfr() is optional, and should be supplied if
* you want to support zone transfers * you want to support zone transfers
*/ */
typedef isc_result_t dlz_dlopen_allowzonexfr_t (void *dbdata, typedef isc_result_t dlz_dlopen_allowzonexfr_t(void *dbdata,
const char *name, const char *name,
const char *client); const char *client);
@ -89,7 +91,7 @@ typedef isc_result_t dlz_dlopen_allowzonexfr_t (void *dbdata,
* dlz_dlopen_allnodes() is optional, but must be supplied if supply a * dlz_dlopen_allnodes() is optional, but must be supplied if supply a
* dlz_dlopen_allowzonexfr() function * dlz_dlopen_allowzonexfr() function
*/ */
typedef isc_result_t dlz_dlopen_allnodes_t (const char *zone, typedef isc_result_t dlz_dlopen_allnodes_t(const char *zone,
void *dbdata, void *dbdata,
dns_sdlzallnodes_t *allnodes); dns_sdlzallnodes_t *allnodes);
@ -97,7 +99,7 @@ typedef isc_result_t dlz_dlopen_allnodes_t (const char *zone,
* dlz_dlopen_newversion() is optional. It should be supplied if you * dlz_dlopen_newversion() is optional. It should be supplied if you
* want to support dynamic updates. * want to support dynamic updates.
*/ */
typedef isc_result_t dlz_dlopen_newversion_t (const char *zone, typedef isc_result_t dlz_dlopen_newversion_t(const char *zone,
void *dbdata, void *dbdata,
void **versionp); void **versionp);
@ -105,7 +107,7 @@ typedef isc_result_t dlz_dlopen_newversion_t (const char *zone,
* dlz_closeversion() is optional, but must be supplied if you supply * dlz_closeversion() is optional, but must be supplied if you supply
* a dlz_newversion() function * a dlz_newversion() function
*/ */
typedef void dlz_dlopen_closeversion_t (const char *zone, typedef void dlz_dlopen_closeversion_t(const char *zone,
isc_boolean_t commit, isc_boolean_t commit,
void *dbdata, void *dbdata,
void **versionp); void **versionp);
@ -114,7 +116,7 @@ typedef void dlz_dlopen_closeversion_t (const char *zone,
* dlz_dlopen_configure() is optional, but must be supplied if you * dlz_dlopen_configure() is optional, but must be supplied if you
* want to support dynamic updates * want to support dynamic updates
*/ */
typedef isc_result_t dlz_dlopen_configure_t (dns_view_t *view, typedef isc_result_t dlz_dlopen_configure_t(dns_view_t *view,
dns_dlzdb_t *dlzdb, dns_dlzdb_t *dlzdb,
void *dbdata); void *dbdata);
@ -123,7 +125,7 @@ typedef isc_result_t dlz_dlopen_configure_t (dns_view_t *view,
* want to retrieve information about the client (e.g., source address) * want to retrieve information about the client (e.g., source address)
* before sending a replay. * before sending a replay.
*/ */
typedef isc_result_t dlz_dlopen_setclientcallback_t (dns_view_t *view, typedef isc_result_t dlz_dlopen_setclientcallback_t(dns_view_t *view,
void *dbdata); void *dbdata);
@ -131,7 +133,7 @@ typedef isc_result_t dlz_dlopen_setclientcallback_t (dns_view_t *view,
* dlz_dlopen_ssumatch() is optional, but must be supplied if you want * dlz_dlopen_ssumatch() is optional, but must be supplied if you want
* to support dynamic updates * to support dynamic updates
*/ */
typedef isc_boolean_t dlz_dlopen_ssumatch_t (const char *signer, typedef isc_boolean_t dlz_dlopen_ssumatch_t(const char *signer,
const char *name, const char *name,
const char *tcpaddr, const char *tcpaddr,
const char *type, const char *type,
@ -144,7 +146,7 @@ typedef isc_boolean_t dlz_dlopen_ssumatch_t (const char *signer,
* dlz_dlopen_addrdataset() is optional, but must be supplied if you * dlz_dlopen_addrdataset() is optional, but must be supplied if you
* want to support dynamic updates * want to support dynamic updates
*/ */
typedef isc_result_t dlz_dlopen_addrdataset_t (const char *name, typedef isc_result_t dlz_dlopen_addrdataset_t(const char *name,
const char *rdatastr, const char *rdatastr,
void *dbdata, void *dbdata,
void *version); void *version);
@ -153,7 +155,7 @@ typedef isc_result_t dlz_dlopen_addrdataset_t (const char *name,
* dlz_dlopen_subrdataset() is optional, but must be supplied if you * dlz_dlopen_subrdataset() is optional, but must be supplied if you
* want to support dynamic updates * want to support dynamic updates
*/ */
typedef isc_result_t dlz_dlopen_subrdataset_t (const char *name, typedef isc_result_t dlz_dlopen_subrdataset_t(const char *name,
const char *rdatastr, const char *rdatastr,
void *dbdata, void *dbdata,
void *version); void *version);
@ -162,7 +164,7 @@ typedef isc_result_t dlz_dlopen_subrdataset_t (const char *name,
* dlz_dlopen_delrdataset() is optional, but must be supplied if you * dlz_dlopen_delrdataset() is optional, but must be supplied if you
* want to support dynamic updates * want to support dynamic updates
*/ */
typedef isc_result_t dlz_dlopen_delrdataset_t (const char *name, typedef isc_result_t dlz_dlopen_delrdataset_t(const char *name,
const char *type, const char *type,
void *dbdata, void *dbdata,
void *version); void *version);

View File

@ -152,8 +152,9 @@ typedef void (*dns_sdlzdestroy_t)(void *driverarg, void *dbdata);
*/ */
typedef isc_result_t 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 * Method prototype. Drivers implementing the SDLZ interface MUST
* supply a find zone method. This method is called when the DNS * supply a find zone method. This method is called when the DNS

View File

@ -72,6 +72,7 @@
#include <isc/stdtime.h> #include <isc/stdtime.h>
#include <dns/acl.h> #include <dns/acl.h>
#include <dns/clientinfo.h>
#include <dns/fixedname.h> #include <dns/fixedname.h>
#include <dns/rdatastruct.h> #include <dns/rdatastruct.h>
#include <dns/rpz.h> #include <dns/rpz.h>
@ -1136,6 +1137,29 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
void void
dns_view_restorekeyring(dns_view_t *view); 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 ISC_LANG_ENDDECLS
#endif /* DNS_VIEW_H */ #endif /* DNS_VIEW_H */

View File

@ -1628,7 +1628,10 @@ dns_sdlzdestroy(void *driverdata, void **dbdata) {
static isc_result_t static isc_result_t
dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx, 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; isc_buffer_t b;
char namestr[DNS_NAME_MAXTEXT + 1]; 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 */ /* Call SDLZ driver's find zone method */
MAYBE_LOCK(imp); MAYBE_LOCK(imp);
result = imp->methods->findzone(imp->driverarg, dbdata, namestr); result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
methods, clientinfo);
MAYBE_UNLOCK(imp); 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); UNUSED(cfg_destroy);
#endif #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_dlzconfigure
dns_dlzcreate dns_dlzcreate
dns_dlzdestroy dns_dlzdestroy
dns_dlzfindzone
dns_dlzregister dns_dlzregister
dns_dlzstrtoargv dns_dlzstrtoargv
dns_dlzunregister dns_dlzunregister
@ -774,6 +773,7 @@ dns_view_issecuredomain
dns_view_load dns_view_load
dns_view_loadnew dns_view_loadnew
dns_view_restorekeyring dns_view_restorekeyring
dns_view_searchdlz
dns_view_setcache dns_view_setcache
dns_view_setcache2 dns_view_setcache2
dns_view_setdstport dns_view_setdstport

View File

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