summaryrefslogtreecommitdiff
path: root/lib/dns
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dns')
-rw-r--r--lib/dns/include/dns/rdataset.h20
-rw-r--r--lib/dns/include/dns/resolver.h46
-rw-r--r--lib/dns/include/dns/result.h11
-rw-r--r--lib/dns/include/dns/validator.h6
-rw-r--r--lib/dns/ncache.c8
-rw-r--r--lib/dns/rbtdb.c40
-rw-r--r--lib/dns/rdatalist.c8
-rw-r--r--lib/dns/rdataset.c25
-rw-r--r--lib/dns/rdataslab.c6
-rw-r--r--lib/dns/resolver.c417
-rw-r--r--lib/dns/result.c12
-rw-r--r--lib/dns/sdb.c6
-rw-r--r--lib/dns/sdlz.c6
-rw-r--r--lib/dns/validator.c160
-rw-r--r--lib/dns/view.c11
15 files changed, 693 insertions, 89 deletions
diff --git a/lib/dns/include/dns/rdataset.h b/lib/dns/include/dns/rdataset.h
index 2749f8a80eb92..4d3578cc496a8 100644
--- a/lib/dns/include/dns/rdataset.h
+++ b/lib/dns/include/dns/rdataset.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2006, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2006, 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.51.18.9 2009/01/19 23:46:16 tbox Exp $ */
+/* $Id: rdataset.h,v 1.51.18.11 2010/02/26 23:46:37 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 */
diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h
index 3fce33665c488..5ea1d6990e3e0 100644
--- a/lib/dns/include/dns/resolver.h
+++ b/lib/dns/include/dns/resolver.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2006, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2006, 2009, 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.40.18.13 2009/09/24 23:46:07 tbox Exp $ */
+/* $Id: resolver.h,v 1.40.18.15 2010/02/26 23:46:37 tbox Exp $ */
#ifndef DNS_RESOLVER_H
#define DNS_RESOLVER_H 1
@@ -491,6 +491,48 @@ dns_resolver_getzeronosoattl(dns_resolver_t *resolver);
void
dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state);
+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 */
diff --git a/lib/dns/include/dns/result.h b/lib/dns/include/dns/result.h
index db5481b34c363..a43207e508764 100644
--- a/lib/dns/include/dns/result.h
+++ b/lib/dns/include/dns/result.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: result.h,v 1.104.10.6 2005/06/17 02:04:32 marka Exp $ */
+/* $Id: result.h,v 1.104.10.8 2010/02/26 23:46:37 tbox Exp $ */
#ifndef DNS_RESULT_H
#define DNS_RESULT_H 1
@@ -147,8 +147,11 @@
#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.
diff --git a/lib/dns/include/dns/validator.h b/lib/dns/include/dns/validator.h
index 9708cc4ce7eb0..befee5d66a40a 100644
--- a/lib/dns/include/dns/validator.h
+++ b/lib/dns/include/dns/validator.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 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.27.18.13 2009/01/19 00:36:28 marka Exp $ */
+/* $Id: validator.h,v 1.27.18.15 2010/02/26 23:46:37 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;
};
/*%
diff --git a/lib/dns/ncache.c b/lib/dns/ncache.c
index 1fdc5c80e2d0e..89106dad7c063 100644
--- a/lib/dns/ncache.c
+++ b/lib/dns/ncache.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ncache.c,v 1.36.18.3 2005/04/29 00:15:59 marka Exp $ */
+/* $Id: ncache.c,v 1.36.18.5 2010/02/26 23:46:36 tbox Exp $ */
/*! \file */
@@ -478,6 +478,8 @@ static dns_rdatasetmethods_t rdataset_methods = {
NULL,
NULL,
NULL,
+ NULL,
+ NULL,
NULL
};
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
index bd168080e76d6..fb561db3cf9dd 100644
--- a/lib/dns/rbtdb.c
+++ b/lib/dns/rbtdb.c
@@ -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.196.18.59 2009/11/26 23:46:11 tbox Exp $ */
+/* $Id: rbtdb.c,v 1.196.18.61 2010/02/26 23:46:36 tbox Exp $ */
/*! \file */
@@ -414,6 +414,8 @@ static isc_result_t rdataset_putadditional(dns_acache_t *acache,
dns_rdataset_t *rdataset,
dns_rdatasetadditional_t type,
dns_rdatatype_t qtype);
+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,
@@ -426,7 +428,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);
@@ -5823,6 +5827,36 @@ 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);
+ header->ttl = 0;
+ header->attributes |= RDATASET_ATTR_STALE;
+ rbtnode->dirty = 1;
+ NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_write);
+}
+
/*
* Rdataset Iterator Methods
*/
diff --git a/lib/dns/rdatalist.c b/lib/dns/rdatalist.c
index 7229fa3e45115..b2c08123e31e3 100644
--- a/lib/dns/rdatalist.c
+++ b/lib/dns/rdatalist.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rdatalist.c,v 1.28.18.3 2005/04/29 00:16:02 marka Exp $ */
+/* $Id: rdatalist.c,v 1.28.18.5 2010/02/26 23:46:36 tbox Exp $ */
/*! \file */
@@ -43,6 +43,8 @@ static dns_rdatasetmethods_t methods = {
isc__rdatalist_getnoqname,
NULL,
NULL,
+ NULL,
+ NULL,
NULL
};
diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c
index f3c062da2f5c4..56a386a9b51e3 100644
--- a/lib/dns/rdataset.c
+++ b/lib/dns/rdataset.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2006, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2006, 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.72.18.7 2009/01/19 23:46:15 tbox Exp $ */
+/* $Id: rdataset.c,v 1.72.18.9 2010/02/26 23:46:36 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);
+}
diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c
index 4255b1d0002cf..fb5a4b786d2e0 100644
--- a/lib/dns/rdataslab.c
+++ b/lib/dns/rdataslab.c
@@ -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: rdataslab.c,v 1.35.18.10 2009/01/19 23:46:15 tbox Exp $ */
+/* $Id: rdataslab.c,v 1.35.18.12 2010/02/26 23:46:36 tbox Exp $ */
/*! \file */
@@ -405,6 +405,8 @@ static dns_rdatasetmethods_t rdataset_methods = {
NULL,
NULL,
NULL,
+ NULL,
+ NULL,
NULL
};
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index 7b41e72da7299..95c7bd4a4f841 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: resolver.c,v 1.284.18.99 2010/01/07 23:46:07 tbox Exp $ */
+/* $Id: resolver.c,v 1.284.18.101 2010/02/26 23:46:36 tbox Exp $ */
/*! \file */
@@ -318,6 +318,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;
@@ -361,6 +373,13 @@ struct dns_resolver {
unsigned int activebuckets;
isc_boolean_t priming;
unsigned int spillat; /* clients-per-query */
+
+ /* 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. */
@@ -390,7 +409,7 @@ 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);
+static void fctx_try(fetchctx_t *fctx, 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,
@@ -1088,7 +1107,7 @@ process_sendevent(resquery_t *query, isc_event_t *event) {
if (result != ISC_R_SUCCESS)
fctx_done(fctx, result, __LINE__);
else
- fctx_try(fctx);
+ fctx_try(fctx, ISC_FALSE);
}
}
@@ -1946,7 +1965,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);
+ fctx_try(fctx, ISC_FALSE);
}
}
@@ -2008,7 +2027,7 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) {
dns_adb_destroyfind(&find);
if (want_try)
- fctx_try(fctx);
+ fctx_try(fctx, ISC_FALSE);
else if (want_done)
fctx_done(fctx, ISC_R_FAILURE, __LINE__);
else if (bucket_empty)
@@ -2371,7 +2390,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;
@@ -2590,12 +2609,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 {
@@ -2817,7 +2848,7 @@ fctx_nextaddress(fetchctx_t *fctx) {
}
static void
-fctx_try(fetchctx_t *fctx) {
+fctx_try(fetchctx_t *fctx, isc_boolean_t badcache) {
isc_result_t result;
dns_adbaddrinfo_t *addrinfo;
@@ -2835,7 +2866,7 @@ fctx_try(fetchctx_t *fctx) {
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.
@@ -2995,7 +3026,7 @@ fctx_timeout(isc_task_t *task, isc_event_t *event) {
/*
* Keep trying.
*/
- fctx_try(fctx);
+ fctx_try(fctx, ISC_FALSE);
}
isc_event_free(&event);
@@ -3165,7 +3196,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);
+ fctx_try(fctx, ISC_FALSE);
} else if (bucket_empty)
empty_bucket(res);
}
@@ -3740,6 +3771,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.
@@ -3785,36 +3818,80 @@ validated(isc_task_t *task, isc_event_t *event) {
FCTXTRACE("validation failed");
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); /* 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); /* Locks bucket. */
return;
}
- isc_stdtime_get(&now);
-
if (negative) {
dns_rdatatype_t covers;
FCTXTRACE("nonexistence validation OK");
@@ -5589,7 +5666,7 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) {
/*
* Try again.
*/
- fctx_try(fctx);
+ fctx_try(fctx, ISC_FALSE);
} else {
unsigned int n;
dns_rdataset_t *nsrdataset = NULL;
@@ -6329,7 +6406,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
/*
* Try again.
*/
- fctx_try(fctx);
+ fctx_try(fctx, ISC_FALSE);
} else if (resend) {
/*
* Resend (probably with changed options).
@@ -6390,6 +6467,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) {
@@ -6427,6 +6525,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);
@@ -6550,6 +6649,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;
@@ -7380,6 +7483,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;
diff --git a/lib/dns/result.c b/lib/dns/result.c
index fdb58e0df7f4e..504de7ebbf763 100644
--- a/lib/dns/result.c
+++ b/lib/dns/result.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: result.c,v 1.115.10.7 2005/06/17 02:04:31 marka Exp $ */
+/* $Id: result.c,v 1.115.10.9 2010/02/26 23:46:37 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] = {
diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c
index 972b72a985f8d..42a1ce3640961 100644
--- a/lib/dns/sdb.c
+++ b/lib/dns/sdb.c
@@ -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.45.18.19 2009/06/26 06:25:20 marka Exp $ */
+/* $Id: sdb.c,v 1.45.18.21 2010/02/26 23:46:37 tbox Exp $ */
/*! \file */
@@ -1374,6 +1374,8 @@ static dns_rdatasetmethods_t methods = {
isc__rdatalist_getnoqname,
NULL,
NULL,
+ NULL,
+ NULL,
NULL
};
diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c
index 6c9a521b05f2d..9dcaa57e33309 100644
--- a/lib/dns/sdlz.c
+++ b/lib/dns/sdlz.c
@@ -1,5 +1,5 @@
/*
- * Portions Copyright (C) 2005-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2005-2007, 2009, 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.2.2.14 2009/06/26 06:25:20 marka Exp $ */
+/* $Id: sdlz.c,v 1.2.2.16 2010/02/26 23:46:37 tbox Exp $ */
/*! \file */
@@ -1198,6 +1198,8 @@ static dns_rdatasetmethods_t rdataset_methods = {
isc__rdatalist_getnoqname,
NULL,
NULL,
+ NULL,
+ NULL,
NULL
};
diff --git a/lib/dns/validator.c b/lib/dns/validator.c
index 387c433f54501..9642791ad1ac6 100644
--- a/lib/dns/validator.c
+++ b/lib/dns/validator.c
@@ -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.119.18.51 2009/12/30 06:44:05 each Exp $ */
+/* $Id: validator.c,v 1.119.18.53 2010/02/26 23:46:37 tbox Exp $ */
/*! \file */
@@ -170,9 +170,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
@@ -337,7 +344,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);
@@ -407,7 +414,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);
@@ -547,10 +554,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);
@@ -597,10 +610,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);
@@ -802,6 +821,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 {
@@ -867,6 +888,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) {
@@ -876,9 +898,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);
@@ -888,6 +913,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;
@@ -896,6 +931,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);
@@ -1240,7 +1276,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);
@@ -1255,7 +1292,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)
@@ -1503,8 +1541,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);
@@ -1680,8 +1717,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) {
@@ -1782,8 +1818,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");
@@ -1810,11 +1845,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);
}
@@ -1875,7 +1913,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);
}
/*
@@ -2024,8 +2063,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) {
@@ -2231,6 +2269,7 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
"nsecvalidate");
if (result != ISC_R_SUCCESS)
return (result);
+ val->authcount++;
return (DNS_R_WAIT);
}
@@ -2252,8 +2291,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),
@@ -2284,6 +2322,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;
@@ -2315,6 +2355,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.
*
@@ -2534,6 +2626,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;
@@ -2584,6 +2694,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)
@@ -2800,7 +2911,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 */
@@ -3007,6 +3119,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);
diff --git a/lib/dns/view.c b/lib/dns/view.c
index 4851cf0084557..801654be365d1 100644
--- a/lib/dns/view.c
+++ b/lib/dns/view.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008, 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.126.18.16 2008/06/17 23:46:03 tbox Exp $ */
+/* $Id: view.c,v 1.126.18.18 2010/02/26 23:46:37 tbox Exp $ */
/*! \file */
@@ -1194,10 +1194,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);
}
@@ -1218,6 +1219,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);
@@ -1232,6 +1235,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));
}