diff --git a/bin/named/unix/dlz_dlopen_driver.c b/bin/named/unix/dlz_dlopen_driver.c index fc5ab8669f..552f698332 100644 --- a/bin/named/unix/dlz_dlopen_driver.c +++ b/bin/named/unix/dlz_dlopen_driver.c @@ -326,11 +326,13 @@ dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[], /* Check the version of the API is the same */ cd->version = cd->dlz_version(&cd->flags); - if (cd->version != DLZ_DLOPEN_VERSION) { + if (cd->version < (DLZ_DLOPEN_VERSION - DLZ_DLOPEN_AGE) || + cd->version > DLZ_DLOPEN_VERSION) + { dlopen_log(ISC_LOG_ERROR, - "dlz_dlopen: incorrect version %d " - "should be %d in '%s'", - cd->version, DLZ_DLOPEN_VERSION, cd->dl_path); + "dlz_dlopen: %s: incorrect driver API version %d, " + "requires %d", + cd->dl_path, cd->version, DLZ_DLOPEN_VERSION); goto failed; } diff --git a/bin/named/win32/dlz_dlopen_driver.c b/bin/named/win32/dlz_dlopen_driver.c index 6c9ecb8116..a73c65f574 100644 --- a/bin/named/win32/dlz_dlopen_driver.c +++ b/bin/named/win32/dlz_dlopen_driver.c @@ -310,11 +310,13 @@ dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[], /* Check the version of the API is the same */ cd->version = cd->dlz_version(&cd->flags); - if (cd->version != DLZ_DLOPEN_VERSION) { + if (cd->version < (DLZ_DLOPEN_VERSION - DLZ_DLOPEN_AGE) || + cd->version > DLZ_DLOPEN_VERSION) + { dlopen_log(ISC_LOG_ERROR, - "dlz_dlopen: incorrect version %d " - "should be %d in '%s'", - cd->version, DLZ_DLOPEN_VERSION, cd->dl_path); + "dlz_dlopen: %s: incorrect driver API version %d, " + "requires %d", + cd->dl_path, cd->version, DLZ_DLOPEN_VERSION); goto failed; } diff --git a/bin/tests/system/dlzexternal/driver.c b/bin/tests/system/dlzexternal/driver.c index ee208d8c76..765f32fad1 100644 --- a/bin/tests/system/dlzexternal/driver.c +++ b/bin/tests/system/dlzexternal/driver.c @@ -368,8 +368,11 @@ dlz_findzonedb(void *dbdata, const char *name, /* * Look up one record in the sample database. * - * If the queryname is "source-addr", we add a TXT record containing + * If the queryname is "source-addr", send back a TXT record containing * the address of the client, to test the use of 'methods' and 'clientinfo' + * + * If the queryname is "too-long", send back a TXT record that's too long + * to process; this should result in a SERVFAIL when queried. */ isc_result_t dlz_lookup(const char *zone, const char *name, void *dbdata, @@ -381,6 +384,7 @@ dlz_lookup(const char *zone, const char *name, void *dbdata, isc_boolean_t found = ISC_FALSE; isc_sockaddr_t *src; char full_name[256]; + char buf[512]; int i; UNUSED(zone); @@ -395,7 +399,6 @@ dlz_lookup(const char *zone, const char *name, void *dbdata, 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 && @@ -415,6 +418,16 @@ dlz_lookup(const char *zone, const char *name, void *dbdata, return (result); } + if (strcmp(name, "too-long") == 0) { + for (i = 0; i < 511; i++) + buf[i] = 'x'; + buf[i] = '\0'; + found = ISC_TRUE; + result = state->putrr(lookup, "TXT", 0, buf); + if (result != ISC_R_SUCCESS) + return (result); + } + for (i = 0; i < MAX_RECORDS; i++) { if (strcasecmp(state->current[i].name, full_name) == 0) { found = ISC_TRUE; diff --git a/bin/tests/system/dlzexternal/tests.sh b/bin/tests/system/dlzexternal/tests.sh index 34311128eb..c8beb537ff 100644 --- a/bin/tests/system/dlzexternal/tests.sh +++ b/bin/tests/system/dlzexternal/tests.sh @@ -136,4 +136,11 @@ lines=`grep "dlz_findzonedb.*example\.net.*alternate.nil" ns1/named.run | wc -l` [ "$ret" -eq 0 ] || echo "I:failed" status=`expr $status + $ret` +ret=0 +echo "I:testing zone returning oversized data" +$DIG $DIGOPTS txt too-long.example.nil > dig.out.ns1.6 2>&1 || ret=1 +grep "status: SERVFAIL" dig.out.ns1.6 > /dev/null || ret=1 +[ "$ret" -eq 0 ] || echo "I:failed" +status=`expr $status + $ret` + exit $status diff --git a/contrib/dlz/example/dlz_example.c b/contrib/dlz/example/dlz_example.c index 0212f884f3..0f381ba5c9 100644 --- a/contrib/dlz/example/dlz_example.c +++ b/contrib/dlz/example/dlz_example.c @@ -357,9 +357,12 @@ dlz_findzonedb(void *dbdata, const char *name, /* * Look up one record in the sample database. * - * If the queryname is "source-addr", we add a TXT record containing + * If the queryname is "source-addr", send back a TXT record containing * the address of the client; this demonstrates the use of 'methods' * and 'clientinfo'. + * + * If the queryname is "too-long", send back a TXT record that's too long + * to process; this should result in a SERVFAIL when queried. */ isc_result_t dlz_lookup(const char *zone, const char *name, void *dbdata, @@ -371,6 +374,7 @@ dlz_lookup(const char *zone, const char *name, void *dbdata, isc_boolean_t found = ISC_FALSE; isc_sockaddr_t *src; char full_name[256]; + char buf[512]; int i; UNUSED(zone); @@ -385,7 +389,6 @@ dlz_lookup(const char *zone, const char *name, void *dbdata, 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 && @@ -406,6 +409,16 @@ dlz_lookup(const char *zone, const char *name, void *dbdata, return (result); } + if (strcmp(name, "too-long") == 0) { + for (i = 0; i < 511; i++) + buf[i] = 'x'; + buf[i] = '\0'; + found = ISC_TRUE; + result = state->putrr(lookup, "TXT", 0, buf); + if (result != ISC_R_SUCCESS) + return (result); + } + for (i = 0; i < MAX_RECORDS; i++) { if (strcasecmp(state->current[i].name, full_name) == 0) { found = ISC_TRUE; diff --git a/contrib/dlz/example/dlz_minimal.h b/contrib/dlz/example/dlz_minimal.h index 3972094ad8..50eb99eff5 100644 --- a/contrib/dlz/example/dlz_minimal.h +++ b/contrib/dlz/example/dlz_minimal.h @@ -37,6 +37,7 @@ typedef int isc_boolean_t; typedef uint32_t dns_ttl_t; #define DLZ_DLOPEN_VERSION 3 +#define DLZ_DLOPEN_AGE 0 /* return this in flags to dlz_version() if thread safe */ #define DNS_SDLZFLAG_THREADSAFE 0x00000001U diff --git a/lib/dns/include/dns/dlz_dlopen.h b/lib/dns/include/dns/dlz_dlopen.h index 6d47b2b7ff..738b5e921a 100644 --- a/lib/dns/include/dns/dlz_dlopen.h +++ b/lib/dns/include/dns/dlz_dlopen.h @@ -31,6 +31,7 @@ ISC_LANG_BEGINDECLS */ #define DLZ_DLOPEN_VERSION 3 +#define DLZ_DLOPEN_AGE 0 /* * dlz_dlopen_version() is required for all DLZ external drivers. It diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c index 7ff4ee7264..db129d062e 100644 --- a/lib/dns/sdlz.c +++ b/lib/dns/sdlz.c @@ -605,7 +605,7 @@ findnodeext(dns_db_t *db, dns_name_t *name, isc_boolean_t create, * if the host (namestr) was not found, try to lookup a * "wildcard" host. */ - if (result != ISC_R_SUCCESS && !create) + if (result == ISC_R_NOTFOUND && !create) result = sdlz->dlzimp->methods->lookup(zonestr, "*", sdlz->dlzimp->driverarg, sdlz->dbdata, node, @@ -878,10 +878,11 @@ findext(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, dns_name_getlabelsequence(name, nlabels - i, i, xname); result = findnodeext(db, xname, ISC_FALSE, methods, clientinfo, &node); - if (result != ISC_R_SUCCESS) { + if (result == ISC_R_NOTFOUND) { result = DNS_R_NXDOMAIN; continue; - } + } else if (result != ISC_R_SUCCESS) + break; /* * Look for a DNAME at the current label, unless this is