]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[master] pass client info to DLZ findzone method
authorEvan Hunt <each@isc.org>
Thu, 6 Dec 2012 20:59:36 +0000 (12:59 -0800)
committerEvan Hunt <each@isc.org>
Thu, 6 Dec 2012 20:59:36 +0000 (12:59 -0800)
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]

25 files changed:
CHANGES
bin/named/query.c
bin/named/unix/dlz_dlopen_driver.c
bin/named/win32/dlz_dlopen_driver.c
bin/tests/system/dlzexternal/driver.c
bin/tests/system/dlzexternal/tests.sh
contrib/dlz/drivers/dlz_bdb_driver.c
contrib/dlz/drivers/dlz_bdbhpt_driver.c
contrib/dlz/drivers/dlz_filesystem_driver.c
contrib/dlz/drivers/dlz_ldap_driver.c
contrib/dlz/drivers/dlz_mysql_driver.c
contrib/dlz/drivers/dlz_odbc_driver.c
contrib/dlz/drivers/dlz_postgres_driver.c
contrib/dlz/drivers/dlz_stub_driver.c
contrib/dlz/example/dlz_example.c
contrib/dlz/example/dlz_minimal.h
lib/dns/dlz.c
lib/dns/include/dns/dlz.h
lib/dns/include/dns/dlz_dlopen.h
lib/dns/include/dns/sdlz.h
lib/dns/include/dns/view.h
lib/dns/sdlz.c
lib/dns/view.c
lib/dns/win32/libdns.def
lib/dns/zone.c

diff --git a/CHANGES b/CHANGES
index 0a88c20f1fd2d04c98d8fdae5b9f340a1f032748..61eb82a4d103a1568378206cc0843c11b284c01e 100644 (file)
--- a/CHANGES
+++ b/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]
 
