vendor/BIND: Update to 9.5.2-P3
authorJan Lentfer <Jan.Lentfer@web.de>
Mon, 29 Mar 2010 08:23:56 +0000 (10:23 +0200)
committerJan Lentfer <Jan.Lentfer@web.de>
Mon, 29 Mar 2010 09:03:57 +0000 (11:03 +0200)
21 files changed:
contrib/bind/CHANGES
contrib/bind/COPYRIGHT
contrib/bind/FAQ
contrib/bind/bin/named/server.c
contrib/bind/lib/dns/api
contrib/bind/lib/dns/include/dns/rdataset.h
contrib/bind/lib/dns/include/dns/resolver.h
contrib/bind/lib/dns/include/dns/result.h
contrib/bind/lib/dns/include/dns/validator.h
contrib/bind/lib/dns/ncache.c
contrib/bind/lib/dns/rbtdb.c
contrib/bind/lib/dns/rdatalist.c
contrib/bind/lib/dns/rdataset.c
contrib/bind/lib/dns/rdataslab.c
contrib/bind/lib/dns/resolver.c
contrib/bind/lib/dns/result.c
contrib/bind/lib/dns/sdb.c
contrib/bind/lib/dns/sdlz.c
contrib/bind/lib/dns/validator.c
contrib/bind/lib/dns/view.c
contrib/bind/version

index f89ca86..55f79e0 100644 (file)
@@ -1,3 +1,7 @@
+       --- 9.5.2-P3 released ---
+
+2852.  [bug]           Handle broken DNSSEC trust chains better. [RT #15619]
+
        --- 9.5.2-P2 released ---
 
 2831.  [security]      Do not attempt to validate or cache
index fe042aa..4e437f2 100644 (file)
@@ -1,4 +1,4 @@
-Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+Copyright (C) 2004-2010  Internet Systems Consortium, Inc. ("ISC")
 Copyright (C) 1996-2003  Internet Software Consortium.
 
 Permission to use, copy, modify, and/or distribute this software for any
@@ -13,7 +13,7 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 PERFORMANCE OF THIS SOFTWARE.
 
-$Id: COPYRIGHT,v 1.13.130.2 2009/01/05 23:46:51 tbox Exp $
+$Id: COPYRIGHT,v 1.13.130.2.2.1 2010/02/25 05:23:41 tbox Exp $
 
 Portions Copyright (C) 1996-2001  Nominum, Inc.
 
index b256ed8..9e3469c 100644 (file)
@@ -1,6 +1,6 @@
 Frequently Asked Questions about BIND 9
 
-Copyright © 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+Copyright © 2004-2010 Internet Systems Consortium, Inc. ("ISC")
 
 Copyright © 2000-2003 Internet Software Consortium.
 
@@ -784,6 +784,22 @@ A: Red Hat Security Enhanced Linux (SELinux) policy security protections :
    See these man-pages for more information : selinux(8), named_selinux
    (8), chcon(1), setsebool(8)
 
+Q: I'm running BIND on Ubuntu -
+
+   Why can't named update slave zone database files?
+
+   Why can't named create DDNS journal files or update the master zones
+   from journals?
+
+   Why can't named create custom log files?
+
+A: Ubuntu uses AppArmor <http://en.wikipedia.org/wiki/AppArmor> in
+   addition to normal file system permissions to protect the system.
+
+   Adjust the paths to use those specified in /etc/apparmor.d/
+   usr.sbin.named or adjust /etc/apparmor.d/usr.sbin.named to allow named
+   to write at the location specified in named.conf.
+
 Q: Listening on individual IPv6 interfaces does not work.
 
 A: This is usually due to "/proc/net/if_inet6" not being available in the
index d3fdb01..7812b16 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: server.c,v 1.495.10.29 2009/07/11 04:28:14 marka Exp $ */
+/* $Id: server.c,v 1.495.10.29.2.2 2010/02/25 10:56:00 tbox Exp $ */
 
 /*! \file */
 
@@ -4722,6 +4722,8 @@ dumpdone(void *arg, isc_result_t result) {
        }
        if (dctx->cache != NULL) {
                dns_adb_dump(dctx->view->view->adb, dctx->fp);
+               dns_resolver_printbadcache(dctx->view->view->resolver,
+                                          dctx->fp);
                dns_db_detach(&dctx->cache);
        }
        if (dctx->dumpzones) {
index 1099c30..75cda1d 100644 (file)
@@ -1,3 +1,3 @@
-LIBINTERFACE = 47
+LIBINTERFACE = 48
 LIBREVISION = 0
-LIBAGE = 0
+LIBAGE = 1
index 8a557b5..7fbd8d7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: rdataset.h,v 1.62.128.2 2009/01/19 23:47:03 tbox Exp $ */
+/* $Id: rdataset.h,v 1.62.128.2.2.2 2010/02/25 10:56:02 tbox Exp $ */
 
 #ifndef DNS_RDATASET_H
 #define DNS_RDATASET_H 1
@@ -104,6 +104,9 @@ typedef struct dns_rdatasetmethods {
                                                 dns_rdataset_t *rdataset,
                                                 dns_rdatasetadditional_t type,
                                                 dns_rdatatype_t qtype);
+       void                    (*settrust)(dns_rdataset_t *rdataset,
+                                           dns_trust_t trust);
+       void                    (*expire)(dns_rdataset_t *rdataset);
 } dns_rdatasetmethods_t;
 
 #define DNS_RDATASET_MAGIC            ISC_MAGIC('D','N','S','R')
@@ -592,6 +595,19 @@ dns_rdataset_putadditional(dns_acache_t *acache,
  *                       information for 'rdataset.'
  */
 
+void
+dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust);
+/*%<
+ * Set the trust of the 'rdataset' to trust in any in the backing database.
+ * The local trust level of 'rdataset' is also set.
+ */
+
+void
+dns_rdataset_expire(dns_rdataset_t *rdataset);
+/*%<
+ * Mark the rdataset to be expired in the backing database.
+ */
+
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_RDATASET_H */
index a1c51a0..0b457df 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: resolver.h,v 1.56.128.7 2009/01/29 22:41:45 jinmei Exp $ */
+/* $Id: resolver.h,v 1.56.128.7.2.2 2010/02/25 10:56:02 tbox Exp $ */
 
 #ifndef DNS_RESOLVER_H
 #define DNS_RESOLVER_H 1
@@ -508,6 +508,48 @@ dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state);
 unsigned int
 dns_resolver_getoptions(dns_resolver_t *resolver);
 
