diff --git a/lib/dns/include/dns/rdataset.h b/lib/dns/include/dns/rdataset.h index 289cfa6dd6..e54fbc6b6b 100644 --- a/lib/dns/include/dns/rdataset.h +++ b/lib/dns/include/dns/rdataset.h @@ -100,6 +100,8 @@ struct dns_rdatasetmethods { isc_result_t (*addglue)(dns_rdataset_t *rdataset, dns_dbversion_t *version, dns_message_t *msg); dns_slabheader_t *(*getheader)(const dns_rdataset_t *rdataset); + bool (*equals)(const dns_rdataset_t *rdataset1, + const dns_rdataset_t *rdataset2); }; #define DNS_RDATASET_MAGIC ISC_MAGIC('D', 'N', 'S', 'R') @@ -676,3 +678,14 @@ dns_rdataset_getheader(const dns_rdataset_t *rdataset); * Requires: * \li 'rdataset' is a valid rdataset. */ + +bool +dns_rdataset_equals(const dns_rdataset_t *rdataset1, + const dns_rdataset_t *rdataset2); +/*%< + * Returns true if the rdata in the rdataset is equal. + * + * Requires: + * \li 'rdataset1' is a valid rdataset. + * \li 'rdataset2' is a valid rdataset. + */ diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c index ceef803ee5..d0962fe95e 100644 --- a/lib/dns/rdataset.c +++ b/lib/dns/rdataset.c @@ -659,3 +659,18 @@ dns_rdataset_getheader(const dns_rdataset_t *rdataset) { return NULL; } + +bool +dns_rdataset_equals(const dns_rdataset_t *rdataset1, + const dns_rdataset_t *rdataset2) { + REQUIRE(DNS_RDATASET_VALID(rdataset1)); + REQUIRE(DNS_RDATASET_VALID(rdataset2)); + + if (rdataset1->methods->equals != NULL && + rdataset1->methods->equals == rdataset2->methods->equals) + { + return (rdataset1->methods->equals)(rdataset1, rdataset2); + } + + return false; +} diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c index 65b803d162..e4fce867ba 100644 --- a/lib/dns/rdataslab.c +++ b/lib/dns/rdataslab.c @@ -115,6 +115,9 @@ static void rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name); static dns_slabheader_t * rdataset_getheader(const dns_rdataset_t *rdataset); +static bool +rdataset_equals(const dns_rdataset_t *rdataset1, + const dns_rdataset_t *rdataset2); /*% Note: the "const void *" are just to make qsort happy. */ static int @@ -943,6 +946,7 @@ dns_rdatasetmethods_t dns_rdataslab_rdatasetmethods = { .setownercase = rdataset_setownercase, .getownercase = rdataset_getownercase, .getheader = rdataset_getheader, + .equals = rdataset_equals, }; /* Fixed RRSet helper macros */ @@ -1234,3 +1238,19 @@ rdataset_getheader(const dns_rdataset_t *rdataset) { dns_slabheader_t *header = (dns_slabheader_t *)rdataset->slab.raw; return header - 1; } + +static bool +rdataset_equals(const dns_rdataset_t *rdataset1, + const dns_rdataset_t *rdataset2) { + if (rdataset1->rdclass != rdataset2->rdclass || + rdataset1->type != rdataset2->type) + { + return false; + } + + dns_slabheader_t *header1 = (dns_slabheader_t *)rdataset1->slab.raw - 1; + dns_slabheader_t *header2 = (dns_slabheader_t *)rdataset2->slab.raw - 1; + + return dns_rdataslab_equalx(header1, header2, rdataset1->rdclass, + rdataset2->type); +} diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index ec23f3b185..e99e21c763 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -6096,33 +6096,43 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_message_t *message, if (result == DNS_R_UNCHANGED) { result = ISC_R_SUCCESS; if (!need_validation && - ardataset != NULL && - NEGATIVE(ardataset)) + ardataset != NULL) { /* * The answer in the * cache is better than - * the answer we found, - * and is a negative - * cache entry, so we + * the answer we found. + * If it's a negative + * cache entry, we * must set eresult * appropriately. */ if (NXDOMAIN(ardataset)) { eresult = DNS_R_NCACHENXDOMAIN; - } else { + } else if (NEGATIVE(ardataset)) + { eresult = DNS_R_NCACHENXRRSET; } + /* - * We have a negative - * response from the - * cache so don't - * attempt to add the - * RRSIG rrset. + * The cache wasn't updated + * because something was + * already there. If the + * data was the same as what + * we were trying to add, + * then sigrdataset might + * still be useful. If + * not, move on. */ - continue; + if (sigrdataset != NULL && + !dns_rdataset_equals( + rdataset, + addedrdataset)) + { + continue; + } } } if (result != ISC_R_SUCCESS) {