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:
parent
177be355d4
commit
abff0f462a
6
CHANGES
6
CHANGES
@ -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]
|
||||
|
||||
|
@ -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) {
|
||||
/*
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user