+void
+dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name,
+                        dns_rdatatype_t type, isc_time_t *expire);
+/*%<
+ * Add a entry to the bad cache for <name,type> that will expire at 'expire'.
+ *
+ * Requires:
+ * \li resolver to be valid.
+ * \li name to be valid.
+ */
+
+isc_boolean_t
+dns_resolver_getbadcache(dns_resolver_t *resolver, dns_name_t *name,
+                        dns_rdatatype_t type, isc_time_t *now);
+/*%<
+ * Check to see if there is a unexpired entry in the bad cache for
+ * <name,type>.
+ *
+ * Requires:
+ * \li resolver to be valid.
+ * \li name to be valid.
+ */
+
+void
+dns_resolver_flushbadcache(dns_resolver_t *resolver, dns_name_t *name);
+/*%<
+ * Flush the bad cache of all entries at 'name' if 'name' is non NULL.
+ * Flush the entire bad cache if 'name' is NULL.
+ *
+ * Requires:
+ * \li resolver to be valid.
+ */
+
+void
+dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp);
+/*%
+ * Print out the contents of the bad cache to 'fp'.
+ *
+ * Requires:
+ * \li resolver to be valid.
+ */
+
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_RESOLVER_H */
index 37d61b5..6a0573f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: result.h,v 1.114 2007/06/19 23:47:17 tbox Exp $ */
+/* $Id: result.h,v 1.114.288.2 2010/02/25 10:56:02 tbox Exp $ */
 
 #ifndef DNS_RESULT_H
 #define DNS_RESULT_H 1
 #define DNS_R_COVERINGNSEC             (ISC_RESULTCLASS_DNS + 101)
 #define DNS_R_MXISADDRESS              (ISC_RESULTCLASS_DNS + 102)
 #define DNS_R_DUPLICATE                        (ISC_RESULTCLASS_DNS + 103)
+#define DNS_R_INVALIDNSEC3             (ISC_RESULTCLASS_DNS + 104)
+#define DNS_R_NOTMASTER                        (ISC_RESULTCLASS_DNS + 105)
+#define DNS_R_BROKENCHAIN              (ISC_RESULTCLASS_DNS + 106)
 
-#define DNS_R_NRESULTS                 104     /*%< Number of results */
+#define DNS_R_NRESULTS                 107     /*%< Number of results */
 
 /*
  * DNS wire format rcodes.
index 746bee1..811bb37 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: validator.h,v 1.39.52.3 2009/01/19 00:01:11 marka Exp $ */
+/* $Id: validator.h,v 1.39.52.3.2.2 2010/02/25 10:56:02 tbox Exp $ */
 
 #ifndef DNS_VALIDATOR_H
 #define DNS_VALIDATOR_H 1
@@ -151,6 +151,8 @@ struct dns_validator {
        isc_boolean_t                   mustbesecure;
        unsigned int                    dlvlabels;
        unsigned int                    depth;
+       unsigned int                    authcount;
+       unsigned int                    authfail;
 };
 
 /*%
index a779e01..e9c0caa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: ncache.c,v 1.41 2007/06/19 23:47:16 tbox Exp $ */
+/* $Id: ncache.c,v 1.41.288.2 2010/02/25 10:56:01 tbox Exp $ */
 
 /*! \file */
 
@@ -478,6 +478,8 @@ static dns_rdatasetmethods_t rdataset_methods = {
        NULL,
        NULL,
        NULL,
+       NULL,
+       NULL,
        NULL
 };
 
index 91ced3e..6c54a87 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: rbtdb.c,v 1.248.12.18.2.2 2009/12/31 21:45:53 each Exp $ */
+/* $Id: rbtdb.c,v 1.248.12.18.2.5 2010/02/26 00:26:54 marka Exp $ */
 
 /*! \file */
 
@@ -497,6 +497,8 @@ static void expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
 static void overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start,
                          isc_stdtime_t now, isc_boolean_t tree_locked);
 static void prune_tree(isc_task_t *task, isc_event_t *event);
+static void rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust);
+static void rdataset_expire(dns_rdataset_t *rdataset);
 
 static dns_rdatasetmethods_t rdataset_methods = {
        rdataset_disassociate,
@@ -509,7 +511,9 @@ static dns_rdatasetmethods_t rdataset_methods = {
        rdataset_getnoqname,
        rdataset_getadditional,
        rdataset_setadditional,
-       rdataset_putadditional
+       rdataset_putadditional,
+       rdataset_settrust,
+       rdataset_expire
 };
 
 static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
@@ -6548,6 +6552,34 @@ rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
        return (ISC_R_SUCCESS);
 }
 
+static void
+rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
+       dns_rbtdb_t *rbtdb = rdataset->private1;
+       dns_rbtnode_t *rbtnode = rdataset->private2;
+       rdatasetheader_t *header = rdataset->private3;
+
+       header--;
+       NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+                 isc_rwlocktype_write);
+       header->trust = rdataset->trust = trust;
+       NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+                 isc_rwlocktype_write);
+}
+
+static void
+rdataset_expire(dns_rdataset_t *rdataset) {
+       dns_rbtdb_t *rbtdb = rdataset->private1;
+       dns_rbtnode_t *rbtnode = rdataset->private2;
+       rdatasetheader_t *header = rdataset->private3;
+
+       header--;
+       NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+                 isc_rwlocktype_write);
+       expire_header(rbtdb, header, ISC_FALSE);
+       NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+                 isc_rwlocktype_write);
+}
+
 /*
  * Rdataset Iterator Methods
  */
index 836d997..2c85529 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008, 2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: rdatalist.c,v 1.33.128.2 2008/04/03 06:08:27 tbox Exp $ */
+/* $Id: rdatalist.c,v 1.33.128.2.28.2 2010/02/25 10:56:01 tbox Exp $ */
 
 /*! \file */
 
@@ -43,6 +43,8 @@ static dns_rdatasetmethods_t methods = {
        isc__rdatalist_getnoqname,
        NULL,
        NULL,
+       NULL,
+       NULL,
        NULL
 };
 
index ea2d90f..142438e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: rdataset.c,v 1.79.128.2 2009/01/19 23:47:02 tbox Exp $ */
+/* $Id: rdataset.c,v 1.79.128.2.2.2 2010/02/25 10:56:01 tbox Exp $ */
 
 /*! \file */
 
@@ -179,6 +179,8 @@ static dns_rdatasetmethods_t question_methods = {
        NULL,
        NULL,
        NULL,
+       NULL,
+       NULL,
        NULL
 };
 
@@ -707,3 +709,22 @@ dns_rdataset_putadditional(dns_acache_t *acache,
        return (ISC_R_FAILURE);
 }
 
+void
+dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
+       REQUIRE(DNS_RDATASET_VALID(rdataset));
+       REQUIRE(rdataset->methods != NULL);
+
+       if (rdataset->methods->settrust != NULL)
+               (rdataset->methods->settrust)(rdataset, trust);
+       else
+               rdataset->trust = trust;
+}
+
+void
+dns_rdataset_expire(dns_rdataset_t *rdataset) {
+       REQUIRE(DNS_RDATASET_VALID(rdataset));
+       REQUIRE(rdataset->methods != NULL);
+
+       if (rdataset->methods->expire != NULL)
+               (rdataset->methods->expire)(rdataset);
+}
index 28d95c9..48dc0e0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: rdataslab.c,v 1.43.128.4 2009/01/19 23:47:02 tbox Exp $ */
+/* $Id: rdataslab.c,v 1.43.128.4.2.2 2010/02/25 10:56:01 tbox Exp $ */
 
 /*! \file */
 