index 41917ffb93607735fad93d343256f27780ce9aa4..d88f73a53c1d1382472810c855126cde8a6a514f 100644 (file)
@@ -1066,8 +1066,14 @@ query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
        if (zonelabels < namelabels &&
            !ISC_LIST_EMPTY(client->view->dlz_searched))
        {
-               tresult = dns_dlzfindzone(client->view, name,
-                                         zonelabels, &tdbp);
+               dns_clientinfomethods_t cm;
+               dns_clientinfo_t ci;
+
+               dns_clientinfomethods_init(&cm, ns_client_sourceip);
+               dns_clientinfo_init(&ci, client);
+
+               tresult = dns_view_searchdlz(client->view, name,
+                                            zonelabels, &cm, &ci, &tdbp);
                 /* If we successful, we found a better match. */
                if (tresult == ISC_R_SUCCESS) {
                        /*
index 9ff7649a975d150ad5b8e3a73ecdee587cbb23af..fc5ab8669f62405653790686069427d828aa8d96 100644 (file)
@@ -161,7 +161,9 @@ dlopen_dlz_authority(const char *zone, void *driverarg, void *dbdata,
 }
 
 static isc_result_t
-dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name)
+dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name,
+                     dns_clientinfomethods_t *methods,
+                     dns_clientinfo_t *clientinfo)
 {
        dlopen_data_t *cd = (dlopen_data_t *) dbdata;
        isc_result_t result;
@@ -169,7 +171,7 @@ dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name)
        UNUSED(driverarg);
 
        MAYBE_LOCK(cd);
-       result = cd->dlz_findzonedb(cd->dbdata, name);
+       result = cd->dlz_findzonedb(cd->dbdata, name, methods, clientinfo);
        MAYBE_UNLOCK(cd);
        return (result);
 }
@@ -289,6 +291,7 @@ dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[],
                dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE);
 
        if (cd->dlz_create == NULL ||
+           cd->dlz_version == NULL ||
            cd->dlz_lookup == NULL ||
            cd->dlz_findzonedb == NULL)
        {
index 0c192b4769799de4526958f4d9dd70269dab2a65..051d511f0987ac839f9dc66a77bbf42128a78102 100644 (file)
@@ -277,6 +277,7 @@ dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[],
                dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE);
 
        if (cd->dlz_create == NULL ||
+           cd->dlz_version == NULL ||
            cd->dlz_lookup == NULL ||
            cd->dlz_findzonedb == NULL)
        {
index cdda7c406e280b91f93d6b57f7b87ac8fbd9555e..ddc658903c73771f915eaf52504f3fd601f8a1da 100644 (file)
@@ -318,11 +318,26 @@ dlz_destroy(void *dbdata) {
  * See if we handle a given zone
  */
 isc_result_t
-dlz_findzonedb(void *dbdata, const char *name) {
+dlz_findzonedb(void *dbdata, const char *name,
+          dns_clientinfomethods_t *methods,
+          dns_clientinfo_t *clientinfo)
+{
        struct dlz_example_data *state = (struct dlz_example_data *)dbdata;
+       isc_sockaddr_t *src;
+       char addrbuf[100];
+
+       strcpy(addrbuf, "unknown");
+       if (methods != NULL &&
+           methods->sourceip != NULL &&
+           methods->version - methods->age >= DNS_CLIENTINFOMETHODS_VERSION)
+       {
+               methods->sourceip(clientinfo, &src);
+               fmt_address(src, addrbuf, sizeof(addrbuf));
+       }
+       fprintf(stderr, "findzonedb: connection from: %s\n", addrbuf);
 
        state->log(ISC_LOG_INFO,
-                  "dlz_example: dlz_findzonedb called with name '%s'"
+                  "dlz_example: dlz_findzonedb called with name '%s' "
                   "in zone DB '%s'", name, state->zone_name);
 
        /*
@@ -335,6 +350,14 @@ dlz_findzonedb(void *dbdata, const char *name) {
        if (strcasecmp(name, "test.example.com") == 0)
                return (ISC_R_NOMORE);
 
+       /*
+        * For example.net, only return ISC_R_NOMORE when queried
+        * from 10.53.0.1.
+        */
+       if (strcasecmp(name, "test.example.net") == 0 &&
+           strncmp(addrbuf, "10.53.0.1", 9) == 0)
+               return (ISC_R_NOMORE);
+
        if (strcasecmp(state->zone_name, name) == 0)
                return (ISC_R_SUCCESS);
 
@@ -342,7 +365,10 @@ dlz_findzonedb(void *dbdata, const char *name) {
 }
 
 /*
- * Look up one record
+ * Look up one record in the sample database.
+ *
+ * If the queryname is "source-addr", we add a TXT record containing
+ * the address of the client, to test the use of 'methods' and 'clientinfo'
  */
 isc_result_t
 dlz_lookup(const char *zone, const char *name, void *dbdata,
@@ -371,6 +397,7 @@ dlz_lookup(const char *zone, const char *name, void *dbdata,
                char buf[100];
                strcpy(buf, "unknown");
                if (methods != NULL &&
+                   methods->sourceip != NULL &&
                    methods->version - methods->age >=
                            DNS_CLIENTINFOMETHODS_VERSION)
                {
@@ -378,7 +405,7 @@ dlz_lookup(const char *zone, const char *name, void *dbdata,
                        fmt_address(src, buf, sizeof(buf));
                }
 
-               fprintf(stderr, "connection from: %s\n", buf);
+               fprintf(stderr, "lookup: connection from: %s\n", buf);
 
                found = ISC_TRUE;
                result = state->putrr(lookup, "TXT", 0, buf);
@@ -412,7 +439,7 @@ dlz_allowzonexfr(void *dbdata, const char *name, const char *client) {
        UNUSED(client);
 
        /* Just say yes for all our zones */
-       return (dlz_findzonedb(dbdata, name));
+       return (dlz_findzonedb(dbdata, name, NULL, NULL));
 }
 
 /*
index 38327d4dab205c53c1ce2bafa410bcd8d88827e0..34311128eb527a976929e06c9c93d422ab9554db 100644 (file)
@@ -112,11 +112,28 @@ ret=0
 echo "I:testing correct behavior with findzone returning ISC_R_NOMORE"
 $DIG $DIGOPTS +noall a test.example.com > /dev/null 2>&1 || ret=1
 # we should only find one logged lookup per searched DLZ database
-lines=`grep "dlz_findzonedb.*example\.com.*example.nil" ns1/named.run | wc -l`
+lines=`grep "dlz_findzonedb.*test\.example\.com.*example.nil" ns1/named.run | wc -l`
 [ $lines -eq 1 ] || ret=1
-lines=`grep "dlz_findzonedb.*example\.com.*alternate.nil" ns1/named.run | wc -l`
+lines=`grep "dlz_findzonedb.*test\.example\.com.*alternate.nil" ns1/named.run | wc -l`
 [ $lines -eq 1 ] || ret=1
 [ "$ret" -eq 0 ] || echo "I:failed"
 status=`expr $status + $ret`
 
+ret=0
+echo "I:testing findzone can return different results per client"
+$DIG $DIGOPTS -b 10.53.0.1 +noall a test.example.net > /dev/null 2>&1 || ret=1
+# we should only find one logged lookup per searched DLZ database
+lines=`grep "dlz_findzonedb.*example\.net.*example.nil" ns1/named.run | wc -l`
+[ $lines -eq 1 ] || ret=1
+lines=`grep "dlz_findzonedb.*example\.net.*alternate.nil" ns1/named.run | wc -l`
+[ $lines -eq 1 ] || ret=1
+$DIG $DIGOPTS -b 10.53.0.2 +noall a test.example.net > /dev/null 2>&1 || ret=1
+# we should find several logged lookups this time
+lines=`grep "dlz_findzonedb.*example\.net.*example.nil" ns1/named.run | wc -l`
+[ $lines -gt 2 ] || ret=1
+lines=`grep "dlz_findzonedb.*example\.net.*alternate.nil" ns1/named.run | wc -l`
+[ $lines -gt 2 ] || ret=1
+[ "$ret" -eq 0 ] || echo "I:failed"
+status=`expr $status + $ret`
+
 exit $status
index 50abb28779ecc19f0f45e39e522e5b6012ea3b0d..e72060c5a05a9aa8641f34e8dcf06e5077eaa8f2 100644 (file)
@@ -114,7 +114,8 @@ typedef struct parsed_data {
 /* forward reference */
 
 static isc_result_t
-bdb_findzone(void *driverarg, void *dbdata, const char *name);
+bdb_findzone(void *driverarg, void *dbdata, const char *name,
+            dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo);
 
 /*%
  * Parses the DBT from the Berkeley DB into a parsed_data record
@@ -226,7 +227,7 @@ bdb_allowzonexfr(void *driverarg, void *dbdata, const char *name,
        DBT key, data;
 
        /* check to see if we are authoritative for the zone first. */
-       result = bdb_findzone(driverarg, dbdata, name);
+       result = bdb_findzone(driverarg, dbdata, name, NULL, NULL);
        if (result != ISC_R_SUCCESS)
                return (ISC_R_NOTFOUND);
 
@@ -393,7 +394,8 @@ bdb_cleanup(bdb_instance_t *db) {
 }
 
 static isc_result_t
-bdb_findzone(void *driverarg, void *dbdata, const char *name)
+bdb_findzone(void *driverarg, void *dbdata, const char *name,
+            dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
 {
 
        isc_result_t result;
@@ -402,6 +404,8 @@ bdb_findzone(void *driverarg, void *dbdata, const char *name)
        DBT key, data;
 
        UNUSED(driverarg);
+       UNUSED(methods);
+       UNUSED(clientinfo);
 
        memset(&key, 0, sizeof(DBT));
        memset(&data, 0, sizeof(DBT));
index a3a2bc4de4c0674f0ddd6bb99c2afe1a440b6674..ff0809802b9487d9eec64630a3f50c23893b08ef 100644 (file)
@@ -112,7 +112,8 @@ typedef struct bdbhpt_parsed_data {
 /* forward reference */
 
 static isc_result_t
-bdbhpt_findzone(void *driverarg, void *dbdata, const char *name);
+bdbhpt_findzone(void *driverarg, void *dbdata, const char *name,
+               dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo);
 
 /*%
  * Reverses a string in place.
@@ -252,7 +253,7 @@ bdbhpt_allowzonexfr(void *driverarg, void *dbdata, const char *name,
        DBT key, data;
 
        /* check to see if we are authoritative for the zone first. */
-       result = bdbhpt_findzone(driverarg, dbdata, name);
+       result = bdbhpt_findzone(driverarg, dbdata, name, NULL, NULL);
        if (result != ISC_R_SUCCESS)
                return (ISC_R_NOTFOUND);
 
@@ -483,7 +484,8 @@ bdbhpt_cleanup(bdbhpt_instance_t *db) {
 }
 
 static isc_result_t
-bdbhpt_findzone(void *driverarg, void *dbdata, const char *name)
+bdbhpt_findzone(void *driverarg, void *dbdata, const char *name,
+               dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
 {
 
        isc_result_t result;
@@ -491,6 +493,8 @@ bdbhpt_findzone(void *driverarg, void *dbdata, const char *name)
        DBT key, data;
 
        UNUSED(driverarg);
+       UNUSED(methods);
+       UNUSED(clientinfo);
 
        memset(&key, 0, sizeof(DBT));
        memset(&data, 0, sizeof(DBT));
index 3a037988775f832bf7d365b312be0a9360fb7b02..73b79769211a458e95597bf3b22befe85f70493b 100644 (file)
@@ -749,7 +749,8 @@ fs_allnodes(const char *zone, void *driverarg, void *dbdata,
 }
 
 static isc_result_t
-fs_findzone(void *driverarg, void *dbdata, const char *name)
+fs_findzone(void *driverarg, void *dbdata, const char *name,
+           dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
 {
 
        isc_result_t result;
@@ -758,6 +759,8 @@ fs_findzone(void *driverarg, void *dbdata, const char *name)
        path = NULL;
 
        UNUSED(driverarg);
+       UNUSED(methods);
+       UNUSED(clientinfo);
 
        if (create_path(name, NULL, NULL, (config_data_t *) dbdata,
                        &path) != ISC_R_SUCCESS) {
index 160895a1908b118848fd28eaf2eb9e4d32705a0d..9bd34bd3bbf6c3572459cbc6aecf04b0e563baba 100644 (file)
@@ -117,7 +117,9 @@ typedef struct {
 /* forward references */
 
 static isc_result_t
-dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name);
+dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name,
+                 dns_clientinfomethods_t *methods,
+                 dns_clientinfo_t *clientinfo);
 
 static void
 dlz_ldap_destroy(void *driverarg, void *dbdata);
@@ -878,7 +880,7 @@ dlz_ldap_allowzonexfr(void *driverarg, void *dbdata, const char *name,
        UNUSED(driverarg);
 
        /* check to see if we are authoritative for the zone first */
-       result = dlz_ldap_findzone(driverarg, dbdata, name);
+       result = dlz_ldap_findzone(driverarg, dbdata, name, NULL, NULL);
        if (result != ISC_R_SUCCESS) {
                return (result);
        }
@@ -905,8 +907,13 @@ dlz_ldap_authority(const char *zone, void *driverarg, void *dbdata,
 }
 
 static isc_result_t
-dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name) {
+dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name,
+                 dns_clientinfomethods_t *methods,
+                 dns_clientinfo_t *clientinfo)
+{
        UNUSED(driverarg);
+       UNUSED(methods);
+       UNUSED(clientinfo);
        return (ldap_get_results(name, NULL, NULL, FINDZONE, dbdata, NULL));
 }
 
index 00e472799aa59b6a7630ad96a8020b562b85370c..97deeabeef03530693808d1ff591cf080e3005a7 100644 (file)
@@ -503,13 +503,16 @@ mysql_process_rs(dns_sdlzlookup_t *lookup, MYSQL_RES *rs)
 /*% determine if the zone is supported by (in) the database */
 
 static isc_result_t
-mysql_findzone(void *driverarg, void *dbdata, const char *name)
+mysql_findzone(void *driverarg, void *dbdata, const char *name,
+              dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
 {
        isc_result_t result;
        MYSQL_RES *rs = NULL;
        my_ulonglong rows;
 
        UNUSED(driverarg);
+       UNUSED(methods);
+       UNUSED(clientinfo);
 
        /* run the query and get the result set from the database. */
        result = mysql_get_resultset(name, NULL, NULL, FINDZONE, dbdata, &rs);
@@ -550,7 +553,7 @@ mysql_allowzonexfr(void *driverarg, void *dbdata, const char *name,
        UNUSED(driverarg);
 
        /* first check if the zone is supported by the database. */
-       result = mysql_findzone(driverarg, dbdata, name);
+       result = mysql_findzone(driverarg, dbdata, name, NULL, NULL);
        if (result != ISC_R_SUCCESS)
                return (ISC_R_NOTFOUND);
 
index 9c1ff4613cf8c098e65f446a3a7b25ec6f6590b7..283998d85eb2486b01a51476054a27d279a858ec 100644 (file)
@@ -963,13 +963,16 @@ odbc_process_rs(dns_sdlzlookup_t *lookup, dbinstance_t *dbi)
 /*% determine if the zone is supported by (in) the database */
 
 static isc_result_t
-odbc_findzone(void *driverarg, void *dbdata, const char *name)
+odbc_findzone(void *driverarg, void *dbdata, const char *name,
+             dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
 {
 
        isc_result_t result;
        dbinstance_t *dbi = NULL;
 
        UNUSED(driverarg);
+       UNUSED(methods);
+       UNUSED(clientinfo);
 
        /* run the query and get the result set from the database. */
        /* if result != ISC_R_SUCCESS cursor and mutex already cleaned up. */
@@ -1007,7 +1010,7 @@ odbc_allowzonexfr(void *driverarg, void *dbdata, const char *name,
        UNUSED(driverarg);
 
        /* first check if the zone is supported by the database. */
-       result = odbc_findzone(driverarg, dbdata, name);
+       result = odbc_findzone(driverarg, dbdata, name, NULL, NULL);
        if (result != ISC_R_SUCCESS)
                return (ISC_R_NOTFOUND);
 
index 4149bff71bfd29d26022e6cfbf227d50d8a12d23..8bd061236aaca394437ed465356f50e9cfa44401 100644 (file)
@@ -770,12 +770,17 @@ postgres_process_rs(dns_sdlzlookup_t *lookup, PGresult *rs)
 /*% determine if the zone is supported by (in) the database */
 
 static isc_result_t
-postgres_findzone(void *driverarg, void *dbdata, const char *name)
+postgres_findzone(void *driverarg, void *dbdata, const char *name,
+                 dns_clientinfomethods_t *methods,
+                 dns_clientinfo_t *clientinfo)
 {
        isc_result_t result;
        PGresult *rs = NULL;
        unsigned int rows;
+
        UNUSED(driverarg);
+       UNUSED(methods);
+       UNUSED(clientinfo);
 
        /* run the query and get the result set from the database. */
        result = postgres_get_resultset(name, NULL, NULL,
@@ -814,7 +819,7 @@ postgres_allowzonexfr(void *driverarg, void *dbdata, const char *name,
        UNUSED(driverarg);
 
        /* first check if the zone is supported by the database. */
-       result = postgres_findzone(driverarg, dbdata, name);
+       result = postgres_findzone(driverarg, dbdata, name, NULL, NULL);
        if (result != ISC_R_SUCCESS)
                return (ISC_R_NOTFOUND);
 
index a41697e344af1b5c49a151e4fb758979f61339d7..e25ef33741b94d3dd8d4c35f8bb027059ebb6f73 100644 (file)
@@ -147,12 +147,16 @@ stub_dlz_authority(const char *zone, void *driverarg, void *dbdata,
 }
 
 static isc_result_t
-stub_dlz_findzonedb(void *driverarg, void *dbdata, const char *name)
+stub_dlz_findzonedb(void *driverarg, void *dbdata, const char *name,
+                   dns_clientinfomethods_t *methods,
+                   dns_clientinfo_t *clientinfo)
 {
 
        config_data_t *cd;
 
        UNUSED(driverarg);
+       UNUSED(methods);
+       UNUSED(clientinfo);
 
        cd = (config_data_t *) dbdata;
 
index 58194fe8b4c1ab862350a72564f8ed2baaec795f..c1eb980c908a109e2c3614edb6a7e71c0474afd7 100644 (file)
 #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);
 }
index c72c1d4c75206ac5f13a9c27e96fba59914ba674..3972094ad811e99b3ffa67e465d3f9dc0687ca35 100644 (file)
@@ -36,7 +36,7 @@ typedef unsigned int isc_result_t;
 typedef int isc_boolean_t;
 typedef uint32_t dns_ttl_t;
 
-#define DLZ_DLOPEN_VERSION 2
+#define DLZ_DLOPEN_VERSION 3
 
 /* return this in flags to dlz_version() if thread safe */
 #define DNS_SDLZFLAG_THREADSAFE                0x00000001U
@@ -45,8 +45,10 @@ typedef uint32_t dns_ttl_t;
 #define ISC_R_SUCCESS                  0
 #define ISC_R_NOMEMORY                 1
 #define ISC_R_NOPERM                   6
+#define ISC_R_NOSPACE                  19
 #define ISC_R_NOTFOUND                 23
 #define ISC_R_FAILURE                  25
+#define ISC_R_NOTIMPLEMENTED           27
 #define ISC_R_NOMORE                   29
 
 /* boolean values */
@@ -67,6 +69,7 @@ typedef uint32_t dns_ttl_t;
 typedef void *dns_sdlzlookup_t;
 typedef void *dns_sdlzallnodes_t;
 typedef void *dns_view_t;
+typedef void *dns_dlzdb_t;
 
 /*
  * Method and type definitions needed for retrieval of client info
@@ -120,9 +123,9 @@ typedef isc_result_t dns_sdlz_putnamedrr_t(dns_sdlzallnodes_t *allnodes,
                                           const char *data);
 
 typedef isc_result_t dns_dlz_writeablezone_t(dns_view_t *view,
+                                            dns_dlzdb_t *dlzdb,
                                             const char *zone_name);
 
-
 /*
  * prototypes for the functions you can include in your module
  */
@@ -156,7 +159,9 @@ dlz_destroy(void *dbdata);
  * dlz_findzonedb is required for all DLZ external drivers
  */
 isc_result_t
-dlz_findzonedb(void *dbdata, const char *name);
+dlz_findzonedb(void *dbdata, const char *name,
+           dns_clientinfomethods_t *methods,
+           dns_clientinfo_t *clientinfo);
 
 /*
  * dlz_lookup is required for all DLZ external drivers
@@ -202,7 +207,7 @@ dlz_closeversion(const char *zone, isc_boolean_t commit, void *dbdata,
  * dynamic updates
  */
 isc_result_t
-dlz_configure(dns_view_t *view, void *dbdata);
+dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, void *dbdata);
 
 /*
  * dlz_ssumatch() is optional, but must be supplied if you want to support
index f8066baac6e05417b4d6a7ac065e6039b4926b6e..bb26537195e76c90da967eb8fc0654e192b493ee 100644 (file)
@@ -273,92 +273,6 @@ dns_dlzdestroy(dns_dlzdb_t **dbp) {
        *dbp = NULL;
 }
 
-
-isc_result_t
-dns_dlzfindzone(dns_view_t *view, dns_name_t *name,
-               unsigned int minlabels, dns_db_t **dbp)
-{
-       dns_fixedname_t fname;
-       dns_name_t *zonename;
-       unsigned int namelabels;
-       unsigned int i;
-       isc_result_t result;
-       dns_dlzfindzone_t findzone;
-       dns_dlzdb_t *dlzdb;
-       dns_db_t *db, *best = NULL;
-
-       /*
-        * Performs checks to make sure data is as we expect it to be.
-        */
-       REQUIRE(view != NULL);
-       REQUIRE(name != NULL);
-       REQUIRE(dbp != NULL && *dbp == NULL);
-
-       /* setup a "fixed" dns name */
-       dns_fixedname_init(&fname);
-       zonename = dns_fixedname_name(&fname);
-
-       /* count the number of labels in the name */
-       namelabels = dns_name_countlabels(name);
-
-       for (dlzdb = ISC_LIST_HEAD(view->dlz_searched);
-            dlzdb != NULL;
-            dlzdb = ISC_LIST_NEXT(dlzdb, link))
-       {
-               REQUIRE(DNS_DLZ_VALID(dlzdb));
-
-               /*
-                * loop through starting with the longest domain name and
-                * trying shorter names portions of the name until we find a
-                * match, have an error, or are below the 'minlabels'
-                * threshold.  minlabels is 0, if neither the standard
-                * database nor any previous DLZ database had a zone name
-                * match. Otherwise minlabels is the number of labels
-                * in that name.  We need to beat that for a "better"
-                * match for this DLZ database to be authoritative.
-                */
-               for (i = namelabels; i > minlabels && i > 1; i--) {
-                       if (i == namelabels) {
-                               result = dns_name_copy(name, zonename, NULL);
-                               if (result != ISC_R_SUCCESS)
-                                       return (result);
-                       } else
-                               dns_name_split(name, i, NULL, zonename);
-
-                       /* ask SDLZ driver if the zone is supported */
-                       db = NULL;
-                       findzone = dlzdb->implementation->methods->findzone;
-                       result = (*findzone)(dlzdb->implementation->driverarg,
-                                            dlzdb->dbdata, dlzdb->mctx,
-                                            view->rdclass, zonename, &db);
-
-                       if (result != ISC_R_NOTFOUND) {
-                               if (best != NULL)
-                                       dns_db_detach(&best);
-                               if (result == ISC_R_SUCCESS) {
-                                       INSIST(db != NULL);
-                                       dns_db_attach(db, &best);
-                                       dns_db_detach(&db);
-                                       minlabels = i;
-                               } else {
-                                       if (db != NULL)
-                                               dns_db_detach(&db);
-                                       break;
-                               }
-                       } else if (db != NULL)
-                               dns_db_detach(&db);
-               }
-       }
-
-       if (best != NULL) {
-               dns_db_attach(best, dbp);
-               dns_db_detach(&best);
-               return (ISC_R_SUCCESS);
-       }
-
-       return (ISC_R_NOTFOUND);
-}
-
 /*%
  * Registers a DLZ driver.  This basically just adds the dlz
  * driver to the list of available drivers in the dlz_implementations list.
index 0414c27542a5d37626c75c5b8c4730afdb6f1021..02e1b6ccd03355c5a23982b8d68a0dd45f7d59fa 100644 (file)
@@ -84,6 +84,7 @@
  ***** Imports
  *****/
 
+#include <dns/clientinfo.h>
 #include <dns/name.h>
 #include <dns/types.h>
 #include <dns/view.h>
@@ -140,10 +141,11 @@ typedef void
 typedef isc_result_t
 (*dns_dlzfindzone_t)(void *driverarg, void *dbdata, isc_mem_t *mctx,
                     dns_rdataclass_t rdclass, dns_name_t *name,
+                    dns_clientinfomethods_t *methods,
+                    dns_clientinfo_t *clientinfo,
                     dns_db_t **dbp);
 
 /*%<
-
  * Method prototype.  Drivers implementing the DLZ interface MUST
  * supply a find zone method.  This method is called when the DNS
  * server is performing a query.  The find zone method will be called
@@ -265,15 +267,6 @@ dns_dlzdestroy(dns_dlzdb_t **dbp);
  * methods, this function will call it.
  */
 
-isc_result_t
-dns_dlzfindzone(dns_view_t *view, dns_name_t *name,
-               unsigned int minlabels, dns_db_t **dbp);
-
-/*%<
- * This method is called when the DNS server is performing a query.
- * It will call the DLZ driver's find zone method.
- */
-
 isc_result_t
 dns_dlzregister(const char *drivername, const dns_dlzmethods_t *methods,
                 void *driverarg, isc_mem_t *mctx,
index c6301457e619e4918a14f3dae5fbcb15fd6c0ff3..6d47b2b7ff0d4cda0c4daaa8b8f520dff8224ef3 100644 (file)
@@ -30,142 +30,144 @@ ISC_LANG_BEGINDECLS
  * for the entry points of an external DLZ module for bind9.
  */
 
-#define DLZ_DLOPEN_VERSION 2
+#define DLZ_DLOPEN_VERSION 3
 
 /*
  * dlz_dlopen_version() is required for all DLZ external drivers. It
  * should return DLZ_DLOPEN_VERSION
  */
-typedef int dlz_dlopen_version_t (unsigned int *flags);
+typedef int dlz_dlopen_version_t(unsigned int *flags);
 
 /*
  * dlz_dlopen_create() is required for all DLZ external drivers.
  */
-typedef isc_result_t dlz_dlopen_create_t (const char *dlzname,
-                                         unsigned int argc,
-                                         char *argv[],
-                                         void **dbdata,
-                                         ...);
+typedef isc_result_t dlz_dlopen_create_t(const char *dlzname,
+                                        unsigned int argc,
+                                        char *argv[],
+                                        void **dbdata,
+                                        ...);
 
 /*
  * dlz_dlopen_destroy() is optional, and will be called when the
  * driver is unloaded if supplied
  */
-typedef void dlz_dlopen_destroy_t (void *dbdata);
+typedef void dlz_dlopen_destroy_t(void *dbdata);
 
 /*
  * dlz_dlopen_findzonedb() is required for all DLZ external drivers
  */
-typedef isc_result_t dlz_dlopen_findzonedb_t (void *dbdata,
-                                             const char *name);
+typedef isc_result_t dlz_dlopen_findzonedb_t(void *dbdata,
+                                            const char *name,
+                                            dns_clientinfomethods_t *methods,
+                                            dns_clientinfo_t *clientinfo);
 
 /*
  * dlz_dlopen_lookup() is required for all DLZ external drivers
  */
-typedef isc_result_t dlz_dlopen_lookup_t (const char *zone,
-                                         const char *name,
-                                         void *dbdata,
-                                         dns_sdlzlookup_t *lookup,
-                                         dns_clientinfomethods_t *methods,
-                                         dns_clientinfo_t *clientinfo);
+typedef isc_result_t dlz_dlopen_lookup_t(const char *zone,
+                                        const char *name,
+                                        void *dbdata,
+                                        dns_sdlzlookup_t *lookup,
+                                        dns_clientinfomethods_t *methods,
+                                        dns_clientinfo_t *clientinfo);
 
 /*
  * dlz_dlopen_authority is optional() if dlz_dlopen_lookup()
  * supplies authority information for the dns record
  */
-typedef isc_result_t dlz_dlopen_authority_t (const char *zone,
-                                            void *dbdata,
-                                            dns_sdlzlookup_t *lookup);
+typedef isc_result_t dlz_dlopen_authority_t(const char *zone,
+                                           void *dbdata,
+                                           dns_sdlzlookup_t *lookup);
 
 /*
  * dlz_dlopen_allowzonexfr() is optional, and should be supplied if
  * you want to support zone transfers
  */
-typedef isc_result_t dlz_dlopen_allowzonexfr_t (void *dbdata,
-                                               const char *name,
-                                               const char *client);
+typedef isc_result_t dlz_dlopen_allowzonexfr_t(void *dbdata,
+                                              const char *name,
+                                              const char *client);
 
 /*
  * dlz_dlopen_allnodes() is optional, but must be supplied if supply a
  * dlz_dlopen_allowzonexfr() function
  */
-typedef isc_result_t dlz_dlopen_allnodes_t (const char *zone,
-                                           void *dbdata,
-                                           dns_sdlzallnodes_t *allnodes);
+typedef isc_result_t dlz_dlopen_allnodes_t(const char *zone,
+                                          void *dbdata,
+                                          dns_sdlzallnodes_t *allnodes);
 
 /*
  * dlz_dlopen_newversion() is optional. It should be supplied if you
  * want to support dynamic updates.
  */
-typedef isc_result_t dlz_dlopen_newversion_t (const char *zone,
-                                             void *dbdata,
-                                             void **versionp);
+typedef isc_result_t dlz_dlopen_newversion_t(const char *zone,
+                                            void *dbdata,
+                                            void **versionp);
 
 /*
  * dlz_closeversion() is optional, but must be supplied if you supply
  * a dlz_newversion() function
  */
-typedef void dlz_dlopen_closeversion_t (const char *zone,
-                                       isc_boolean_t commit,
-                                       void *dbdata,
-                                       void **versionp);
+typedef void dlz_dlopen_closeversion_t(const char *zone,
+                                      isc_boolean_t commit,
+                                      void *dbdata,
+                                      void **versionp);
 
 /*
  * dlz_dlopen_configure() is optional, but must be supplied if you
  * want to support dynamic updates
  */
-typedef isc_result_t dlz_dlopen_configure_t (dns_view_t *view,
-                                            dns_dlzdb_t *dlzdb,
-                                            void *dbdata);
+typedef isc_result_t dlz_dlopen_configure_t(dns_view_t *view,
+                                           dns_dlzdb_t *dlzdb,
+                                           void *dbdata);
 
 /*
  * dlz_dlopen_setclientcallback() is optional, but must be supplied if you
  * want to retrieve information about the client (e.g., source address)
  * before sending a replay.
  */
-typedef isc_result_t dlz_dlopen_setclientcallback_t (dns_view_t *view,
-                                                    void *dbdata);
+typedef isc_result_t dlz_dlopen_setclientcallback_t(dns_view_t *view,
+                                                   void *dbdata);
 
 
 /*
  * dlz_dlopen_ssumatch() is optional, but must be supplied if you want
  * to support dynamic updates
  */
-typedef isc_boolean_t dlz_dlopen_ssumatch_t (const char *signer,
-                                            const char *name,
-                                            const char *tcpaddr,
-                                            const char *type,
-                                            const char *key,
-                                            isc_uint32_t keydatalen,
-                                            unsigned char *keydata,
-                                            void *dbdata);
+typedef isc_boolean_t dlz_dlopen_ssumatch_t(const char *signer,
+                                           const char *name,
+                                           const char *tcpaddr,
+                                           const char *type,
+                                           const char *key,
+                                           isc_uint32_t keydatalen,
+                                           unsigned char *keydata,
+                                           void *dbdata);
 
 /*
  * dlz_dlopen_addrdataset() is optional, but must be supplied if you
  * want to support dynamic updates
  */
-typedef isc_result_t dlz_dlopen_addrdataset_t (const char *name,
-                                              const char *rdatastr,
-                                              void *dbdata,
-                                              void *version);
+typedef isc_result_t dlz_dlopen_addrdataset_t(const char *name,
+                                             const char *rdatastr,
+                                             void *dbdata,
+                                             void *version);
 
 /*
  * dlz_dlopen_subrdataset() is optional, but must be supplied if you
  * want to support dynamic updates
  */
-typedef isc_result_t dlz_dlopen_subrdataset_t (const char *name,
-                                              const char *rdatastr,
-                                              void *dbdata,
-                                              void *version);
+typedef isc_result_t dlz_dlopen_subrdataset_t(const char *name,
+                                             const char *rdatastr,
+                                             void *dbdata,
+                                             void *version);
 
 /*
  * dlz_dlopen_delrdataset() is optional, but must be supplied if you
  * want to support dynamic updates
  */
-typedef isc_result_t dlz_dlopen_delrdataset_t (const char *name,
-                                              const char *type,
-                                              void *dbdata,
-                                              void *version);
+typedef isc_result_t dlz_dlopen_delrdataset_t(const char *name,
+                                             const char *type,
+                                             void *dbdata,
+                                             void *version);
 
 ISC_LANG_ENDDECLS
 
index c6b396ab10ff858bf3b89c13d39e35a184b2ab4b..9108bb3482bee190623192a34041e1e1de5acc14 100644 (file)
@@ -152,8 +152,9 @@ typedef void (*dns_sdlzdestroy_t)(void *driverarg, void *dbdata);
  */
 
 typedef isc_result_t
-(*dns_sdlzfindzone_t)(void *driverarg, void *dbdata, const char *name);
-
+(*dns_sdlzfindzone_t)(void *driverarg, void *dbdata, const char *name,
+                     dns_clientinfomethods_t *methods,
+                     dns_clientinfo_t *clientinfo);
 /*%<
  * Method prototype.  Drivers implementing the SDLZ interface MUST
  * supply a find zone method.  This method is called when the DNS
index 5962a7527894e33a1bce9e1df6d979695824d1b4..5865d4a7f9042e86642030fc1fb3e58f0c3962fc 100644 (file)
@@ -72,6 +72,7 @@
 #include <isc/stdtime.h>
 
 #include <dns/acl.h>
+#include <dns/clientinfo.h>
 #include <dns/fixedname.h>
 #include <dns/rdatastruct.h>
 #include <dns/rpz.h>
@@ -1136,6 +1137,29 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
 void
 dns_view_restorekeyring(dns_view_t *view);
 
+isc_result_t
+dns_view_searchdlz(dns_view_t *view, dns_name_t *name,
+                  unsigned int minlabels,
+                  dns_clientinfomethods_t *methods,
+                  dns_clientinfo_t *clientinfo,
+                  dns_db_t **dbp);
+
+/*%<
+ * Search through the DLZ database(s) in view->dlz_searched to find
+ * one that can answer a query for 'name', using the DLZ driver's
+ * findzone method.  If successful, '*dbp' is set to point to the
+ * DLZ database.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOTFOUND
+ *
+ * Requires:
+ * \li 'view' is valid.
+ * \li 'name' is not NULL.
+ * \li 'dbp' is not NULL and *dbp is NULL.
+ */
+
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_VIEW_H */
index d509364c51c4d8ac3e85c38eab9f0fe10ec75084..c80cce1caa334c41db4619fb337335e6a548af49 100644 (file)
@@ -1628,7 +1628,10 @@ dns_sdlzdestroy(void *driverdata, void **dbdata) {
 
 static isc_result_t
 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
-                dns_rdataclass_t rdclass, dns_name_t *name, dns_db_t **dbp)
+                dns_rdataclass_t rdclass, dns_name_t *name,
+                dns_clientinfomethods_t *methods,
+                dns_clientinfo_t *clientinfo,
+                dns_db_t **dbp)
 {
        isc_buffer_t b;
        char namestr[DNS_NAME_MAXTEXT + 1];
@@ -1656,7 +1659,8 @@ dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
 
        /* Call SDLZ driver's find zone method */
        MAYBE_LOCK(imp);
-       result = imp->methods->findzone(imp->driverarg, dbdata, namestr);
+       result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
+                                       methods, clientinfo);
        MAYBE_UNLOCK(imp);
 
        /*
index b9fd09ead41a10cd06c1dc2aed82ccfad6195f9b..4562c1bcbc83cab85b1c2b23186d7a0abdf9d65f 100644 (file)
@@ -1868,3 +1868,91 @@ dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
        UNUSED(cfg_destroy);
 #endif
 }
+
+isc_result_t
+dns_view_searchdlz(dns_view_t *view, dns_name_t *name, unsigned int minlabels,
+                  dns_clientinfomethods_t *methods,
+                  dns_clientinfo_t *clientinfo,
+                  dns_db_t **dbp)
+{
+       dns_fixedname_t fname;
+       dns_name_t *zonename;
+       unsigned int namelabels;
+       unsigned int i;
+       isc_result_t result;
+       dns_dlzfindzone_t findzone;
+       dns_dlzdb_t *dlzdb;
+       dns_db_t *db, *best = NULL;
+
+       /*
+        * Performs checks to make sure data is as we expect it to be.
+        */
+       REQUIRE(DNS_VIEW_VALID(view));
+       REQUIRE(name != NULL);
+       REQUIRE(dbp != NULL && *dbp == NULL);
+
+       /* setup a "fixed" dns name */
+       dns_fixedname_init(&fname);
+       zonename = dns_fixedname_name(&fname);
+
+       /* count the number of labels in the name */
+       namelabels = dns_name_countlabels(name);
+
+       for (dlzdb = ISC_LIST_HEAD(view->dlz_searched);
+            dlzdb != NULL;
+            dlzdb = ISC_LIST_NEXT(dlzdb, link))
+       {
+               REQUIRE(DNS_DLZ_VALID(dlzdb));
+
+               /*
+                * loop through starting with the longest domain name and
+                * trying shorter names portions of the name until we find a
+                * match, have an error, or are below the 'minlabels'
+                * threshold.  minlabels is 0, if neither the standard
+                * database nor any previous DLZ database had a zone name
+                * match. Otherwise minlabels is the number of labels
+                * in that name.  We need to beat that for a "better"
+                * match for this DLZ database to be authoritative.
+                */
+               for (i = namelabels; i > minlabels && i > 1; i--) {
+                       if (i == namelabels) {
+                               result = dns_name_copy(name, zonename, NULL);
+                               if (result != ISC_R_SUCCESS)
+                                       return (result);
+                       } else
+                               dns_name_split(name, i, NULL, zonename);
+
+                       /* ask SDLZ driver if the zone is supported */
+                       db = NULL;
+                       findzone = dlzdb->implementation->methods->findzone;
+                       result = (*findzone)(dlzdb->implementation->driverarg,
+                                            dlzdb->dbdata, dlzdb->mctx,
+                                            view->rdclass, zonename,
+                                            methods, clientinfo, &db);
+
+                       if (result != ISC_R_NOTFOUND) {
+                               if (best != NULL)
+                                       dns_db_detach(&best);
+                               if (result == ISC_R_SUCCESS) {
+                                       INSIST(db != NULL);
+                                       dns_db_attach(db, &best);
+                                       dns_db_detach(&db);
+                                       minlabels = i;
+                               } else {
+                                       if (db != NULL)
+                                               dns_db_detach(&db);
+                                       break;
+                               }
+                       } else if (db != NULL)
+                               dns_db_detach(&db);
+               }
+       }
+
+       if (best != NULL) {
+               dns_db_attach(best, dbp);
+               dns_db_detach(&best);
+               return (ISC_R_SUCCESS);
+       }
+
+       return (ISC_R_NOTFOUND);
+}
index 4895e01202e0e9b1f5c58f38871d8b4f0c45e728..eec36f7615bcbcfe1ee4185deea246d2f1952631 100644 (file)
@@ -203,7 +203,6 @@ dns_dlzallowzonexfr
 dns_dlzconfigure
 dns_dlzcreate
 dns_dlzdestroy
-dns_dlzfindzone
 dns_dlzregister
 dns_dlzstrtoargv
 dns_dlzunregister
@@ -774,6 +773,7 @@ dns_view_issecuredomain
 dns_view_load
 dns_view_loadnew
 dns_view_restorekeyring
+dns_view_searchdlz
 dns_view_setcache
 dns_view_setcache2
 dns_view_setdstport
index a28043a2d8472e07df9998708dfac29f4702a531..a1a5d1b5ad06f4fa64781fff39f9262c1aeff62e 100644 (file)
@@ -1670,7 +1670,8 @@ zone_load(dns_zone_t *zone, unsigned int flags) {
                findzone = dlzdb->implementation->methods->findzone;
                result = (*findzone)(dlzdb->implementation->driverarg,
                                     dlzdb->dbdata, dlzdb->mctx,
-                                    zone->view->rdclass, &zone->origin, &db);
+                                    zone->view->rdclass, &zone->origin,
+                                    NULL, NULL, &db);
                if (result != ISC_R_NOTFOUND) {
                        if (zone->db != NULL)
                                zone_detachdb(zone);