* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ncache.h,v 1.15 2002/02/20 03:34:35 marka Exp $ */
+/* $Id: ncache.h,v 1.16 2002/07/19 03:29:15 marka Exp $ */
#ifndef DNS_NCACHE_H
#define DNS_NCACHE_H 1
* dns_name_towire().
*/
+isc_result_t
+dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdataset_t *rdataset);
+/*
+ * Search the negative caching rdataset for an rdataset with the
+ * specified name and type.
+ *
+ * Requires:
+ * 'ncacherdataset' is a valid negative caching rdataset.
+ *
+ * 'ncacherdataset' is not empty.
+ *
+ * 'name' is a valid name.
+ *
+ * 'type' is not SIG, or a meta-RR type.
+ *
+ * 'rdataset' is a valid disassociated rdataset.
+ *
+ * Ensures:
+ * On a return of ISC_R_SUCCESS, 'rdataset' is bound to the found
+ * rdataset.
+ *
+ * Returns:
+ * ISC_R_SUCCESS - the rdataset was found.
+ * ISC_R_NOTFOUND - the rdataset was not found.
+ *
+ */
+
ISC_LANG_ENDDECLS
#endif /* DNS_NCACHE_H */
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: ncache.c,v 1.29 2002/02/20 03:34:15 marka Exp $ */
+/* $Id: ncache.c,v 1.30 2002/07/19 03:29:15 marka Exp $ */
#include <config.h>
return (result);
}
+
+static void
+rdataset_disassociate(dns_rdataset_t *rdataset) {
+ UNUSED(rdataset);
+}
+
+static isc_result_t
+rdataset_first(dns_rdataset_t *rdataset) {
+ unsigned char *raw = rdataset->private3;
+ unsigned int count;
+
+ count = raw[0] * 256 + raw[1];
+ if (count == 0) {
+ rdataset->private5 = NULL;
+ return (ISC_R_NOMORE);
+ }
+ raw += 2;
+ /*
+ * The private4 field is the number of rdata beyond the cursor
+ * position, so we decrement the total count by one before storing
+ * it.
+ */
+ count--;
+ rdataset->private4 = (void *)count;
+ rdataset->private5 = raw;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+rdataset_next(dns_rdataset_t *rdataset) {
+ unsigned int count;
+ unsigned int length;
+ unsigned char *raw;
+
+ count = (unsigned int)rdataset->private4;
+ if (count == 0)
+ return (ISC_R_NOMORE);
+ count--;
+ rdataset->private4 = (void *)count;
+ raw = rdataset->private5;
+ length = raw[0] * 256 + raw[1];
+ raw += length + 2;
+ rdataset->private5 = raw;
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
+ unsigned char *raw = rdataset->private5;
+ isc_region_t r;
+
+ REQUIRE(raw != NULL);
+
+ r.length = raw[0] * 256 + raw[1];
+ raw += 2;
+ r.base = raw;
+ dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
+}
+
+static void
+rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
+ *target = *source;
+
+ /*
+ * Reset iterator state.
+ */
+ target->private4 = NULL;
+ target->private5 = NULL;
+}
+
+static unsigned int
+rdataset_count(dns_rdataset_t *rdataset) {
+ unsigned char *raw = rdataset->private3;
+ unsigned int count;
+
+ count = raw[0] * 256 + raw[1];
+
+ return (count);
+}
+
+static dns_rdatasetmethods_t rdataset_methods = {
+ rdataset_disassociate,
+ rdataset_first,
+ rdataset_next,
+ rdataset_current,
+ rdataset_clone,
+ rdataset_count
+};
+
+isc_result_t
+dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdataset_t *rdataset)
+{
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_region_t remaining;
+ isc_buffer_t source;
+ dns_name_t tname;
+ dns_rdatatype_t ttype;
+ unsigned int i, rcount;
+ isc_uint16_t length;
+
+ REQUIRE(ncacherdataset != NULL);
+ REQUIRE(ncacherdataset->type == 0);
+ REQUIRE(name != NULL);
+ REQUIRE(!dns_rdataset_isassociated(rdataset));
+ REQUIRE(type != dns_rdatatype_sig);
+
+ result = dns_rdataset_first(ncacherdataset);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_rdataset_current(ncacherdataset, &rdata);
+ INSIST(dns_rdataset_next(ncacherdataset) == ISC_R_NOMORE);
+ isc_buffer_init(&source, rdata.data, rdata.length);
+ isc_buffer_add(&source, rdata.length);
+
+ do {
+ dns_name_init(&tname, NULL);
+ isc_buffer_remainingregion(&source, &remaining);
+ dns_name_fromregion(&tname, &remaining);
+ INSIST(remaining.length >= tname.length);
+ isc_buffer_forward(&source, tname.length);
+ remaining.length -= tname.length;
+
+ INSIST(remaining.length >= 4);
+ ttype = isc_buffer_getuint16(&source);
+
+ if (ttype == type && dns_name_equal(&tname, name)) {
+ isc_buffer_remainingregion(&source, &remaining);
+ break;
+ }
+
+ rcount = isc_buffer_getuint16(&source);
+ for (i = 0; i < rcount; i++) {
+ isc_buffer_remainingregion(&source, &remaining);
+ INSIST(remaining.length >= 2);
+ length = isc_buffer_getuint16(&source);
+ isc_buffer_remainingregion(&source, &remaining);
+ INSIST(remaining.length >= length);
+ isc_buffer_forward(&source, length);
+ }
+ isc_buffer_remainingregion(&source, &remaining);
+ } while (remaining.length > 0);
+
+ if (remaining.length == 0)
+ return (ISC_R_NOTFOUND);
+
+ rdataset->methods = &rdataset_methods;
+ rdataset->rdclass = ncacherdataset->rdclass;
+ rdataset->type = type;
+ rdataset->covers = 0;
+ rdataset->ttl = ncacherdataset->ttl;
+ rdataset->trust = ncacherdataset->trust;
+ rdataset->private1 = NULL;
+ rdataset->private2 = NULL;
+
+ rdataset->private3 = remaining.base;
+
+ /*
+ * Reset iterator state.
+ */
+ rdataset->private4 = NULL;
+ rdataset->private5 = NULL;
+ return (ISC_R_SUCCESS);
+}
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: validator.c,v 1.108 2002/07/15 03:25:28 marka Exp $ */
+/* $Id: validator.c,v 1.109 2002/07/19 03:29:15 marka Exp $ */
#include <config.h>
#include <dns/keytable.h>
#include <dns/log.h>
#include <dns/message.h>
+#include <dns/ncache.h>
#include <dns/nxt.h>
#include <dns/rdata.h>
#include <dns/rdatastruct.h>
#include <dns/view.h>
#define VALIDATOR_MAGIC ISC_MAGIC('V', 'a', 'l', '?')
-#define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
+#define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
#define VALATTR_SHUTDOWN 0x01
#define VALATTR_FOUNDNONEXISTENCE 0x02
}
}
+static isc_boolean_t
+isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
+ isc_result_t dbresult)
+{
+ dns_rdataset_t set;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_boolean_t found;
+ isc_result_t result;
+
+ REQUIRE(dbresult == DNS_R_NXRRSET || dbresult == DNS_R_NCACHENXRRSET);
+
+ dns_rdataset_init(&set);
+ if (dbresult == DNS_R_NXRRSET)
+ dns_rdataset_clone(rdataset, &set);
+ else {
+ result = dns_ncache_getrdataset(rdataset, name,
+ dns_rdatatype_nxt, &set);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_FALSE);
+ }
+
+ INSIST(set.type == dns_rdatatype_nxt);
+
+ found = ISC_FALSE;
+ result = dns_rdataset_first(&set);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(&set, &rdata);
+ found = dns_nxt_typepresent(&rdata, dns_rdatatype_ns);
+ }
+ dns_rdataset_disassociate(&set);
+ return (found);
+}
+
static void
fetch_callback_validator(isc_task_t *task, isc_event_t *event) {
dns_fetchevent_t *devent;
dns_fetchevent_t *devent;
dns_validator_t *val;
dns_rdataset_t *rdataset;
+ dns_name_t *tname;
isc_boolean_t want_destroy;
isc_result_t result;
isc_result_t eresult;
rdataset = &val->frdataset;
eresult = devent->result;
- isc_event_free(&event);
dns_resolver_destroyfetch(&val->fetch);
INSIST(val->event != NULL);
LOCK(&val->lock);
if (eresult == DNS_R_NXRRSET || eresult == DNS_R_NCACHENXRRSET) {
/*
- * There is no DS. We're done.
+ * There is no DS. If this is a delegation, we're done.
*/
- val->event->rdataset->trust = dns_trust_answer;
- validator_done(val, ISC_R_SUCCESS);
+ tname = dns_fixedname_name(&devent->foundname);
+ if (isdelegation(tname, &val->frdataset, eresult)) {
+ val->event->rdataset->trust = dns_trust_answer;
+ validator_done(val, ISC_R_SUCCESS);
+ } else {
+ result = proveunsecure(val, ISC_TRUE);
+ if (result != DNS_R_WAIT)
+ validator_done(val, result);
+ }
} else if (eresult == ISC_R_SUCCESS ||
eresult == DNS_R_NXDOMAIN ||
eresult == DNS_R_NCACHENXDOMAIN)
else
validator_done(val, DNS_R_NOVALIDDS);
}
+ isc_event_free(&event);
want_destroy = exit_check(val);
UNLOCK(&val->lock);
if (want_destroy)
result = view_find(val, tname, dns_rdatatype_ds);
if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
/*
- * There is no DS. We're hopefully done.
+ * There is no DS. If this is a delegation,
+ * we're done.
*/
if (val->frdataset.trust < dns_trust_secure) {
/*
result = DNS_R_NOVALIDSIG;
goto out;
}
- val->event->rdataset->trust = dns_trust_answer;
- return (ISC_R_SUCCESS);
+ if (isdelegation(tname, &val->frdataset, result)) {
+ val->event->rdataset->trust = dns_trust_answer;
+ return (ISC_R_SUCCESS);
+ }
+ continue;
} else if (result == ISC_R_SUCCESS) {
/*
- * There is a DS here. Verify that it's secure and
+ * There is a DS here. Verify that it's secure and
* continue.
*/
if (val->frdataset.trust >= dns_trust_secure)
result == DNS_R_NCACHENXDOMAIN)
{
/*
- * This is not a zone cut. Assuming things are
+ * This is not a zone cut. Assuming things are
* as expected, continue.
*/
if (!dns_rdataset_isassociated(&val->frdataset)) {