aboutsummaryrefslogtreecommitdiff
path: root/bin/named/query.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/named/query.c')
-rw-r--r--bin/named/query.c68
1 files changed, 56 insertions, 12 deletions
diff --git a/bin/named/query.c b/bin/named/query.c
index ffd9b3554a76..602948497a4f 100644
--- a/bin/named/query.c
+++ b/bin/named/query.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: query.c,v 1.313.20.7 2009/03/13 01:38:51 marka Exp $ */
+/* $Id: query.c,v 1.313.20.7.12.1 2009/11/18 23:58:04 marka Exp $ */
/*! \file */
@@ -116,6 +116,8 @@
#define DNS_GETDB_NOLOG 0x02U
#define DNS_GETDB_PARTIAL 0x04U
+#define PENDINGOK(x) (((x) & DNS_DBFIND_PENDINGOK) != 0)
+
typedef struct client_additionalctx {
ns_client_t *client;
dns_rdataset_t *rdataset;
@@ -1761,8 +1763,8 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
*/
if (result == ISC_R_SUCCESS &&
additionaltype == dns_rdatasetadditional_fromcache &&
- (rdataset->trust == dns_trust_pending ||
- rdataset->trust == dns_trust_glue) &&
+ (DNS_TRUST_PENDING(rdataset->trust) ||
+ DNS_TRUST_GLUE(rdataset->trust)) &&
!validate(client, db, fname, rdataset, sigrdataset)) {
dns_rdataset_disassociate(rdataset);
if (dns_rdataset_isassociated(sigrdataset))
@@ -1801,8 +1803,8 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
*/
if (result == ISC_R_SUCCESS &&
additionaltype == dns_rdatasetadditional_fromcache &&
- (rdataset->trust == dns_trust_pending ||
- rdataset->trust == dns_trust_glue) &&
+ (DNS_TRUST_PENDING(rdataset->trust) ||
+ DNS_TRUST_GLUE(rdataset->trust)) &&
!validate(client, db, fname, rdataset, sigrdataset)) {
dns_rdataset_disassociate(rdataset);
if (dns_rdataset_isassociated(sigrdataset))
@@ -2601,14 +2603,14 @@ query_addbestns(ns_client_t *client) {
/*
* Attempt to validate RRsets that are pending or that are glue.
*/
- if ((rdataset->trust == dns_trust_pending ||
- (sigrdataset != NULL && sigrdataset->trust == dns_trust_pending))
+ if ((DNS_TRUST_PENDING(rdataset->trust) ||
+ (sigrdataset != NULL && DNS_TRUST_PENDING(sigrdataset->trust)))
&& !validate(client, db, fname, rdataset, sigrdataset) &&
- (client->query.dboptions & DNS_DBFIND_PENDINGOK) == 0)
+ !PENDINGOK(client->query.dboptions))
goto cleanup;
- if ((rdataset->trust == dns_trust_glue ||
- (sigrdataset != NULL && sigrdataset->trust == dns_trust_glue)) &&
+ if ((DNS_TRUST_GLUE(rdataset->trust) ||
+ (sigrdataset != NULL && DNS_TRUST_GLUE(sigrdataset->trust))) &&
!validate(client, db, fname, rdataset, sigrdataset) &&
SECURE(client) && WANTDNSSEC(client))
goto cleanup;
@@ -3716,6 +3718,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
dns_rdataset_t *noqname;
isc_boolean_t resuming;
int line = -1;
+ dns_rdataset_t tmprdataset;
+ unsigned int dboptions;
CTRACE("query_find");
@@ -3933,9 +3937,49 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
/*
* Now look for an answer in the database.
*/
+ dboptions = client->query.dboptions;
+ if (sigrdataset == NULL && client->view->enablednssec) {
+ /*
+ * If the client doesn't want DNSSEC we still want to
+ * look for any data pending validation to save a remote
+ * lookup if possible.
+ */
+ dns_rdataset_init(&tmprdataset);
+ sigrdataset = &tmprdataset;
+ dboptions |= DNS_DBFIND_PENDINGOK;
+ }
+ refind:
result = dns_db_find(db, client->query.qname, version, type,
- client->query.dboptions, client->now,
- &node, fname, rdataset, sigrdataset);
+ dboptions, client->now, &node, fname,
+ rdataset, sigrdataset);
+ /*
+ * If we have found pending data try to validate it.
+ * If the data does not validate as secure and we can't
+ * use the unvalidated data requery the database with
+ * pending disabled to prevent infinite looping.
+ */
+ if (result != ISC_R_SUCCESS || !DNS_TRUST_PENDING(rdataset->trust))
+ goto validation_done;
+ if (validate(client, db, fname, rdataset, sigrdataset))
+ goto validation_done;
+ if (rdataset->trust != dns_trust_pending_answer ||
+ !PENDINGOK(client->query.dboptions)) {
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ if (sigrdataset == &tmprdataset)
+ sigrdataset = NULL;
+ dns_db_detachnode(db, &node);
+ dboptions &= ~DNS_DBFIND_PENDINGOK;
+ goto refind;
+ }
+ validation_done:
+ if (sigrdataset == &tmprdataset) {
+ if (dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ sigrdataset = NULL;
+ }
resume:
CTRACE("query_find: resume");