diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index afd9a174ea..ffa6f1225f 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -238,7 +238,7 @@ find_keys(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name, *nkeys = 0; dns_rdataset_init(&rdataset); result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_key, 0, 0, - &rdataset); + &rdataset, NULL); check_result(result, "dns_db_findrdataset()"); result = dns_rdataset_first(&rdataset); check_result(result, "dns_rdataset_first()"); diff --git a/bin/tests/db/t_db.c b/bin/tests/db/t_db.c index df1194d379..d2a05a94f3 100644 --- a/bin/tests/db/t_db.c +++ b/bin/tests/db/t_db.c @@ -2182,8 +2182,9 @@ t_dns_db_findnode_1(char **av) { dns_db_currentversion(db, &cversionp); dns_rdataset_init(&rdataset); - dns_result = dns_db_findrdataset(db, nodep, cversionp, rdatatype, 0, - 0, &rdataset); + dns_result = dns_db_findrdataset(db, nodep, cversionp, + rdatatype, 0, + 0, &rdataset, NULL); if (dns_result == DNS_R_SUCCESS) { dns_rdataset_disassociate(&rdataset); result = T_PASS; diff --git a/bin/tests/signer.c b/bin/tests/signer.c index afd9a174ea..ffa6f1225f 100644 --- a/bin/tests/signer.c +++ b/bin/tests/signer.c @@ -238,7 +238,7 @@ find_keys(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name, *nkeys = 0; dns_rdataset_init(&rdataset); result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_key, 0, 0, - &rdataset); + &rdataset, NULL); check_result(result, "dns_db_findrdataset()"); result = dns_rdataset_first(&rdataset); check_result(result, "dns_rdataset_first()"); diff --git a/lib/dns/db.c b/lib/dns/db.c index a8ecf0413a..c4156fe55c 100644 --- a/lib/dns/db.c +++ b/lib/dns/db.c @@ -451,7 +451,8 @@ dns_db_createiterator(dns_db_t *db, isc_boolean_t relative_names, dns_result_t dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_rdatatype_t type, dns_rdatatype_t covers, - isc_stdtime_t now, dns_rdataset_t *rdataset) + isc_stdtime_t now, dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset) { /* * Search for an rdataset of type 'type' at 'node' that are in version @@ -464,9 +465,12 @@ dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, REQUIRE(rdataset->methods == NULL); REQUIRE(covers == 0 || type == dns_rdatatype_sig); REQUIRE(type != dns_rdatatype_any); + REQUIRE(sigrdataset == NULL || + (DNS_RDATASET_VALID(sigrdataset) && + sigrdataset->methods == NULL)); return ((db->methods->findrdataset)(db, node, version, type, covers, - now, rdataset)); + now, rdataset, sigrdataset)); } dns_result_t diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h index 05f24afeec..e5c4f72d2f 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -115,7 +115,8 @@ typedef struct dns_dbmethods { dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now, - dns_rdataset_t *rdataset); + dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset); dns_result_t (*allrdatasets)(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, isc_stdtime_t now, @@ -802,7 +803,8 @@ dns_db_createiterator(dns_db_t *db, isc_boolean_t relative_names, dns_result_t dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_rdatatype_t type, dns_rdatatype_t covers, - isc_stdtime_t now, dns_rdataset_t *rdataset); + isc_stdtime_t now, dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset); /* * Search for an rdataset of type 'type' at 'node' that are in version * 'version' of 'db'. If found, make 'rdataset' refer to it. @@ -811,9 +813,9 @@ dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, * * If 'version' is NULL, then the current version will be used. * - * This routine is not suitable for use in building responses to - * ordinary DNS queries; clients which wish to do that should use - * dns_db_find() instead. + * Care must be used when using this routine to build a DNS response: + * 'node' should have been found with dns_db_find(), not + * dns_db_findnode(). No glue checking is done. * * The 'now' field is ignored if 'db' is a zone database. If 'db' is a * cache database, an rdataset will not be found unless it expires after @@ -827,6 +829,8 @@ dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, * * 'rdataset' is a valid, disassociated rdataset. * + * 'sigrdataset' is a valid, disassociated rdataset, or it is NULL. + * * If 'covers' != 0, 'type' must be SIG. * * 'type' is not a meta-RR type such as 'ANY' or 'OPT'. diff --git a/lib/dns/journal.c b/lib/dns/journal.c index b09b0b32da..e5269e2f96 100644 --- a/lib/dns/journal.c +++ b/lib/dns/journal.c @@ -124,7 +124,7 @@ dns_db_getsoaserial(dns_db_t *db, dns_dbversion_t *ver, isc_uint32_t *serialp) dns_rdataset_init(&rdataset); result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa, 0, - (isc_stdtime_t) 0, &rdataset); + (isc_stdtime_t) 0, &rdataset, NULL); if (result != DNS_R_SUCCESS) goto freenode; @@ -165,7 +165,7 @@ dns_db_createsoatuple(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx, dns_rdataset_init(&rdataset); result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa, 0, - (isc_stdtime_t) 0, &rdataset); + (isc_stdtime_t) 0, &rdataset, NULL); if (result != DNS_R_SUCCESS) goto freenode; diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 68680cfc27..a10a8cb164 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -2569,15 +2569,16 @@ createiterator(dns_db_t *db, isc_boolean_t relative_names, static dns_result_t zone_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_rdatatype_t type, dns_rdatatype_t covers, - isc_stdtime_t now, dns_rdataset_t *rdataset) + isc_stdtime_t now, dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset) { dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node; - rdatasetheader_t *header; + rdatasetheader_t *header, *found, *foundsig; rbtdb_serial_t serial; rbtdb_version_t *rbtversion = version; isc_boolean_t close_version = ISC_FALSE; - rbtdb_rdatatype_t matchtype; + rbtdb_rdatatype_t matchtype, sigmatchtype; REQUIRE(VALID_RBTDB(rbtdb)); REQUIRE(type != dns_rdatatype_any); @@ -2587,38 +2588,62 @@ zone_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, close_version = ISC_TRUE; } serial = rbtversion->serial; + now = 0; LOCK(&rbtdb->node_locks[rbtnode->locknum].lock); + found = NULL; + foundsig = NULL; matchtype = RBTDB_RDATATYPE_VALUE(type, covers); + if (covers == 0) + sigmatchtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_sig, type); + else + sigmatchtype = 0; + for (header = rbtnode->data; header != NULL; header = header->next) { - if (header->type == matchtype) { - do { - if (header->serial <= serial && - !IGNORE(header)) { - /* - * Is this a "this rdataset doesn't - * exist" record? - */ - if ((header->attributes & - RDATASET_ATTR_NONEXISTENT) != 0) - header = NULL; + do { + if (header->serial <= serial && + !IGNORE(header)) { + /* + * Is this a "this rdataset doesn't + * exist" record? + */ + if ((header->attributes & + RDATASET_ATTR_NONEXISTENT) != 0) + header = NULL; + break; + } else + header = header->down; + } while (header != NULL); + if (header != NULL) { + /* + * We have an active, extant rdataset. If it's a + * type we're looking for, remember it. + */ + if (header->type == matchtype) { + found = header; + if (foundsig != NULL) break; - } else - header = header->down; - } while (header != NULL); - break; + } else if (header->type == sigmatchtype) { + foundsig = header; + if (found != NULL) + break; + } } } - if (header != NULL) - bind_rdataset(rbtdb, rbtnode, header, now, rdataset); + if (found != NULL) { + bind_rdataset(rbtdb, rbtnode, found, now, rdataset); + if (foundsig != NULL) + bind_rdataset(rbtdb, rbtnode, foundsig, now, + sigrdataset); + } UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock); if (close_version) closeversion(db, (dns_dbversion_t **)(&rbtversion), ISC_FALSE); - if (header == NULL) + if (found == NULL) return (DNS_R_NOTFOUND); return (DNS_R_SUCCESS); @@ -2627,12 +2652,13 @@ zone_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, static dns_result_t cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, dns_rdatatype_t type, dns_rdatatype_t covers, - isc_stdtime_t now, dns_rdataset_t *rdataset) + isc_stdtime_t now, dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset) { dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node; - rdatasetheader_t *header, *header_next, *found; - rbtdb_rdatatype_t matchtype; + rdatasetheader_t *header, *header_next, *found, *foundsig; + rbtdb_rdatatype_t matchtype, sigmatchtype; REQUIRE(VALID_RBTDB(rbtdb)); REQUIRE(type != dns_rdatatype_any); @@ -2650,7 +2676,13 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, LOCK(&rbtdb->node_locks[rbtnode->locknum].lock); found = NULL; + foundsig = NULL; matchtype = RBTDB_RDATATYPE_VALUE(type, covers); + if (covers == 0) + sigmatchtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_sig, type); + else + sigmatchtype = 0; + for (header = rbtnode->data; header != NULL; header = header_next) { header_next = header->next; if (header->ttl <= now) { @@ -2666,10 +2698,18 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, (header->attributes & RDATASET_ATTR_NONEXISTENT) == 0) { found = header; + } else if (header->type == sigmatchtype && + (header->attributes & RDATASET_ATTR_NONEXISTENT) == + 0) { + foundsig = header; } } - if (found != NULL) + if (found != NULL) { bind_rdataset(rbtdb, rbtnode, found, now, rdataset); + if (foundsig != NULL) + bind_rdataset(rbtdb, rbtnode, foundsig, now, + sigrdataset); + } UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock); diff --git a/lib/dns/zone.c b/lib/dns/zone.c index eb5deab90f..94cd0b2a6e 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: zone.c,v 1.3 1999/09/03 20:59:50 brister Exp $ */ + /* $Id: zone.c,v 1.4 1999/09/08 01:09:48 halley Exp $ */ #include @@ -499,7 +499,8 @@ dns_zone_load(dns_zone_t *zone) { dns_rdataset_init(&rdataset); result = dns_db_findrdataset(zone->top, node, version, dns_rdatatype_ns, - dns_rdatatype_none, 0, &rdataset); + dns_rdatatype_none, 0, &rdataset, + NULL); if (result == DNS_R_SUCCESS) { result = dns_rdataset_first(&rdataset); while (result == DNS_R_SUCCESS) { @@ -511,7 +512,8 @@ dns_zone_load(dns_zone_t *zone) { dns_rdataset_disassociate(&rdataset); result = dns_db_findrdataset(zone->top, node, version, dns_rdatatype_soa, - dns_rdatatype_none, 0, &rdataset); + dns_rdatatype_none, 0, &rdataset, + NULL); if (result == DNS_R_SUCCESS) { result = dns_rdataset_first(&rdataset); @@ -605,7 +607,8 @@ dns_zone_checkservers(dns_zone_t *zone) { dns_rdataset_init(&rdataset); result = dns_db_findrdataset(zone->top, node, version, dns_rdatatype_ns, - dns_rdatatype_none, 0, &rdataset); + dns_rdatatype_none, 0, &rdataset, + NULL); if (result == DNS_R_SUCCESS) { result = dns_rdataset_first(&rdataset); while (result == DNS_R_SUCCESS) { @@ -1593,7 +1596,7 @@ dns_zone_notify(dns_zone_t *zone) { dns_rdataset_init(&nsrdset); result = dns_db_findrdataset(zone->top, node, version, dns_rdatatype_ns, - dns_rdatatype_none, 0, &nsrdset); + dns_rdatatype_none, 0, &nsrdset, NULL); if (result != DNS_R_SUCCESS) goto cleanup2;