@@ -401,6 +401,8 @@ static dns_rdatasetmethods_t rdataset_methods = {
        NULL,
        NULL,
        NULL,
+       NULL,
+       NULL,
        NULL
 };
 
index 82fbafb..429fa46 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: resolver.c,v 1.355.12.44.2.2 2010/01/07 17:19:22 each Exp $ */
+/* $Id: resolver.c,v 1.355.12.44.2.5 2010/02/25 10:56:01 tbox Exp $ */
 
 /*! \file */
 
@@ -328,6 +328,18 @@ typedef struct alternate {
        ISC_LINK(struct alternate)      link;
 } alternate_t;
 
+typedef struct dns_badcache dns_badcache_t;
+struct dns_badcache {
+       dns_badcache_t *        next;
+       dns_rdatatype_t         type;
+       isc_time_t              expire;
+       unsigned int            hashval;
+       dns_name_t              name;
+};
+#define DNS_BADCACHE_SIZE 1021
+#define DNS_BADCACHE_TTL(fctx) \
+       (((fctx)->res->lame_ttl > 30 ) ? (fctx)->res->lame_ttl : 30)
+
 struct dns_resolver {
        /* Unlocked. */
        unsigned int                    magic;
@@ -374,6 +386,13 @@ struct dns_resolver {
        isc_boolean_t                   priming;
        unsigned int                    spillat;        /* clients-per-query */
        unsigned int                    nextdisp;
+
+       /* Bad cache. */
+       dns_badcache_t  **              badcache;
+       unsigned int                    badcount;
+       unsigned int                    badhash;
+       unsigned int                    badsweep;
+
        /* Locked by primelock. */
        dns_fetch_t *                   primefetch;
        /* Locked by nlock. */
@@ -401,7 +420,8 @@ static void empty_bucket(dns_resolver_t *res);
 static isc_result_t resquery_send(resquery_t *query);
 static void resquery_response(isc_task_t *task, isc_event_t *event);
 static void resquery_connected(isc_task_t *task, isc_event_t *event);
-static void fctx_try(fetchctx_t *fctx, isc_boolean_t retrying);
+static void fctx_try(fetchctx_t *fctx, isc_boolean_t retrying,
+                    isc_boolean_t badcache);
 static isc_boolean_t fctx_destroy(fetchctx_t *fctx);
 static isc_result_t ncache_adderesult(dns_message_t *message,
                                      dns_db_t *cache, dns_dbnode_t *node,
@@ -1153,7 +1173,7 @@ process_sendevent(resquery_t *query, isc_event_t *event) {
                if (result != ISC_R_SUCCESS)
                        fctx_done(fctx, result, __LINE__);
                else
-                       fctx_try(fctx, ISC_TRUE);
+                       fctx_try(fctx, ISC_TRUE, ISC_FALSE);
        }
 }
 
@@ -2050,7 +2070,7 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
                if (result != ISC_R_SUCCESS)
                        fctx_done(fctx, result, __LINE__);
                else
-                       fctx_try(fctx, ISC_TRUE);
+                       fctx_try(fctx, ISC_TRUE, ISC_FALSE);
        }
 }
 
