From: Evan Hunt Date: Tue, 22 Jan 2013 23:13:08 +0000 (-0800) Subject: [master] DLZ fixes X-Git-Tag: v9.10.0a1~556 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=cbd1fa092ea66bfa9990c5e515725646295396c5;p=thirdparty%2Fbind9.git [master] DLZ fixes - handle malformed answers from DLZ better: - handle dlz_lookup errors better: when the first lookup of a name returns an unexpected failure code, we return it to the caller rather than continuing on to look up the wildcard. we now only continue processing if the return from the first lookup was either ISC_R_SUCCESS or ISC_R_NOTFOUND. - improved backward-compatibility for dlz_version: added a DLZ_DLOPEN_AGE value indicating how many versions back from the current DLZ_DLOPEN_VERSION named will support --- diff --git a/bin/named/unix/dlz_dlopen_driver.c b/bin/named/unix/dlz_dlopen_driver.c index fc5ab8669f6..552f6983324 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 6c9ecb81166..a73c65f5747 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 ee208d8c76b..765f32fad11 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 34311128eb5..c8beb537ffc 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 0212f884f3b..0f381ba5c95 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 3972094ad81..50eb99eff55 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 6d47b2b7ff0..738b5e921a8 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 7ff4ee72640..db129d062e0 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