2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 05:28:00 +00:00

[master] add better servfail logging

3937.	[func]		Added some debug logging to better indicate the
			conditions causing SERVFAILs when resolving.
			[RT #35538]
This commit is contained in:
Evan Hunt 2014-08-28 22:37:55 -07:00
parent d46855caed
commit f5c24a7f48
3 changed files with 377 additions and 107 deletions

View File

@ -1,3 +1,7 @@
3937. [func] Added some debug logging to better indicate the
conditions causing SERVFAILs when resolving.
[RT #35538]
3936. [func] Added authoritative support for the EDNS Client
Subnet (ECS) option.

View File

@ -125,21 +125,25 @@
DNS_RDATASETATTR_NOQNAME) != 0)
#if 0
#define CTRACE(m) isc_log_write(ns_g_lctx, \
NS_LOGCATEGORY_CLIENT, \
NS_LOGMODULE_QUERY, \
ISC_LOG_DEBUG(3), \
"client %p: %s", client, (m))
#define QTRACE(m) isc_log_write(ns_g_lctx, \
NS_LOGCATEGORY_GENERAL, \
NS_LOGMODULE_QUERY, \
ISC_LOG_DEBUG(3), \
"query %p: %s", query, (m))
#define CTRACE(l,m) do { \
if (client != NULL && client->query.qname != NULL) { \
char qbuf[DNS_NAME_FORMATSIZE]; \
dns_name_format(client->query.qname, qbuf, sizeof(qbuf)); \
isc_log_write(ns_g_lctx, \
NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, \
l, "client %p (%s): %s", client, qbuf, (m)); \
} else { \
isc_log_write(ns_g_lctx, \
NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_QUERY, \
l, "client %p (<unknown-name>): %s", \
client, (m)); \
} \
} while(0)
#else
#define CTRACE(m) ((void)m)
#define QTRACE(m) ((void)m)
#define CTRACE(l,m) ((void)m)
#endif
#define DNS_GETDB_NOEXACT 0x01U
#define DNS_GETDB_NOLOG 0x02U
#define DNS_GETDB_PARTIAL 0x04U
@ -312,13 +316,13 @@ static inline void
query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) {
dns_rdataset_t *rdataset = *rdatasetp;
CTRACE("query_putrdataset");
CTRACE(ISC_LOG_DEBUG(3), "query_putrdataset");
if (rdataset != NULL) {
if (dns_rdataset_isassociated(rdataset))
dns_rdataset_disassociate(rdataset);
dns_message_puttemprdataset(client->message, rdatasetp);
}
CTRACE("query_putrdataset: done");
CTRACE(ISC_LOG_DEBUG(3), "query_putrdataset: done");
}
static inline void
@ -425,7 +429,7 @@ query_newnamebuf(ns_client_t *client) {
isc_buffer_t *dbuf;
isc_result_t result;
CTRACE("query_newnamebuf");
CTRACE(ISC_LOG_DEBUG(3), "query_newnamebuf");
/*%
* Allocate a name buffer.
*/
@ -433,12 +437,13 @@ query_newnamebuf(ns_client_t *client) {
dbuf = NULL;
result = isc_buffer_allocate(client->mctx, &dbuf, 1024);
if (result != ISC_R_SUCCESS) {
CTRACE("query_newnamebuf: isc_buffer_allocate failed: done");
CTRACE(ISC_LOG_DEBUG(3),
"query_newnamebuf: isc_buffer_allocate failed: done");
return (result);
}
ISC_LIST_APPEND(client->query.namebufs, dbuf, link);
CTRACE("query_newnamebuf: done");
CTRACE(ISC_LOG_DEBUG(3), "query_newnamebuf: done");
return (ISC_R_SUCCESS);
}
@ -448,7 +453,7 @@ query_getnamebuf(ns_client_t *client) {
isc_result_t result;
isc_region_t r;
CTRACE("query_getnamebuf");
CTRACE(ISC_LOG_DEBUG(3), "query_getnamebuf");
/*%
* Return a name buffer with space for a maximal name, allocating
* a new one if necessary.
@ -457,7 +462,8 @@ query_getnamebuf(ns_client_t *client) {
if (ISC_LIST_EMPTY(client->query.namebufs)) {
result = query_newnamebuf(client);
if (result != ISC_R_SUCCESS) {
CTRACE("query_getnamebuf: query_newnamebuf failed: done");
CTRACE(ISC_LOG_DEBUG(3),
"query_getnamebuf: query_newnamebuf failed: done");
return (NULL);
}
}
@ -468,7 +474,8 @@ query_getnamebuf(ns_client_t *client) {
if (r.length < 255) {
result = query_newnamebuf(client);
if (result != ISC_R_SUCCESS) {
CTRACE("query_getnamebuf: query_newnamebuf failed: done");
CTRACE(ISC_LOG_DEBUG(3),
"query_getnamebuf: query_newnamebuf failed: done");
return (NULL);
}
@ -476,7 +483,7 @@ query_getnamebuf(ns_client_t *client) {
isc_buffer_availableregion(dbuf, &r);
INSIST(r.length >= 255);
}
CTRACE("query_getnamebuf: done");
CTRACE(ISC_LOG_DEBUG(3), "query_getnamebuf: done");
return (dbuf);
}
@ -484,7 +491,7 @@ static inline void
query_keepname(ns_client_t *client, dns_name_t *name, isc_buffer_t *dbuf) {
isc_region_t r;
CTRACE("query_keepname");
CTRACE(ISC_LOG_DEBUG(3), "query_keepname");
/*%
* 'name' is using space in 'dbuf', but 'dbuf' has not yet been
* adjusted to take account of that. We do the adjustment.
@ -508,14 +515,14 @@ query_releasename(ns_client_t *client, dns_name_t **namep) {
* rights on the buffer.
*/
CTRACE("query_releasename");
CTRACE(ISC_LOG_DEBUG(3), "query_releasename");
if (dns_name_hasbuffer(name)) {
INSIST((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED)
!= 0);
client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
}
dns_message_puttempname(client->message, namep);
CTRACE("query_releasename: done");
CTRACE(ISC_LOG_DEBUG(3), "query_releasename: done");
}
static inline dns_name_t *
@ -528,11 +535,12 @@ query_newname(ns_client_t *client, isc_buffer_t *dbuf,
REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) == 0);
CTRACE("query_newname");
CTRACE(ISC_LOG_DEBUG(3), "query_newname");
name = NULL;
result = dns_message_gettempname(client->message, &name);
if (result != ISC_R_SUCCESS) {
CTRACE("query_newname: dns_message_gettempname failed: done");
CTRACE(ISC_LOG_DEBUG(3),
"query_newname: dns_message_gettempname failed: done");
return (NULL);
}
isc_buffer_availableregion(dbuf, &r);
@ -541,7 +549,7 @@ query_newname(ns_client_t *client, isc_buffer_t *dbuf,
dns_name_setbuffer(name, nbuf);
client->query.attributes |= NS_QUERYATTR_NAMEBUFUSED;
CTRACE("query_newname: done");
CTRACE(ISC_LOG_DEBUG(3), "query_newname: done");
return (name);
}
@ -550,17 +558,18 @@ query_newrdataset(ns_client_t *client) {
dns_rdataset_t *rdataset;
isc_result_t result;
CTRACE("query_newrdataset");
CTRACE(ISC_LOG_DEBUG(3), "query_newrdataset");
rdataset = NULL;
result = dns_message_gettemprdataset(client->message, &rdataset);
if (result != ISC_R_SUCCESS) {
CTRACE("query_newrdataset: "
CTRACE(ISC_LOG_DEBUG(3),
"query_newrdataset: "
"dns_message_gettemprdataset failed: done");
return (NULL);
}
dns_rdataset_init(rdataset);
CTRACE("query_newrdataset: done");
CTRACE(ISC_LOG_DEBUG(3), "query_newrdataset: done");
return (rdataset);
}
@ -727,8 +736,10 @@ query_validatezonedb(ns_client_t *client, dns_name_t *name,
* Get the current version of this database.
*/
dbversion = query_findversion(client, db);
if (dbversion == NULL)
if (dbversion == NULL) {
CTRACE(ISC_LOG_ERROR, "unable to get db version");
return (DNS_R_SERVFAIL);
}
if ((options & DNS_GETDB_IGNOREACL) != 0)
goto approved;
@ -1191,7 +1202,7 @@ query_isduplicate(ns_client_t *client, dns_name_t *name,
dns_name_t *mname = NULL;
isc_result_t result;
CTRACE("query_isduplicate");
CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate");
for (section = DNS_SECTION_ANSWER;
section <= DNS_SECTION_ADDITIONAL;
@ -1202,7 +1213,8 @@ query_isduplicate(ns_client_t *client, dns_name_t *name,
/*
* We've already got this RRset in the response.
*/
CTRACE("query_isduplicate: true: done");
CTRACE(ISC_LOG_DEBUG(3),
"query_isduplicate: true: done");
return (ISC_TRUE);
} else if (result == DNS_R_NXRRSET) {
/*
@ -1218,7 +1230,7 @@ query_isduplicate(ns_client_t *client, dns_name_t *name,
if (mnamep != NULL)
*mnamep = mname;
CTRACE("query_isduplicate: false: done");
CTRACE(ISC_LOG_DEBUG(3), "query_isduplicate: false: done");
return (ISC_FALSE);
}
@ -1245,7 +1257,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
if (!WANTDNSSEC(client) && dns_rdatatype_isdnssec(qtype))
return (ISC_R_SUCCESS);
CTRACE("query_addadditional");
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional");
/*
* Initialization.
@ -1301,7 +1313,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
if (result != ISC_R_SUCCESS)
goto try_cache;
CTRACE("query_addadditional: db_find");
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: db_find");
/*
* Since we are looking for authoritative data, we do not set
@ -1573,7 +1585,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
}
addname:
CTRACE("query_addadditional: addname");
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: addname");
/*
* If we haven't added anything, then we're done.
*/
@ -1613,7 +1625,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
}
cleanup:
CTRACE("query_addadditional: cleanup");
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: cleanup");
query_putrdataset(client, &rdataset);
if (sigrdataset != NULL)
query_putrdataset(client, &sigrdataset);
@ -1626,7 +1638,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
if (zone != NULL)
dns_zone_detach(&zone);
CTRACE("query_addadditional: done");
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional: done");
return (eresult);
}
@ -1744,7 +1756,7 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
dns_clientinfomethods_init(&cm, ns_client_sourceip);
dns_clientinfo_init(&ci, client, NULL);
CTRACE("query_addadditional2");
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2");
/*
* We treat type A additional section processing as if it
@ -1776,14 +1788,16 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
if (result != ISC_R_SUCCESS)
goto findauthdb;
if (zone == NULL) {
CTRACE("query_addadditional2: auth zone not found");
CTRACE(ISC_LOG_DEBUG(3),
"query_addadditional2: auth zone not found");
goto try_cache;
}
/* Is the cached DB up-to-date? */
result = query_iscachevalid(zone, cdb, NULL, cversion);
if (result != ISC_R_SUCCESS) {
CTRACE("query_addadditional2: old auth additional cache");
CTRACE(ISC_LOG_DEBUG(3),
"query_addadditional2: old auth additional cache");
query_discardcache(client, rdataset_base, additionaltype,
type, &zone, &cdb, &cversion, &cnode,
&cfname);
@ -1796,7 +1810,8 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
* ACL, since the result (not using this zone) would be same
* regardless of the result.
*/
CTRACE("query_addadditional2: negative auth additional cache");
CTRACE(ISC_LOG_DEBUG(3),
"query_addadditional2: negative auth additional cache");
dns_db_closeversion(cdb, &cversion, ISC_FALSE);
dns_db_detach(&cdb);
dns_zone_detach(&zone);
@ -1813,7 +1828,8 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
}
/* We've got an active cache. */
CTRACE("query_addadditional2: auth additional cache");
CTRACE(ISC_LOG_DEBUG(3),
"query_addadditional2: auth additional cache");
dns_db_closeversion(cdb, &cversion, ISC_FALSE);
db = cdb;
node = cnode;
@ -1837,7 +1853,7 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
goto try_cache;
}
CTRACE("query_addadditional2: db_find");
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: db_find");
/*
* Since we are looking for authoritative data, we do not set
@ -1922,7 +1938,8 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
result = query_iscachevalid(zone, cdb, client->query.gluedb, cversion);
if (result != ISC_R_SUCCESS) {
CTRACE("query_addadditional2: old glue additional cache");
CTRACE(ISC_LOG_DEBUG(3),
"query_addadditional2: old glue additional cache");
query_discardcache(client, rdataset_base, additionaltype,
type, &zone, &cdb, &cversion, &cnode,
&cfname);
@ -1931,14 +1948,15 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
if (cnode == NULL) {
/* We have a negative cache. */
CTRACE("query_addadditional2: negative glue additional cache");
CTRACE(ISC_LOG_DEBUG(3),
"query_addadditional2: negative glue additional cache");
dns_db_closeversion(cdb, &cversion, ISC_FALSE);
dns_db_detach(&cdb);
goto cleanup;
}
/* Cache hit. */
CTRACE("query_addadditional2: glue additional cache");
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: glue additional cache");
dns_db_closeversion(cdb, &cversion, ISC_FALSE);
db = cdb;
node = cnode;
@ -2121,7 +2139,7 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
}
}
CTRACE("query_addadditional2: addname");
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: addname");
/*
* If we haven't added anything, then we're done.
@ -2140,7 +2158,7 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
fname = NULL;
cleanup:
CTRACE("query_addadditional2: cleanup");
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: cleanup");
if (rdataset != NULL)
query_putrdataset(client, &rdataset);
@ -2159,7 +2177,7 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
if (zone != NULL)
dns_zone_detach(&zone);
CTRACE("query_addadditional2: done");
CTRACE(ISC_LOG_DEBUG(3), "query_addadditional2: done");
return (eresult);
}
@ -2174,7 +2192,7 @@ query_addrdataset(ns_client_t *client, dns_name_t *fname,
* 'fname', a name in the response message for 'client'.
*/
CTRACE("query_addrdataset");
CTRACE(ISC_LOG_DEBUG(3), "query_addrdataset");
ISC_LIST_APPEND(fname->list, rdataset, link);
@ -2196,7 +2214,7 @@ query_addrdataset(ns_client_t *client, dns_name_t *fname,
additionalctx.rdataset = rdataset;
(void)dns_rdataset_additionaldata(rdataset, query_addadditional2,
&additionalctx);
CTRACE("query_addrdataset: done");
CTRACE(ISC_LOG_DEBUG(3), "query_addrdataset: done");
}
static isc_result_t
@ -2228,7 +2246,7 @@ query_dns64(ns_client_t *client, dns_name_t **namep, dns_rdataset_t *rdataset,
* stored in 'dbuf'. In this case, query_addrrset() guarantees that
* when it returns the name will either have been kept or released.
*/
CTRACE("query_dns64");
CTRACE(ISC_LOG_DEBUG(3), "query_dns64");
name = *namep;
mname = NULL;
mrdataset = NULL;
@ -2245,7 +2263,8 @@ query_dns64(ns_client_t *client, dns_name_t **namep, dns_rdataset_t *rdataset,
* We've already got an RRset of the given name and type.
* There's nothing else to do;
*/
CTRACE("query_dns64: dns_message_findname succeeded: done");
CTRACE(ISC_LOG_DEBUG(3),
"query_dns64: dns_message_findname succeeded: done");
if (dbuf != NULL)
query_releasename(client, namep);
return (ISC_R_SUCCESS);
@ -2376,7 +2395,7 @@ query_dns64(ns_client_t *client, dns_name_t **namep, dns_rdataset_t *rdataset,
dns_message_puttemprdatalist(client->message, &dns64_rdatalist);
}
CTRACE("query_dns64: done");
CTRACE(ISC_LOG_DEBUG(3), "query_dns64: done");
return (result);
}
@ -2395,7 +2414,7 @@ query_filter64(ns_client_t *client, dns_name_t **namep,
isc_result_t result;
unsigned int i;
CTRACE("query_filter64");
CTRACE(ISC_LOG_DEBUG(3), "query_filter64");
INSIST(client->query.dns64_aaaaok != NULL);
INSIST(client->query.dns64_aaaaoklen == dns_rdataset_count(rdataset));
@ -2415,7 +2434,8 @@ query_filter64(ns_client_t *client, dns_name_t **namep,
* We've already got an RRset of the given name and type.
* There's nothing else to do;
*/
CTRACE("query_filter64: dns_message_findname succeeded: done");
CTRACE(ISC_LOG_DEBUG(3),
"query_filter64: dns_message_findname succeeded: done");
if (dbuf != NULL)
query_releasename(client, namep);
return;
@ -2514,7 +2534,7 @@ query_filter64(ns_client_t *client, dns_name_t **namep,
if (dbuf != NULL)
query_releasename(client, &name);
CTRACE("query_filter64: done");
CTRACE(ISC_LOG_DEBUG(3), "query_filter64: done");
}
static void
@ -2536,7 +2556,7 @@ query_addrrset(ns_client_t *client, dns_name_t **namep,
* stored in 'dbuf'. In this case, query_addrrset() guarantees that
* when it returns the name will either have been kept or released.
*/
CTRACE("query_addrrset");
CTRACE(ISC_LOG_DEBUG(3), "query_addrrset");
name = *namep;
rdataset = *rdatasetp;
if (sigrdatasetp != NULL)
@ -2552,7 +2572,8 @@ query_addrrset(ns_client_t *client, dns_name_t **namep,
/*
* We've already got an RRset of the given name and type.
*/
CTRACE("query_addrrset: dns_message_findname succeeded: done");
CTRACE(ISC_LOG_DEBUG(3),
"query_addrrset: dns_message_findname succeeded: done");
if (dbuf != NULL)
query_releasename(client, namep);
if ((rdataset->attributes & DNS_RDATASETATTR_REQUIRED) != 0)
@ -2591,7 +2612,7 @@ query_addrrset(ns_client_t *client, dns_name_t **namep,
ISC_LIST_APPEND(mname->list, sigrdataset, link);
*sigrdatasetp = NULL;
}
CTRACE("query_addrrset: done");
CTRACE(ISC_LOG_DEBUG(3), "query_addrrset: done");
}
static inline isc_result_t
@ -2607,7 +2628,7 @@ query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,
dns_clientinfomethods_t cm;
dns_clientinfo_t ci;
CTRACE("query_addsoa");
CTRACE(ISC_LOG_DEBUG(3), "query_addsoa");
/*
* Initialization.
*/
@ -2635,12 +2656,14 @@ query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,
dns_name_clone(dns_db_origin(db), name);
rdataset = query_newrdataset(client);
if (rdataset == NULL) {
CTRACE(ISC_LOG_ERROR, "unable to allocate rdataset");
eresult = DNS_R_SERVFAIL;
goto cleanup;
}
if (WANTDNSSEC(client) && dns_db_issecure(db)) {
sigrdataset = query_newrdataset(client);
if (sigrdataset == NULL) {
CTRACE(ISC_LOG_ERROR, "unable to allocate sigrdataset");
eresult = DNS_R_SERVFAIL;
goto cleanup;
}
@ -2670,6 +2693,7 @@ query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,
* This is bad. We tried to get the SOA RR at the zone top
* and it didn't work!
*/
CTRACE(ISC_LOG_ERROR, "unable to find SOA RR at zone apex");
eresult = DNS_R_SERVFAIL;
} else {
/*
@ -2734,7 +2758,7 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
dns_clientinfomethods_t cm;
dns_clientinfo_t ci;
CTRACE("query_addns");
CTRACE(ISC_LOG_DEBUG(3), "query_addns");
/*
* Initialization.
*/
@ -2752,21 +2776,24 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
*/
result = dns_message_gettempname(client->message, &name);
if (result != ISC_R_SUCCESS) {
CTRACE("query_addns: dns_message_gettempname failed: done");
CTRACE(ISC_LOG_DEBUG(3),
"query_addns: dns_message_gettempname failed: done");
return (result);
}
dns_name_init(name, NULL);
dns_name_clone(dns_db_origin(db), name);
rdataset = query_newrdataset(client);
if (rdataset == NULL) {
CTRACE("query_addns: query_newrdataset failed");
CTRACE(ISC_LOG_ERROR,
"query_addns: query_newrdataset failed");
eresult = DNS_R_SERVFAIL;
goto cleanup;
}
if (WANTDNSSEC(client) && dns_db_issecure(db)) {
sigrdataset = query_newrdataset(client);
if (sigrdataset == NULL) {
CTRACE("query_addns: query_newrdataset failed");
CTRACE(ISC_LOG_ERROR,
"query_addns: query_newrdataset failed");
eresult = DNS_R_SERVFAIL;
goto cleanup;
}
@ -2781,14 +2808,15 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
dns_rdatatype_ns, 0, client->now,
rdataset, sigrdataset);
} else {
CTRACE("query_addns: calling dns_db_find");
CTRACE(ISC_LOG_DEBUG(3), "query_addns: calling dns_db_find");
result = dns_db_findext(db, name, NULL, dns_rdatatype_ns,
client->query.dboptions, 0, &node,
fname, &cm, &ci, rdataset, sigrdataset);
CTRACE("query_addns: dns_db_find complete");
CTRACE(ISC_LOG_DEBUG(3), "query_addns: dns_db_find complete");
}
if (result != ISC_R_SUCCESS) {
CTRACE("query_addns: "
CTRACE(ISC_LOG_ERROR,
"query_addns: "
"dns_db_findrdataset or dns_db_find failed");
/*
* This is bad. We tried to get the NS rdataset at the zone
@ -2805,7 +2833,7 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
}
cleanup:
CTRACE("query_addns: cleanup");
CTRACE(ISC_LOG_DEBUG(3), "query_addns: cleanup");
query_putrdataset(client, &rdataset);
if (sigrdataset != NULL)
query_putrdataset(client, &sigrdataset);
@ -2814,7 +2842,7 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
if (node != NULL)
dns_db_detachnode(db, &node);
CTRACE("query_addns: done");
CTRACE(ISC_LOG_DEBUG(3), "query_addns: done");
return (eresult);
}
@ -3082,7 +3110,7 @@ query_addbestns(ns_client_t *client) {
dns_clientinfomethods_t cm;
dns_clientinfo_t ci;
CTRACE("query_addbestns");
CTRACE(ISC_LOG_DEBUG(3), "query_addbestns");
fname = NULL;
zfname = NULL;
rdataset = NULL;
@ -3287,7 +3315,7 @@ query_addds(ns_client_t *client, dns_db_t *db, dns_dbnode_t *node,
isc_result_t result;
unsigned int count;
CTRACE("query_addds");
CTRACE(ISC_LOG_DEBUG(3), "query_addds");
rname = NULL;
rdataset = NULL;
sigrdataset = NULL;
@ -3417,7 +3445,7 @@ query_addwildcardproof(ns_client_t *client, dns_db_t *db,
dns_clientinfomethods_t cm;
dns_clientinfo_t ci;
CTRACE("query_addwildcardproof");
CTRACE(ISC_LOG_DEBUG(3), "query_addwildcardproof");
fname = NULL;
rdataset = NULL;
sigrdataset = NULL;
@ -3781,9 +3809,10 @@ query_resume(isc_task_t *task, isc_event_t *event) {
if (devent->sigrdataset != NULL)
query_putrdataset(client, &devent->sigrdataset);
isc_event_free(&event);
if (fetch_canceled)
if (fetch_canceled) {
CTRACE(ISC_LOG_ERROR, "fetch cancelled");
query_error(client, DNS_R_SERVFAIL, __LINE__);
else
} else
query_next(client, ISC_R_CANCELED);
/*
* This may destroy the client.
@ -4047,8 +4076,11 @@ rpz_ready(ns_client_t *client, dns_rdataset_t **rdatasetp)
if (*rdatasetp == NULL) {
*rdatasetp = query_newrdataset(client);
if (*rdatasetp == NULL)
if (*rdatasetp == NULL) {
CTRACE(ISC_LOG_ERROR,
"rpz_ready: query_newrdataset failed");
return (DNS_R_SERVFAIL);
}
} else if (dns_rdataset_isassociated(*rdatasetp)) {
dns_rdataset_disassociate(*rdatasetp);
}
@ -4187,6 +4219,7 @@ rpz_rrset_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type,
st->r.r_rdataset = NULL;
result = st->r.r_result;
if (result == DNS_R_DELEGATION) {
CTRACE(ISC_LOG_ERROR, "RPZ recursing");
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name,
rpz_type, " rpz_rrset_find(1)", result);
st->m.policy = DNS_RPZ_POLICY_ERROR;
@ -4372,8 +4405,10 @@ rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype,
*/
rpz_clean(zonep, dbp, nodep, rdatasetp);
result = rpz_ready(client, rdatasetp);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
CTRACE(ISC_LOG_ERROR, "rpz_ready() failed");
return (DNS_R_SERVFAIL);
}
*versionp = NULL;
result = rpz_getdb(client, p_name, rpz_type, zonep, dbp, versionp);
if (result != ISC_R_SUCCESS)
@ -4396,6 +4431,8 @@ rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype,
if (result != ISC_R_SUCCESS) {
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name,
rpz_type, " allrdatasets()", result);
CTRACE(ISC_LOG_ERROR,
"rpz_find_p: allrdatasets failed");
return (DNS_R_SERVFAIL);
}
for (result = dns_rdatasetiter_first(rdsiter);
@ -4413,6 +4450,9 @@ rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype,
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
p_name, rpz_type,
" rdatasetiter", result);
CTRACE(ISC_LOG_ERROR,
"rpz_find_p: rdatasetiter_destroy "
"failed");
return (DNS_R_SERVFAIL);
}
/*
@ -4467,6 +4507,8 @@ rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype,
default:
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type,
"", result);
CTRACE(ISC_LOG_ERROR,
"rpz_find_p: unexpected result");
return (DNS_R_SERVFAIL);
}
}
@ -4696,6 +4738,8 @@ rpz_rewrite_ip_rrset(ns_client_t *client,
rpz_type, " NS address rewrite rrset",
result);
}
CTRACE(ISC_LOG_ERROR,
"rpz_rewrite_ip_rrset: unexpected result");
return (DNS_R_SERVFAIL);
}
@ -5330,6 +5374,7 @@ cleanup:
rpz_match_clear(st);
}
if (st->m.policy == DNS_RPZ_POLICY_ERROR) {
CTRACE(ISC_LOG_ERROR, "SERVFAIL due to RPZ policy");
st->m.type = DNS_RPZ_TYPE_BAD;
result = DNS_R_SERVFAIL;
}
@ -5563,7 +5608,7 @@ query_addnoqnameproof(ns_client_t *client, dns_rdataset_t *rdataset) {
dns_rdataset_t *neg, *negsig;
isc_result_t result = ISC_R_NOMEMORY;
CTRACE("query_addnoqnameproof");
CTRACE(ISC_LOG_DEBUG(3), "query_addnoqnameproof");
fname = NULL;
neg = NULL;
@ -5977,7 +6022,7 @@ redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
dns_clientinfo_t ci;
ns_dbversion_t *dbversion;
CTRACE("redirect");
CTRACE(ISC_LOG_DEBUG(3), "redirect");
if (client->view->redirect == NULL)
return (ISC_FALSE);
@ -6044,7 +6089,7 @@ redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset,
dns_db_detach(&db);
return (ISC_FALSE);
}
CTRACE("redirect: found data: done");
CTRACE(ISC_LOG_DEBUG(3), "redirect: found data: done");
dns_name_copy(found, name, NULL);
if (dns_rdataset_isassociated(rdataset))
@ -6109,11 +6154,12 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
isc_boolean_t nxrewrite = ISC_FALSE;
dns_clientinfomethods_t cm;
dns_clientinfo_t ci;
char errmsg[256];
isc_boolean_t associated;
dns_section_t section;
dns_ttl_t ttl;
CTRACE("query_find");
CTRACE(ISC_LOG_DEBUG(3), "query_find");
/*
* One-time initialization.
@ -6205,11 +6251,15 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
*/
dbuf = query_getnamebuf(client);
if (dbuf == NULL) {
CTRACE(ISC_LOG_ERROR,
"query_find: query_getnamebuf failed (1)");
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
fname = query_newname(client, dbuf, &b);
if (fname == NULL) {
CTRACE(ISC_LOG_ERROR,
"query_find: query_newname failed (1)");
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
@ -6221,6 +6271,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
}
result = dns_name_copy(tname, fname, NULL);
if (result != ISC_R_SUCCESS) {
CTRACE(ISC_LOG_ERROR,
"query_find: dns_name_copy failed");
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
@ -6249,7 +6301,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
type = qtype;
restart:
CTRACE("query_find: restart");
CTRACE(ISC_LOG_DEBUG(3), "query_find: restart");
want_restart = ISC_FALSE;
authoritative = ISC_FALSE;
version = NULL;
@ -6326,8 +6378,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
inc_stats(client, dns_nsstatscounter_authrej);
if (!PARTIALANSWER(client))
QUERY_ERROR(DNS_R_REFUSED);
} else
} else {
CTRACE(ISC_LOG_ERROR,
"query_find: query_getdb failed");
QUERY_ERROR(DNS_R_SERVFAIL);
}
goto cleanup;
}
@ -6360,24 +6415,30 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
}
db_find:
CTRACE("query_find: db_find");
CTRACE(ISC_LOG_DEBUG(3), "query_find: db_find");
/*
* We'll need some resources...
*/
dbuf = query_getnamebuf(client);
if (dbuf == NULL) {
CTRACE(ISC_LOG_ERROR,
"query_find: query_getnamebuf failed (2)");
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
fname = query_newname(client, dbuf, &b);
rdataset = query_newrdataset(client);
if (fname == NULL || rdataset == NULL) {
CTRACE(ISC_LOG_ERROR,
"query_find: query_newname failed (2)");
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
if (WANTDNSSEC(client) && (!is_zone || dns_db_issecure(db))) {
sigrdataset = query_newrdataset(client);
if (sigrdataset == NULL) {
CTRACE(ISC_LOG_ERROR,
"query_find: query_newrdataset failed (2)");
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
@ -6394,7 +6455,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
dns_cache_updatestats(client->view->cache, result);
resume:
CTRACE("query_find: resume");
CTRACE(ISC_LOG_DEBUG(3), "query_find: resume");
/*
* Rate limit these responses to this client.
@ -6759,6 +6820,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
goto cleanup;
} else {
/* Unable to give root server referral. */
CTRACE(ISC_LOG_ERROR,
"unable to give root server referral");
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
@ -7025,11 +7088,17 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
if (fname == NULL) {
dbuf = query_getnamebuf(client);
if (dbuf == NULL) {
CTRACE(ISC_LOG_ERROR,
"query_find: "
"query_getnamebuf failed (3)");
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
fname = query_newname(client, dbuf, &b);
if (fname == NULL) {
CTRACE(ISC_LOG_ERROR,
"query_find: "
"query_newname failed (3)");
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
@ -7128,6 +7197,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
if (fname == NULL ||
rdataset == NULL ||
sigrdataset == NULL) {
CTRACE(ISC_LOG_ERROR,
"query_find: "
"failure getting "
"closest encloser");
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
@ -7306,11 +7379,17 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
if (fname == NULL) {
dbuf = query_getnamebuf(client);
if (dbuf == NULL) {
CTRACE(ISC_LOG_ERROR,
"query_find: "
"query_getnamebuf failed (4)");
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
fname = query_newname(client, dbuf, &b);
if (fname == NULL) {
CTRACE(ISC_LOG_ERROR,
"query_find: "
"query_newname failed (4)");
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
@ -7567,6 +7646,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
/*
* Something has gone wrong.
*/
snprintf(errmsg, sizeof(errmsg) - 1,
"query_find: unexpected error after resuming: %s",
isc_result_totext(result));
CTRACE(ISC_LOG_ERROR, errmsg);
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
@ -7625,6 +7708,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
rdsiter = NULL;
result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
if (result != ISC_R_SUCCESS) {
CTRACE(ISC_LOG_ERROR,
"query_find: type any; allrdatasets failed");
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
@ -7759,12 +7844,18 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
dns_rdatasetiter_destroy(&rdsiter);
fname = query_newname(client, dbuf, &b);
goto nxrrset_rrsig;
} else
} else {
CTRACE(ISC_LOG_ERROR,
"query_find: no matching rdatasets "
"in cache");
result = DNS_R_SERVFAIL;
}
}
dns_rdatasetiter_destroy(&rdsiter);
if (result != ISC_R_NOMORE) {
CTRACE(ISC_LOG_ERROR,
"query_find: dns_rdatasetiter_destroy failed");
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
@ -7988,7 +8079,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
}
addauth:
CTRACE("query_find: addauth");
CTRACE(ISC_LOG_DEBUG(3), "query_find: addauth");
/*
* Add NS records to the authority section (if we haven't already
* added them to the answer section).
@ -8016,7 +8107,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
dns_fixedname_name(&wildcardname),
ISC_TRUE, ISC_FALSE);
cleanup:
CTRACE("query_find: cleanup");
CTRACE(ISC_LOG_DEBUG(3), "query_find: cleanup");
/*
* General cleanup.
*/
@ -8124,7 +8215,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
query_send(client);
ns_client_detach(&client);
}
CTRACE("query_find: done");
CTRACE(ISC_LOG_DEBUG(3), "query_find: done");
return (eresult);
}
@ -8212,7 +8303,7 @@ ns_query_start(ns_client_t *client) {
unsigned int saved_extflags = client->extflags;
unsigned int saved_flags = client->message->flags;
CTRACE("ns_query_start");
CTRACE(ISC_LOG_DEBUG(3), "ns_query_start");
/*
* Test only.

View File

@ -80,11 +80,13 @@
DNS_LOGMODULE_RESOLVER, \
ISC_LOG_DEBUG(3), \
"res %p: %s", (r), (m))
#define FCTXTRACE(m) isc_log_write(dns_lctx, \
#define FCTXTRACE(m) \
isc_log_write(dns_lctx, \
DNS_LOGCATEGORY_RESOLVER, \
DNS_LOGMODULE_RESOLVER, \
ISC_LOG_DEBUG(3), \
"fctx %p(%s): %s", fctx, fctx->info, (m))
"fctx %p(%s): %s", \
fctx, fctx->info, (m))
#define FCTXTRACE2(m1, m2) \
isc_log_write(dns_lctx, \
DNS_LOGCATEGORY_RESOLVER, \
@ -92,6 +94,22 @@
ISC_LOG_DEBUG(3), \
"fctx %p(%s): %s %s", \
fctx, fctx->info, (m1), (m2))
#define FCTXTRACE3(m, res) \
isc_log_write(dns_lctx, \
DNS_LOGCATEGORY_RESOLVER, \
DNS_LOGMODULE_RESOLVER, \
ISC_LOG_DEBUG(3), \
"fctx %p(%s): [result: %s] %s", \
fctx, fctx->info, \
isc_result_totext(res), (m))
#define FCTXTRACE4(m1, m2, res) \
isc_log_write(dns_lctx, \
DNS_LOGCATEGORY_RESOLVER, \
DNS_LOGMODULE_RESOLVER, \
ISC_LOG_DEBUG(3), \
"fctx %p(%s): [result: %s] %s %s", \
fctx, fctx->info, \
isc_result_totext(res), (m1), (m2))
#define FTRACE(m) isc_log_write(dns_lctx, \
DNS_LOGCATEGORY_RESOLVER, \
DNS_LOGMODULE_RESOLVER, \
@ -1268,6 +1286,9 @@ process_sendevent(resquery_t *query, isc_event_t *event) {
case ISC_R_NOPERM:
case ISC_R_ADDRNOTAVAIL:
case ISC_R_CONNREFUSED:
FCTXTRACE3("query canceled in sendevent(): "
"no route to host; no response",
sevent->result);
/*
* No route to remote.
@ -1279,6 +1300,10 @@ process_sendevent(resquery_t *query, isc_event_t *event) {
break;
default:
FCTXTRACE3("query canceled in sendevent() due to "
"unexpected event result; responding",
sevent->result);
fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
break;
}
@ -2359,6 +2384,9 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
isc_interval_set(&interval, 20, 0);
result = fctx_startidletimer(query->fctx, &interval);
if (result != ISC_R_SUCCESS) {
FCTXTRACE("query canceled: idle timer failed; "
"responding");
fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
fctx_done(fctx, result, __LINE__);
break;
@ -2395,6 +2423,9 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
result = resquery_send(query);
if (result != ISC_R_SUCCESS) {
FCTXTRACE("query canceled: "
"resquery_send() failed; responding");
fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
fctx_done(fctx, result, __LINE__);
}
@ -2406,6 +2437,10 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
case ISC_R_NOPERM:
case ISC_R_ADDRNOTAVAIL:
case ISC_R_CONNECTIONRESET:
FCTXTRACE3("query canceled in connected(): "
"no route to host; no response",
sevent->result);
/*
* No route to remote.
*/
@ -2415,6 +2450,10 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
break;
default:
FCTXTRACE3("query canceled in connected() due to "
"unexpected event result; responding",
sevent->result);
isc_socket_detach(&query->tcpsocket);
fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
break;
@ -2495,11 +2534,12 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) {
isc_event_free(&event);
dns_adb_destroyfind(&find);
if (want_try)
if (want_try) {
fctx_try(fctx, ISC_TRUE, ISC_FALSE);
else if (want_done)
} else if (want_done) {
FCTXTRACE("fetch failed in finddone(); return ISC_R_FAILURE");
fctx_done(fctx, ISC_R_FAILURE, __LINE__);
else if (destroy) {
} else if (destroy) {
fctx_destroy(fctx);
if (bucket_empty)
empty_bucket(res);
@ -3479,6 +3519,7 @@ fctx_timeout(isc_task_t *task, isc_event_t *event) {
fctx->timeouts++;
fctx->timeout = ISC_TRUE;
/*
* We could cancel the running queries here, or we could let
* them keep going. Since we normally use separate sockets for
@ -3490,10 +3531,13 @@ fctx_timeout(isc_task_t *task, isc_event_t *event) {
*/
query = ISC_LIST_HEAD(fctx->queries);
if (query != NULL &&
isc_time_compare(&tevent->due, &query->start) >= 0) {
isc_time_compare(&tevent->due, &query->start) >= 0)
{
FCTXTRACE("query timed out; no response");
fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
}
fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
/*
* Our timer has triggered. Reestablish the fctx lifetime
* timer.
@ -3777,7 +3821,6 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
unsigned int findoptions = 0;
char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE];
char typebuf[DNS_RDATATYPE_FORMATSIZE];
dns_name_t suffix;
isc_mem_t *mctx;
/*
@ -3789,6 +3832,11 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
fctx = isc_mem_get(mctx, sizeof(*fctx));
if (fctx == NULL)
return (ISC_R_NOMEMORY);
/*
* Make fctx->info point to a copy of a formatted string
* "name/type".
*/
dns_name_format(name, buf, sizeof(buf));
dns_rdatatype_format(type, typebuf, sizeof(typebuf));
strcat(buf, "/"); /* checked */
@ -3798,6 +3846,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
result = ISC_R_NOMEMORY;
goto cleanup_fetch;
}
FCTXTRACE("create");
dns_name_init(&fctx->name, NULL);
result = dns_name_dup(name, mctx, &fctx->name);
@ -3870,10 +3919,12 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
dns_forwarders_t *forwarders = NULL;
unsigned int labels;
dns_name_t *fwdname = name;
dns_name_t suffix;
/*
* DS records are found in the parent server.
* Strip label to get the correct forwarder (if any).
* DS records are found in the parent server. Strip one
* leading label from the name (to be used in finding
* the forwarder).
*/
if (dns_rdatatype_atparent(fctx->type) &&
dns_name_countlabels(name) > 1) {
@ -3882,6 +3933,8 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
fwdname = &suffix;
}
/* Find the forwarder for this name. */
dns_fixedname_init(&fixed);
domain = dns_fixedname_name(&fixed);
result = dns_fwdtable_find2(fctx->res->view->fwdtable, fwdname,
@ -7170,6 +7223,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
if (fctx->res->exiting) {
result = ISC_R_SHUTTINGDOWN;
FCTXTRACE("resolver shutting down");
goto done;
}
@ -7224,6 +7278,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
no_response = ISC_TRUE;
}
}
FCTXTRACE3("dispatcher failure", devent->result);
goto done;
}
@ -7231,14 +7286,18 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
if (query->tsig != NULL) {
result = dns_message_setquerytsig(message, query->tsig);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
FCTXTRACE3("unable to set query tsig", result);
goto done;
}
}
if (query->tsigkey) {
result = dns_message_settsigkey(message, query->tsigkey);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
FCTXTRACE3("unable to set tsig key", result);
goto done;
}
}
if ((options & DNS_FETCHOPT_TCP) == 0) {
@ -7250,6 +7309,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
}
result = dns_message_parse(message, &devent->buffer, 0);
if (result != ISC_R_SUCCESS) {
FCTXTRACE3("message failed to parse", result);
switch (result) {
case ISC_R_UNEXPECTEDEND:
if (!message->question_ok ||
@ -7338,6 +7398,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
*/
resend = ISC_TRUE;
/* XXXMPA log it */
FCTXTRACE("bad sit");
goto done;
}
#endif
@ -7348,8 +7409,10 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
* returns success anyway.
*/
result = dns_message_checksig(message, fctx->res->view);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
FCTXTRACE3("signature check failed", result);
goto done;
}
/*
* The dispatcher should ensure we only get responses with QR set.
@ -7453,6 +7516,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
options |= DNS_FETCHOPT_TCP;
resend = ISC_TRUE;
}
FCTXTRACE3("message truncated", result);
goto done;
}
@ -7463,6 +7527,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
/* XXXRTH Log */
broken_server = DNS_R_UNEXPECTEDOPCODE;
keep_trying = ISC_TRUE;
FCTXTRACE("invalid message opcode");
goto done;
}
@ -7497,6 +7562,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
*/
if (message->rcode != dns_rcode_noerror &&
message->rcode != dns_rcode_nxdomain) {
isc_buffer_t b;
char code[64];
#ifdef ISC_PLATFORM_USESIT
unsigned char sit[64];
@ -7623,6 +7690,11 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
INSIST(broken_server != ISC_R_SUCCESS);
keep_trying = ISC_TRUE;
}
isc_buffer_init(&b, code, sizeof(code) - 1);
dns_rcode_totext(fctx->rmessage->rcode, &b);
code[isc_buffer_usedlength(&b)] = '\0';
FCTXTRACE2("remote server broken: returned ", code);
goto done;
}
@ -7634,6 +7706,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
/* XXXRTH Log */
if (result == DNS_R_FORMERR)
keep_trying = ISC_TRUE;
FCTXTRACE3("response did not match question", result);
goto done;
}
@ -7654,6 +7727,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
isc_result_totext(result));
broken_server = DNS_R_LAME;
keep_trying = ISC_TRUE;
FCTXTRACE("lame server");
goto done;
}
@ -7706,22 +7780,32 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
*/
if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 ||
ISFORWARDER(query->addrinfo))
{
result = answer_response(fctx);
else if (iscname(fctx) &&
if (result != ISC_R_SUCCESS)
FCTXTRACE3("answer_response (AA/fwd)", result);
} else if (iscname(fctx) &&
fctx->type != dns_rdatatype_any &&
fctx->type != dns_rdatatype_cname) {
fctx->type != dns_rdatatype_cname)
{
/*
* A BIND8 server could return a non-authoritative
* answer when a CNAME is followed. We should treat
* it as a valid answer.
*/
result = answer_response(fctx);
if (result != ISC_R_SUCCESS)
FCTXTRACE3("answer_response (!ANY/!CNAME)",
result);
} else if (fctx->type != dns_rdatatype_ns &&
!betterreferral(fctx)) {
/*
* Lame response !!!.
*/
result = answer_response(fctx);
if (result != ISC_R_SUCCESS)
FCTXTRACE("answer_response (!NS)");
FCTXTRACE3("answer_response (!NS)", result);
} else {
if (fctx->type == dns_rdatatype_ns) {
/*
@ -7734,6 +7818,9 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
*/
result = noanswer_response(fctx, NULL,
LOOK_FOR_NS_IN_ANSWER);
if (result != ISC_R_SUCCESS)
FCTXTRACE3("noanswer_response (NS)",
result);
} else {
/*
* Some other servers may still somehow include
@ -7749,6 +7836,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
*/
result = noanswer_response(fctx, NULL,
LOOK_FOR_GLUE_IN_ANSWER);
if (result != ISC_R_SUCCESS)
FCTXTRACE3("noanswer_response", result);
}
if (result != DNS_R_DELEGATION) {
/*
@ -7813,6 +7902,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
*/
if (result == DNS_R_FORMERR)
keep_trying = ISC_TRUE;
FCTXTRACE3("noanswer_response", result);
goto done;
}
} else {
@ -7822,6 +7912,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
/* XXXRTH Log */
broken_server = DNS_R_UNEXPECTEDRCODE;
keep_trying = ISC_TRUE;
FCTXTRACE("broken server: unexpected rcode");
goto done;
}
@ -7836,8 +7927,10 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
*/
if (WANTCACHE(fctx)) {
result = cache_message(fctx, query->addrinfo, now);
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
FCTXTRACE3("cache_message complete", result);
goto done;
}
}
/*
@ -7855,6 +7948,8 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
* Cache any negative cache entries in the message.
*/
result = ncache_message(fctx, query->addrinfo, covers, now);
if (result != ISC_R_SUCCESS)
FCTXTRACE3("ncache_message complete", result);
}
done:
@ -7864,6 +7959,10 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
*/
addrinfo = query->addrinfo;
FCTXTRACE4("query canceled in response(); ",
no_response ? "no response" : "responding",
result);
/*
* Cancel the query.
*
@ -8616,6 +8715,10 @@ log_fetch(dns_name_t *name, dns_rdatatype_t type) {
char typebuf[DNS_RDATATYPE_FORMATSIZE];
int level = ISC_LOG_DEBUG(1);
/*
* If there's no chance of logging it, don't render (format) the
* name and RDATA type (further below), and return early.
*/
if (! isc_log_wouldlog(dns_lctx, level))
return;
@ -9022,6 +9125,11 @@ dns_resolver_flushbadcache(dns_resolver_t *resolver, dns_name_t *name) {
unsigned int i;
dns_badcache_t *bad, *prev, *next;
/*
* Drop all entries that match the name, and also all expired
* entries from the badcache.
*/
REQUIRE(VALID_RESOLVER(resolver));
LOCK(&resolver->lock);
@ -9066,6 +9174,8 @@ dns_resolver_flushbadnames(dns_resolver_t *resolver, dns_name_t *name) {
isc_time_t now;
isc_result_t result;
/* Drop all expired entries from the badcache. */
REQUIRE(VALID_RESOLVER(resolver));
REQUIRE(name != NULL);
@ -9105,6 +9215,13 @@ resizehash(dns_resolver_t *resolver, isc_time_t *now, isc_boolean_t grow) {
dns_badcache_t **new, *bad, *next;
unsigned int i;
/*
* The number of buckets in the hashtable is modified in this
* function. Afterwards, all the entries are remapped into the
* corresponding new slot. Rehashing (hash computation) is
* unnecessary as the hash values had been saved.
*/
if (grow)
newsize = resolver->badhash * 2 + 1;
else
@ -9115,6 +9232,13 @@ resizehash(dns_resolver_t *resolver, isc_time_t *now, isc_boolean_t grow) {
if (new == NULL)
return;
memset(new, 0, sizeof(*resolver->badcache) * newsize);
/*
* Because the hashtable implements a simple modulus mapping
* from hash to bucket (no extendible hashing is used), every
* name in the hashtable has to be remapped to its new slot.
* Entries that have expired (time) are dropped.
*/
for (i = 0; i < resolver->badhash; i++) {
for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
next = bad->next;
@ -9143,6 +9267,18 @@ dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name,
unsigned int i, hashval;
dns_badcache_t *bad, *prev, *next;
/*
* The badcache is implemented as a hashtable keyed on the name,
* and each bucket slot points to a linked list (separate
* chaining).
*
* To avoid long list chains, if the number of entries in the
* hashtable goes over number-of-buckets * 8, the
* number-of-buckets is doubled. Similarly, if the number of
* entries goes below number-of-buckets * 2, the number-of-buckets
* is halved. See resizehash().
*/
REQUIRE(VALID_RESOLVER(resolver));
LOCK(&resolver->lock);
@ -9167,6 +9303,7 @@ dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name,
next = bad->next;
if (bad->type == type && dns_name_equal(name, &bad->name))
break;
/* Drop expired entries when walking the chain. */
if (isc_time_compare(&bad->expire, &now) < 0) {
if (prev == NULL)
resolver->badcache[i] = bad->next;
@ -9179,6 +9316,12 @@ dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name,
prev = bad;
}
if (bad == NULL) {
/*
* Insert the name into the badcache hashtable at the
* head of the linked list at the appropriate slot. The
* name data follows right after the allocation for the
* linked list node.
*/
isc_buffer_t buffer;
bad = isc_mem_get(resolver->mctx, sizeof(*bad) + name->length);
if (bad == NULL)
@ -9337,6 +9480,12 @@ dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
isc_result_t result;
dns_rbtnode_t *node = NULL;
/*
* Whether an algorithm is disabled (or not) is stored in a
* per-name bitfield that is stored as the node data of an
* RBT.
*/
REQUIRE(VALID_RESOLVER(resolver));
if (alg > 255)
return (ISC_R_RANGE);
@ -9358,7 +9507,17 @@ dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
algorithms = node->data;
/*
* If algorithms is set, algorithms[0] contains its
* length.
*/
if (algorithms == NULL || len > *algorithms) {
/*
* If no bitfield exists in the node data, or if
* it is not long enough, allocate a new
* bitfield and copy the old (smaller) bitfield
* into it if one exists.
*/
new = isc_mem_get(resolver->mctx, len);
if (new == NULL) {
result = ISC_R_NOMEMORY;
@ -9368,8 +9527,10 @@ dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
if (algorithms != NULL)
memmove(new, algorithms, *algorithms);
new[len-1] |= mask;
/* new[0] should contain the length of new. */
*new = len;
node->data = new;
/* Free the older bitfield. */
if (algorithms != NULL)
isc_mem_put(resolver->mctx, algorithms,
*algorithms);
@ -9451,6 +9612,11 @@ dns_resolver_disable_ds_digest(dns_resolver_t *resolver, dns_name_t *name,
isc_result_t result;
dns_rbtnode_t *node = NULL;
/*
* Whether a digest is disabled (or not) is stored in a per-name
* bitfield that is stored as the node data of an RBT.
*/
REQUIRE(VALID_RESOLVER(resolver));
if (digest_type > 255)
return (ISC_R_RANGE);
@ -9472,7 +9638,14 @@ dns_resolver_disable_ds_digest(dns_resolver_t *resolver, dns_name_t *name,
if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
digests = node->data;
/* If digests is set, digests[0] contains its length. */
if (digests == NULL || len > *digests) {
/*
* If no bitfield exists in the node data, or if
* it is not long enough, allocate a new
* bitfield and copy the old (smaller) bitfield
* into it if one exists.
*/
new = isc_mem_get(resolver->mctx, len);
if (new == NULL) {
result = ISC_R_NOMEMORY;
@ -9482,8 +9655,10 @@ dns_resolver_disable_ds_digest(dns_resolver_t *resolver, dns_name_t *name,
if (digests != NULL)
memmove(new, digests, *digests);
new[len-1] |= mask;
/* new[0] should contain the length of new. */
*new = len;
node->data = new;
/* Free the older bitfield. */
if (digests != NULL)
isc_mem_put(resolver->mctx, digests,
*digests);