@@ -2112,7 +2132,7 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) {
        dns_adb_destroyfind(&find);
 
        if (want_try)
-               fctx_try(fctx, ISC_TRUE);
+               fctx_try(fctx, ISC_TRUE, ISC_FALSE);
        else if (want_done)
                fctx_done(fctx, ISC_R_FAILURE, __LINE__);
        else if (bucket_empty)
@@ -2475,7 +2495,7 @@ isstrictsubdomain(dns_name_t *name1, dns_name_t *name2) {
 }
 
 static isc_result_t
-fctx_getaddresses(fetchctx_t *fctx) {
+fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) {
        dns_rdata_t rdata = DNS_RDATA_INIT;
        isc_result_t result;
        dns_resolver_t *res;
@@ -2694,12 +2714,24 @@ fctx_getaddresses(fetchctx_t *fctx) {
                         */
                        result = DNS_R_WAIT;
                } else {
+                       isc_time_t expire;
+                       isc_interval_t i;
                        /*
                         * We've lost completely.  We don't know any
                         * addresses, and the ADB has told us it can't get
                         * them.
                         */
                        FCTXTRACE("no addresses");
+                       isc_interval_set(&i, DNS_BADCACHE_TTL(fctx), 0);
+                       result = isc_time_nowplusinterval(&expire, &i);
+                       if (badcache &&
+                           (fctx->type == dns_rdatatype_dnskey ||
+                            fctx->type == dns_rdatatype_dlv ||
+                            fctx->type == dns_rdatatype_ds) &&
+                            result == ISC_R_SUCCESS)
+                               dns_resolver_addbadcache(fctx->res,
+                                                        &fctx->name,
+                                                        fctx->type, &expire);
                        result = ISC_R_FAILURE;
                }
        } else {
@@ -2921,7 +2953,7 @@ fctx_nextaddress(fetchctx_t *fctx) {
 }
 
 static void
-fctx_try(fetchctx_t *fctx, isc_boolean_t retrying) {
+fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) {
        isc_result_t result;
        dns_adbaddrinfo_t *addrinfo;
 
@@ -2939,7 +2971,7 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying) {
                fctx_cleanupaltfinds(fctx);
                fctx_cleanupforwaddrs(fctx);
                fctx_cleanupaltaddrs(fctx);
-               result = fctx_getaddresses(fctx);
+               result = fctx_getaddresses(fctx, badcache);
                if (result == DNS_R_WAIT) {
                        /*
                         * Sleep waiting for addresses.
@@ -3104,7 +3136,7 @@ fctx_timeout(isc_task_t *task, isc_event_t *event) {
                        /*
                         * Keep trying.
                         */
-                       fctx_try(fctx, ISC_TRUE);
+                       fctx_try(fctx, ISC_TRUE, ISC_FALSE);
        }
 
        isc_event_free(&event);
@@ -3274,7 +3306,7 @@ fctx_start(isc_task_t *task, isc_event_t *event) {
                if (result != ISC_R_SUCCESS)
                        fctx_done(fctx, result, __LINE__);
                else
-                       fctx_try(fctx, ISC_FALSE);
+                       fctx_try(fctx, ISC_FALSE, ISC_FALSE);
        } else if (bucket_empty)
                empty_bucket(res);
 }
@@ -3850,6 +3882,8 @@ validated(isc_task_t *task, isc_event_t *event) {
 
        LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
 
+       isc_stdtime_get(&now);
+
        /*
         * If chaining, we need to make sure that the right result code is
         * returned, and that the rdatasets are bound.
@@ -3896,35 +3930,80 @@ validated(isc_task_t *task, isc_event_t *event) {
                inc_stats(fctx->res, dns_resstatscounter_valfail);
                fctx->valfail++;
                fctx->vresult = vevent->result;
-               result = ISC_R_NOTFOUND;
-               if (vevent->rdataset != NULL)
-                       result = dns_db_findnode(fctx->cache, vevent->name,
-                                                ISC_TRUE, &node);
-               if (result == ISC_R_SUCCESS)
-                       (void)dns_db_deleterdataset(fctx->cache, node, NULL,
-                                                   vevent->type, 0);
-               if (result == ISC_R_SUCCESS && vevent->sigrdataset != NULL)
-                       (void)dns_db_deleterdataset(fctx->cache, node, NULL,
-                                                   dns_rdatatype_rrsig,
-                                                   vevent->type);
-               if (result == ISC_R_SUCCESS)
-                       dns_db_detachnode(fctx->cache, &node);
-               result = vevent->result;
+               if (fctx->vresult != DNS_R_BROKENCHAIN) {
+                       result = ISC_R_NOTFOUND;
+                       if (vevent->rdataset != NULL)
+                               result = dns_db_findnode(fctx->cache,
+                                                        vevent->name,
+                                                        ISC_TRUE, &node);
+                       if (result == ISC_R_SUCCESS)
+                               (void)dns_db_deleterdataset(fctx->cache, node,
+                                                            NULL,
+                                                           vevent->type, 0);
+                       if (result == ISC_R_SUCCESS &&
+                            vevent->sigrdataset != NULL)
+                               (void)dns_db_deleterdataset(fctx->cache, node,
+                                                           NULL,
+                                                           dns_rdatatype_rrsig,
+                                                           vevent->type);
+                       if (result == ISC_R_SUCCESS)
+                               dns_db_detachnode(fctx->cache, &node);
+               }
+               if (fctx->vresult == DNS_R_BROKENCHAIN && !negative) {
+                       /*
+                        * Cache the data as pending for later validation.
+                        */
+                       result = ISC_R_NOTFOUND;
+                       if (vevent->rdataset != NULL)
+                               result = dns_db_findnode(fctx->cache,
+                                                        vevent->name,
+                                                        ISC_TRUE, &node);
+                       if (result == ISC_R_SUCCESS) {
+                               (void)dns_db_addrdataset(fctx->cache, node,
+                                                        NULL, now,
+                                                        vevent->rdataset, 0,
+                                                        NULL);
+                       }
+                       if (result == ISC_R_SUCCESS &&
+                           vevent->sigrdataset != NULL)
+                               (void)dns_db_addrdataset(fctx->cache, node,
+                                                        NULL, now,
+                                                        vevent->sigrdataset,
+                                                        0, NULL);
+                       if (result == ISC_R_SUCCESS)
+                               dns_db_detachnode(fctx->cache, &node);
+               }
+               result = fctx->vresult;
                add_bad(fctx, addrinfo, result, badns_validation);
                isc_event_free(&event);
                UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
                INSIST(fctx->validator == NULL);
                fctx->validator = ISC_LIST_HEAD(fctx->validators);
-               if (fctx->validator != NULL) {
+               if (fctx->validator != NULL)
                        dns_validator_send(fctx->validator);
-               else if (sentresponse)
+               else if (sentresponse)
                        fctx_done(fctx, result, __LINE__); /* Locks bucket. */
-               else
-                       fctx_try(fctx, ISC_TRUE);       /* Locks bucket. */
+               else if (result == DNS_R_BROKENCHAIN) {
+                       isc_result_t tresult;
+                       isc_time_t expire;
+                       isc_interval_t i;
+
+                       isc_interval_set(&i, DNS_BADCACHE_TTL(fctx), 0);
+                       tresult = isc_time_nowplusinterval(&expire, &i);
+                       if (negative &&
+                           (fctx->type == dns_rdatatype_dnskey ||
+                            fctx->type == dns_rdatatype_dlv ||
+                            fctx->type == dns_rdatatype_ds) &&
+                            tresult == ISC_R_SUCCESS)
+                               dns_resolver_addbadcache(fctx->res,
+                                                        &fctx->name,
+                                                        fctx->type, &expire);
+                       fctx_done(fctx, result, __LINE__); /* Locks bucket. */
+               } else
+                       fctx_try(fctx, ISC_TRUE, ISC_TRUE); /* Locks bucket. */
                return;
        }
 
-       isc_stdtime_get(&now);
 
        if (negative) {
                dns_rdatatype_t covers;
@@ -5703,7 +5782,7 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
                /*
                 * Try again.
                 */
-               fctx_try(fctx, ISC_TRUE);
+               fctx_try(fctx, ISC_TRUE, ISC_FALSE);
        } else {
                unsigned int n;
                dns_rdataset_t *nsrdataset = NULL;
@@ -6542,7 +6621,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
                /*
                 * Try again.
                 */
-               fctx_try(fctx, !get_nameservers);
+               fctx_try(fctx, !get_nameservers, ISC_FALSE);
        } else if (resend) {
                /*
                 * Resend (probably with changed options).
@@ -6604,6 +6683,27 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
 /***
  *** Resolver Methods
  ***/
+static void
+destroy_badcache(dns_resolver_t *res) {
+       dns_badcache_t *bad, *next;
+       unsigned int i;
+
+       if (res->badcache != NULL) {
+               for (i = 0; i < res->badhash; i++)
+                       for (bad = res->badcache[i]; bad != NULL;
+                            bad = next) {
+                               next = bad->next;
+                               isc_mem_put(res->mctx, bad, sizeof(*bad) +
+                                           bad->name.length);
+                               res->badcount--;
+                       }
+               isc_mem_put(res->mctx, res->badcache,
+                           sizeof(*res->badcache) * res->badhash);
+               res->badcache = NULL;
+               res->badhash = 0;
+               INSIST(res->badcount == 0);
+       }
+}
 
 static void
 destroy(dns_resolver_t *res) {
@@ -6641,6 +6741,7 @@ destroy(dns_resolver_t *res) {
                isc_mem_put(res->mctx, a, sizeof(*a));
        }
        dns_resolver_reset_algorithms(res);
+       destroy_badcache(res);
        dns_resolver_resetmustbesecure(res);
 #if USE_ALGLOCK
        isc_rwlock_destroy(&res->alglock);
@@ -6764,6 +6865,10 @@ dns_resolver_create(dns_view_t *view,
        ISC_LIST_INIT(res->alternates);
        res->udpsize = RECV_BUFFER_SIZE;
        res->algorithms = NULL;
+       res->badcache = NULL;
+       res->badcount = 0;
+       res->badhash = 0;
+       res->badsweep = 0;
        res->mustbesecure = NULL;
        res->spillatmin = res->spillat = 10;
        res->spillatmax = 100;
@@ -7605,6 +7710,256 @@ dns_resolver_getudpsize(dns_resolver_t *resolver) {
        return (resolver->udpsize);
 }
 
+void
+dns_resolver_flushbadcache(dns_resolver_t *resolver, dns_name_t *name) {
+       unsigned int i;
+       dns_badcache_t *bad, *prev, *next;
+
+       REQUIRE(VALID_RESOLVER(resolver));
+
+       LOCK(&resolver->lock);
+       if (resolver->badcache == NULL)
+               goto unlock;
+
+       if (name != NULL) {
+               isc_time_t now;
+               isc_result_t result;
+               result = isc_time_now(&now);
+               if (result != ISC_R_SUCCESS)
+                       isc_time_settoepoch(&now);
+               i = dns_name_hash(name, ISC_FALSE) % resolver->badhash;
+               prev = NULL;
+               for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
+                       int n;
+                       next = bad->next;
+                       n = isc_time_compare(&bad->expire, &now);
+                       if (n < 0 || dns_name_equal(name, &bad->name)) {
+                               if (prev == NULL)
+                                       resolver->badcache[i] = bad->next;
+                               else
+                                       prev->next = bad->next;
+                               isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
+                                           bad->name.length);
+                               resolver->badcount--;
+                       } else
+                               prev = bad;
+               }
+       } else
+               destroy_badcache(resolver);
+
+ unlock:
+       UNLOCK(&resolver->lock);
+
+}
+
+static void
+resizehash(dns_resolver_t *resolver, isc_time_t *now, isc_boolean_t grow) {
+       unsigned int newsize;
+       dns_badcache_t **new, *bad, *next;
+       unsigned int i;
+
+       if (grow)
+               newsize = resolver->badhash * 2 + 1;
+       else
+               newsize = (resolver->badhash - 1) / 2;
+
+       new = isc_mem_get(resolver->mctx,
+                         sizeof(*resolver->badcache) * newsize);
+       if (new == NULL)
+               return;
+       memset(new, 0, sizeof(*resolver->badcache) * newsize);
+       for (i = 0; i < resolver->badhash; i++) {
+               for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
+                       next = bad->next;
+                       if (isc_time_compare(&bad->expire, now) < 0) {
+                               isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
+                                           bad->name.length);
+                               resolver->badcount--;
+                       } else {
+                               bad->next = new[bad->hashval % newsize];
+                               new[bad->hashval % newsize] = bad;
+                       }
+               }
+       }
+       isc_mem_put(resolver->mctx, resolver->badcache,
+                   sizeof(*resolver->badcache) * resolver->badhash);
+       resolver->badhash = newsize;
+       resolver->badcache = new;
+}
+
+void
+dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name,
+                        dns_rdatatype_t type, isc_time_t *expire)
+{
+       isc_time_t now;
+       isc_result_t result = ISC_R_SUCCESS;
+       unsigned int i, hashval;
+       dns_badcache_t *bad, *prev, *next;
+
+       REQUIRE(VALID_RESOLVER(resolver));
+
+       LOCK(&resolver->lock);
+       if (resolver->badcache == NULL) {
+               resolver->badcache = isc_mem_get(resolver->mctx,
+                                                sizeof(*resolver->badcache) *
+                                                DNS_BADCACHE_SIZE);
+               if (resolver->badcache == NULL) {
+                       result = ISC_R_NOMEMORY;
+                       goto cleanup;
+               }
+               resolver->badhash = DNS_BADCACHE_SIZE;
+               memset(resolver->badcache, 0, sizeof(*resolver->badcache) *
+                      resolver->badhash);
+       }
+
+       result = isc_time_now(&now);
+       if (result != ISC_R_SUCCESS)
+               isc_time_settoepoch(&now);
+       hashval = dns_name_hash(name, ISC_FALSE);
+       i = hashval % resolver->badhash;
+       prev = NULL;
+       for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
+               next = bad->next;
+               if (bad->type == type && dns_name_equal(name, &bad->name))
+                       break;
+               if (isc_time_compare(&bad->expire, &now) < 0) {
+                       if (prev == NULL)
+                               resolver->badcache[i] = bad->next;
+                       else
+                               prev->next = bad->next;
+                       isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
+                                   bad->name.length);
+                       resolver->badcount--;
+               } else
+                       prev = bad;
+       }
+       if (bad == NULL) {
+               isc_buffer_t buffer;
+               bad = isc_mem_get(resolver->mctx, sizeof(*bad) + name->length);
+               if (bad == NULL) {
+                       result = ISC_R_NOMEMORY;
+                       goto cleanup;
+               }
+               bad->type = type;
+               bad->hashval = hashval;
+               isc_buffer_init(&buffer, bad + 1, name->length);
+               dns_name_init(&bad->name, NULL);
+               dns_name_copy(name, &bad->name, &buffer);
+               bad->next = resolver->badcache[i];
+               resolver->badcache[i] = bad;
+               resolver->badcount++;
+               if (resolver->badcount > resolver->badhash * 8)
+                       resizehash(resolver, &now, ISC_TRUE);
+               if (resolver->badcount < resolver->badhash * 2 &&
+                   resolver->badhash > DNS_BADCACHE_SIZE)
+                       resizehash(resolver, &now, ISC_FALSE);
+       }
+       bad->expire = *expire;
+ cleanup:
+       UNLOCK(&resolver->lock);
+}
+
+isc_boolean_t
+dns_resolver_getbadcache(dns_resolver_t *resolver, dns_name_t *name,
+                        dns_rdatatype_t type, isc_time_t *now)
+{
+       dns_badcache_t *bad, *prev, *next;
+       isc_boolean_t answer = ISC_FALSE;
+       unsigned int i;
+
+       REQUIRE(VALID_RESOLVER(resolver));
+
+       LOCK(&resolver->lock);
+       if (resolver->badcache == NULL)
+               goto unlock;
+
+       i = dns_name_hash(name, ISC_FALSE) % resolver->badhash;
+       prev = NULL;
+       for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
+               next = bad->next;
+               /*
+                * Search the hash list. Clean out expired records as we go.
+                */
+               if (isc_time_compare(&bad->expire, now) < 0) {
+                       if (prev != NULL)
+                               prev->next = bad->next;
+                       else
+                               resolver->badcache[i] = bad->next;
+                       isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
+                                   bad->name.length);
+                       resolver->badcount--;
+                       continue;
+               }
+               if (bad->type == type && dns_name_equal(name, &bad->name)) {
+                       answer = ISC_TRUE;
+                       break;
+               }
+               prev = bad;
+       }
+
+       /*
+        * Slow sweep to clean out stale records.
+        */
+       i = resolver->badsweep++ % resolver->badhash;
+       bad = resolver->badcache[i];
+       if (bad != NULL && isc_time_compare(&bad->expire, now) < 0) {
+               resolver->badcache[i] = bad->next;
+               isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
+                           bad->name.length);
+               resolver->badcount--;
+       }
+
+ unlock:
+       UNLOCK(&resolver->lock);
+       return (answer);
+}
+
+void
+dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp) {
+       char namebuf[DNS_NAME_FORMATSIZE];
+       char typebuf[DNS_RDATATYPE_FORMATSIZE];
+       dns_badcache_t *bad, *next, *prev;
+       isc_time_t now;
+       unsigned int i;
+       isc_uint64_t t;
+
+       LOCK(&resolver->lock);
+       fprintf(fp, ";\n; Bad cache\n;\n");
+
+       if (resolver->badcache == NULL)
+               goto unlock;
+
+       TIME_NOW(&now);
+       for (i = 0; i < resolver->badhash; i++) {
+               prev = NULL;
+               for (bad = resolver->badcache[i]; bad != NULL; bad = next) {
+                       next = bad->next;
+                       if (isc_time_compare(&bad->expire, &now) < 0) {
+                               if (prev != NULL)
+                                       prev->next = bad->next;
+                               else
+                                       resolver->badcache[i] = bad->next;
+                               isc_mem_put(resolver->mctx, bad, sizeof(*bad) +
+                                           bad->name.length);
+                               resolver->badcount--;
+                               continue;
+                       }
+                       prev = bad;
+                       dns_name_format(&bad->name, namebuf, sizeof(namebuf));
+                       dns_rdatatype_format(bad->type, typebuf,
+                                            sizeof(typebuf));
+                       t = isc_time_microdiff(&bad->expire, &now);
+                       t /= 1000;
+                       fprintf(fp, "; %s/%s [ttl "
+                               "%" ISC_PLATFORM_QUADFORMAT "u]\n",
+                               namebuf, typebuf, t);
+               }
+       }
+
+ unlock:
+       UNLOCK(&resolver->lock);
+}
+
 static void
 free_algorithm(void *node, void *arg) {
        unsigned char *algorithms = node;
index 2e06054..0d433dc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: result.c,v 1.123 2007/06/19 23:47:16 tbox Exp $ */
+/* $Id: result.c,v 1.123.288.2 2010/02/25 10:56:02 tbox Exp $ */
 
 /*! \file */
 
@@ -155,7 +155,11 @@ static const char *text[DNS_R_NRESULTS] = {
        "must-be-secure",                      /*%< 100 DNS_R_MUSTBESECURE */
        "covering NSEC record returned",       /*%< 101 DNS_R_COVERINGNSEC */
        "MX is an address",                    /*%< 102 DNS_R_MXISADDRESS */
-       "duplicate query"                      /*%< 103 DNS_R_DUPLICATE */
+       "duplicate query",                     /*%< 103 DNS_R_DUPLICATE */
+       "invalid NSEC3 owner name (wildcard)", /*%< 104 DNS_R_INVALIDNSEC3 */
+
+       "not master",                          /*%< 105 DNS_R_NOTMASTER */
+       "broken trust chain",                  /*%< 106 DNS_R_BROKENCHAIN */
 };
 
 static const char *rcode_text[DNS_R_NRCODERESULTS] = {
index 1c80f97..5bf888d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000, 2001, 2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: sdb.c,v 1.59.94.8 2009/06/26 06:23:47 marka Exp $ */
+/* $Id: sdb.c,v 1.59.94.8.2.2 2010/02/25 10:56:02 tbox Exp $ */
 
 /*! \file */
 
@@ -1376,6 +1376,8 @@ static dns_rdatasetmethods_t methods = {
        isc__rdatalist_getnoqname,
        NULL,
        NULL,
+       NULL,
+       NULL,
        NULL
 };
 
index 1199393..60fe69b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Portions Copyright (C) 2005-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2005-2010  Internet Systems Consortium, Inc. ("ISC")
  * Portions Copyright (C) 1999-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -50,7 +50,7 @@
  * USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: sdlz.c,v 1.14.94.6 2009/06/26 06:23:47 marka Exp $ */
+/* $Id: sdlz.c,v 1.14.94.6.2.2 2010/02/25 10:56:02 tbox Exp $ */
 
 /*! \file */
 
@@ -1200,6 +1200,8 @@ static dns_rdatasetmethods_t rdataset_methods = {
        isc__rdatalist_getnoqname,
        NULL,
        NULL,
+       NULL,
+       NULL,
        NULL
 };
 
index 937da66..756da8f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: validator.c,v 1.155.52.14.2.2 2009/12/31 21:02:44 each Exp $ */
+/* $Id: validator.c,v 1.155.52.14.2.4 2010/02/25 10:56:02 tbox Exp $ */
 
 #include <config.h>
 
@@ -168,9 +168,16 @@ static inline void
 markanswer(dns_validator_t *val) {
        validator_log(val, ISC_LOG_DEBUG(3), "marking as answer");
        if (val->event->rdataset != NULL)
-               val->event->rdataset->trust = dns_trust_answer;
+               dns_rdataset_settrust(val->event->rdataset, dns_trust_answer);
        if (val->event->sigrdataset != NULL)
-               val->event->sigrdataset->trust = dns_trust_answer;
+               dns_rdataset_settrust(val->event->sigrdataset,
+                                     dns_trust_answer);
+}
+
+static inline void
+marksecure(dns_validatorevent_t *event) {
+       dns_rdataset_settrust(event->rdataset, dns_trust_secure);
+       dns_rdataset_settrust(event->sigrdataset, dns_trust_secure);
 }
 
 static void
@@ -335,7 +342,7 @@ fetch_callback_validator(isc_task_t *task, isc_event_t *event) {
                if (eresult == ISC_R_CANCELED)
                        validator_done(val, eresult);
                else
-                       validator_done(val, DNS_R_NOVALIDKEY);
+                       validator_done(val, DNS_R_BROKENCHAIN);
        }
        want_destroy = exit_check(val);
        UNLOCK(&val->lock);
@@ -405,7 +412,7 @@ dsfetched(isc_task_t *task, isc_event_t *event) {
                if (eresult == ISC_R_CANCELED)
                        validator_done(val, eresult);
                else
-                       validator_done(val, DNS_R_NOVALIDDS);
+                       validator_done(val, DNS_R_BROKENCHAIN);
        }
        want_destroy = exit_check(val);
        UNLOCK(&val->lock);
@@ -545,10 +552,16 @@ keyvalidated(isc_task_t *task, isc_event_t *event) {
                if (result != DNS_R_WAIT)
                        validator_done(val, result);
        } else {
+               if (eresult != DNS_R_BROKENCHAIN) {
+                       if (dns_rdataset_isassociated(&val->frdataset))
+                               dns_rdataset_expire(&val->frdataset);
+                       if (dns_rdataset_isassociated(&val->fsigrdataset))
+                               dns_rdataset_expire(&val->fsigrdataset);
+               }
                validator_log(val, ISC_LOG_DEBUG(3),
                              "keyvalidated: got %s",
                              isc_result_totext(eresult));
-               validator_done(val, eresult);
+               validator_done(val, DNS_R_BROKENCHAIN);
        }
        want_destroy = exit_check(val);
        UNLOCK(&val->lock);
@@ -595,10 +608,16 @@ dsvalidated(isc_task_t *task, isc_event_t *event) {
                if (result != DNS_R_WAIT)
                        validator_done(val, result);
        } else {
+               if (eresult != DNS_R_BROKENCHAIN) {
+                       if (dns_rdataset_isassociated(&val->frdataset))
+                               dns_rdataset_expire(&val->frdataset);
+                       if (dns_rdataset_isassociated(&val->fsigrdataset))
+                               dns_rdataset_expire(&val->fsigrdataset);
+               }
                validator_log(val, ISC_LOG_DEBUG(3),
                              "dsvalidated: got %s",
                              isc_result_totext(eresult));
-               validator_done(val, eresult);
+               validator_done(val, DNS_R_BROKENCHAIN);
        }
        want_destroy = exit_check(val);
        UNLOCK(&val->lock);
@@ -800,6 +819,8 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
                validator_log(val, ISC_LOG_DEBUG(3),
                              "authvalidated: got %s",
                              isc_result_totext(result));
+               if (result == DNS_R_BROKENCHAIN)
+                       val->authfail++;
                if (result == ISC_R_CANCELED)
                        validator_done(val, result);
                else {
@@ -865,6 +886,7 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
  * \li DNS_R_NCACHENXRRSET
  * \li DNS_R_NXRRSET
  * \li DNS_R_NXDOMAIN
+ * \li DNS_R_BROKENCHAIN
  */
 static inline isc_result_t
 view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
@@ -874,9 +896,12 @@ view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
        dns_rdata_t rdata = DNS_RDATA_INIT;
        isc_result_t result;
        unsigned int options;
+       isc_time_t now;
        char buf1[DNS_NAME_FORMATSIZE];
        char buf2[DNS_NAME_FORMATSIZE];
        char buf3[DNS_NAME_FORMATSIZE];
+       char namebuf[DNS_NAME_FORMATSIZE];
+       char typebuf[DNS_RDATATYPE_FORMATSIZE];
 
        if (dns_rdataset_isassociated(&val->frdataset))
                dns_rdataset_disassociate(&val->frdataset);
@@ -886,6 +911,16 @@ view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
        if (val->view->zonetable == NULL)
                return (ISC_R_CANCELED);
 
+       if (isc_time_now(&now) == ISC_R_SUCCESS &&
+           dns_resolver_getbadcache(val->view->resolver, name, type, &now)) {
+
+               dns_name_format(name, namebuf, sizeof(namebuf));
+               dns_rdatatype_format(type, typebuf, sizeof(typebuf));
+               validator_log(val, ISC_LOG_INFO, "bad cache hit (%s/%s)",
+                             namebuf, typebuf);
+               return (DNS_R_BROKENCHAIN);
+       }
+
        options = DNS_DBFIND_PENDINGOK;
        if (type == dns_rdatatype_dlv)
                options |= DNS_DBFIND_COVERINGNSEC;
@@ -894,6 +929,7 @@ view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
        result = dns_view_find(val->view, name, type, 0, options,
                               ISC_FALSE, NULL, NULL, foundname,
                               &val->frdataset, &val->fsigrdataset);
+
        if (result == DNS_R_NXDOMAIN) {
                if (dns_rdataset_isassociated(&val->frdataset))
                        dns_rdataset_disassociate(&val->frdataset);
@@ -1238,7 +1274,8 @@ get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
                /*
                 * We don't know anything about this key.
                 */
-               result = create_fetch(val, &siginfo->signer, dns_rdatatype_dnskey,
+               result = create_fetch(val, &siginfo->signer,
+                                     dns_rdatatype_dnskey,
                                      fetch_callback_validator, "get_key");
                if (result != ISC_R_SUCCESS)
                        return (result);
@@ -1253,7 +1290,8 @@ get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
                 * This key doesn't exist.
                 */
                result = DNS_R_CONTINUE;
-       }
+       } else if (result == DNS_R_BROKENCHAIN)
+               return (result);
 
        if (dns_rdataset_isassociated(&val->frdataset) &&
            val->keyset != &val->frdataset)
@@ -1501,8 +1539,7 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
                                      "looking for noqname proof");
                        return (nsecvalidate(val, ISC_FALSE));
                } else if (result == ISC_R_SUCCESS) {
-                       event->rdataset->trust = dns_trust_secure;
-                       event->sigrdataset->trust = dns_trust_secure;
+                       marksecure(event);
                        validator_log(val, ISC_LOG_DEBUG(3),
                                      "marking as secure");
                        return (result);
@@ -1678,8 +1715,7 @@ dlv_validatezonekey(dns_validator_t *val) {
                              "no RRSIG matching DLV key");
        }
        if (result == ISC_R_SUCCESS) {
-               val->event->rdataset->trust = dns_trust_secure;
-               val->event->sigrdataset->trust = dns_trust_secure;
+               marksecure(val->event);
                validator_log(val, ISC_LOG_DEBUG(3), "marking as secure");
                return (result);
        } else if (result == ISC_R_NOMORE && !supported_algorithm) {
@@ -1780,8 +1816,7 @@ validatezonekey(dns_validator_t *val) {
                                keynode = nextnode;
                        }
                        if (result == ISC_R_SUCCESS) {
-                               event->rdataset->trust = dns_trust_secure;
-                               event->sigrdataset->trust = dns_trust_secure;
+                               marksecure(event);
                                validator_log(val, ISC_LOG_DEBUG(3),
                                              "signed by trusted key; "
                                              "marking as secure");
@@ -1808,11 +1843,14 @@ validatezonekey(dns_validator_t *val) {
                         */
                        dns_name_format(val->event->name, namebuf,
                                        sizeof(namebuf));
-                       validator_log(val, ISC_LOG_DEBUG(2),
+                       validator_log(val, ISC_LOG_NOTICE,
                                      "unable to find a DNSKEY which verifies "
                                      "the DNSKEY RRset and also matches one "
                                      "of specified trusted-keys for '%s'",
                                      namebuf);
+                       validator_log(val, ISC_LOG_NOTICE,
+                                     "please check the 'trusted-keys' for "
+                                     "'%s' in named.conf.", namebuf);
                        return (DNS_R_NOVALIDKEY);
                }
 
@@ -1873,7 +1911,8 @@ validatezonekey(dns_validator_t *val) {
                                dns_rdataset_disassociate(&val->fsigrdataset);
                        validator_log(val, ISC_LOG_DEBUG(2), "no DS record");
                        return (DNS_R_NOVALIDSIG);
-               }
+               } else if (result == DNS_R_BROKENCHAIN)
+                       return (result);
        }
 
        /*
@@ -2022,8 +2061,7 @@ validatezonekey(dns_validator_t *val) {
                              "no RRSIG matching DS key");
        }
        if (result == ISC_R_SUCCESS) {
-               event->rdataset->trust = dns_trust_secure;
-               event->sigrdataset->trust = dns_trust_secure;
+               marksecure(event);
                validator_log(val, ISC_LOG_DEBUG(3), "marking as secure");
                return (result);
        } else if (result == ISC_R_NOMORE && !supported_algorithm) {
@@ -2229,6 +2267,7 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
                                                  "nsecvalidate");
                        if (result != ISC_R_SUCCESS)
                                return (result);
+                       val->authcount++;
                        return (DNS_R_WAIT);
 
                }
@@ -2250,8 +2289,7 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
                                      "noqname proof found");
                        validator_log(val, ISC_LOG_DEBUG(3),
                                      "marking as secure");
-                       val->event->rdataset->trust = dns_trust_secure;
-                       val->event->sigrdataset->trust = dns_trust_secure;
+                       marksecure(val->event);
                        return (ISC_R_SUCCESS);
                }
                validator_log(val, ISC_LOG_DEBUG(3),
@@ -2282,6 +2320,8 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
                return (ISC_R_SUCCESS);
        }
 
+       if (val->authcount == val->authfail)
+               return (DNS_R_BROKENCHAIN);
        validator_log(val, ISC_LOG_DEBUG(3),
                      "nonexistence proof(s) not found");
        val->attributes |= VALATTR_INSECURITY;
@@ -2313,6 +2353,58 @@ check_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) {
        return (ISC_FALSE);
 }
 
+static void
+dlvvalidated(isc_task_t *task, isc_event_t *event) {
+       dns_validatorevent_t *devent;
+       dns_validator_t *val;
+       isc_result_t eresult;
+       isc_boolean_t want_destroy;
+
+       UNUSED(task);
+       INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
+
+       devent = (dns_validatorevent_t *)event;
+       val = devent->ev_arg;
+       eresult = devent->result;
+
+       isc_event_free(&event);
+       dns_validator_destroy(&val->subvalidator);
+
+       INSIST(val->event != NULL);
+
+       validator_log(val, ISC_LOG_DEBUG(3), "in dlvvalidated");
+       LOCK(&val->lock);
+       if (CANCELED(val)) {
+               validator_done(val, ISC_R_CANCELED);
+       } else if (eresult == ISC_R_SUCCESS) {
+               validator_log(val, ISC_LOG_DEBUG(3),
+                             "dlvset with trust %d", val->frdataset.trust);
+               dns_rdataset_clone(&val->frdataset, &val->dlv);
+               val->havedlvsep = ISC_TRUE;
+               if (dlv_algorithm_supported(val))
+                       dlv_validator_start(val);
+               else {
+                       markanswer(val);
+                       validator_done(val, ISC_R_SUCCESS);
+               }
+       } else {
+               if (eresult != DNS_R_BROKENCHAIN) {
+                       if (dns_rdataset_isassociated(&val->frdataset))
+                               dns_rdataset_expire(&val->frdataset);
+                       if (dns_rdataset_isassociated(&val->fsigrdataset))
+                               dns_rdataset_expire(&val->fsigrdataset);
+               }
+               validator_log(val, ISC_LOG_DEBUG(3),
+                             "dlvvalidated: got %s",
+                             isc_result_totext(eresult));
+               validator_done(val, DNS_R_BROKENCHAIN);
+       }
+       want_destroy = exit_check(val);
+       UNLOCK(&val->lock);
+       if (want_destroy)
+               destroy(val);
+}
+
 /*%
  * Callback from fetching a DLV record.
  *
@@ -2532,6 +2624,24 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
                              namebuf);
                result = view_find(val, dlvname, dns_rdatatype_dlv);
                if (result == ISC_R_SUCCESS) {
+                       if (DNS_TRUST_PENDING(val->frdataset.trust) &&
+                           dns_rdataset_isassociated(&val->fsigrdataset))
+                       {
+                               dns_fixedname_init(&val->fname);
+                               dns_name_copy(dlvname,
+                                             dns_fixedname_name(&val->fname),
+                                             NULL);
+                               result = create_validator(val,
+                                               dns_fixedname_name(&val->fname),
+                                                         dns_rdatatype_dlv,
+                                                         &val->frdataset,
+                                                         &val->fsigrdataset,
+                                                         dlvvalidated,
+                                                         "finddlvsep");
+                               if (result != ISC_R_SUCCESS)
+                                       return (result);
+                               return (DNS_R_WAIT);
+                       }
                        if (val->frdataset.trust < dns_trust_secure)
                                return (DNS_R_NOVALIDSIG);
                        val->havedlvsep = ISC_TRUE;
@@ -2582,6 +2692,7 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
  * \li DNS_R_NOVALIDSIG
  * \li DNS_R_NOVALIDNSEC
  * \li DNS_R_NOTINSECURE
+ * \li DNS_R_BROKENCHAIN
  */
 static isc_result_t
 proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
@@ -2798,7 +2909,8 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
                        if (result != ISC_R_SUCCESS)
                                goto out;
                        return (DNS_R_WAIT);
-               }
+               } else if (result == DNS_R_BROKENCHAIN)
+                       return (result);
        }
        validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed");
        return (DNS_R_NOTINSECURE); /* Couldn't complete insecurity proof */
