bind - Upgraded vendor branch to 9.5.2-P1
[dragonfly.git] / contrib / bind-9.5.2 / bin / named / query.c
index 08dc9c3..9565eb6 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: query.c,v 1.298.48.15 2009/09/16 22:28:52 marka Exp $ */
+/* $Id: query.c,v 1.298.48.15.2.1 2009/11/18 23:41:17 marka Exp $ */
 
 /*! \file */
 
 #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;
@@ -1744,8 +1746,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))
@@ -1784,8 +1786,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))
@@ -2570,14 +2572,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;
@@ -3387,6 +3389,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");
 
@@ -3603,9 +3607,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");