@@ -3005,6 +3117,8 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
        val->seensig = ISC_FALSE;
        val->havedlvsep = ISC_FALSE;
        val->depth = 0;
+       val->authcount = 0;
+       val->authfail = 0;
        val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
        dns_rdataset_init(&val->frdataset);
        dns_rdataset_init(&val->fsigrdataset);
index 5766cd5..08095b1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: view.c,v 1.143.128.9 2009/01/29 23:47:13 tbox Exp $ */
+/* $Id: view.c,v 1.143.128.9.2.2 2010/02/25 10:56:02 tbox Exp $ */
 
 /*! \file */
 
@@ -1270,10 +1270,11 @@ dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) {
 
        (void)fprintf(fp, ";\n; Cache dump of view '%s'\n;\n", view->name);
        result = dns_master_dumptostream(view->mctx, view->cachedb, NULL,
-                                         &dns_master_style_cache, fp);
+                                        &dns_master_style_cache, fp);
        if (result != ISC_R_SUCCESS)
                return (result);
        dns_adb_dump(view->adb, fp);
+       dns_resolver_printbadcache(view->resolver, fp);
        return (ISC_R_SUCCESS);
 }
 
@@ -1294,6 +1295,8 @@ dns_view_flushcache(dns_view_t *view) {
        dns_cache_attachdb(view->cache, &view->cachedb);
        if (view->acache != NULL)
                dns_acache_setdb(view->acache, view->cachedb);
+       if (view->resolver != NULL)
+               dns_resolver_flushbadcache(view->resolver, NULL);
 
        dns_adb_flush(view->adb);
        return (ISC_R_SUCCESS);
@@ -1308,6 +1311,8 @@ dns_view_flushname(dns_view_t *view, dns_name_t *name) {
                dns_adb_flushname(view->adb, name);
        if (view->cache == NULL)
                return (ISC_R_SUCCESS);
+       if (view->resolver != NULL)
+               dns_resolver_flushbadcache(view->resolver, name);
        return (dns_cache_flushname(view->cache, name));
 }
 
index dadbc08..e0ff895 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: version,v 1.39.18.13.2.2 2009/12/31 21:02:44 each Exp $
+# $Id: version,v 1.39.18.13.2.3 2010/02/25 10:49:12 marka Exp $
 # 
 # This file must follow /bin/sh rules.  It is imported directly via
 # configure.
@@ -7,4 +7,4 @@ MAJORVER=9
 MINORVER=5
 PATCHVER=2
 RELEASETYPE=-P
-RELEASEVER=2
+RELEASEVER=3