mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 06:55:30 +00:00
Check whether a rejected rrset is different
Add a new dns_rdataset_equals() function to check whether two rdatasets are equal in DNSSEC terms. When an rdataset being cached is rejected because its trust level is lower than the existing rdataset, we now check to see whether the rejected data was identical to the existing data. This allows us to cache a potentially useful RRSIG when handling CD=1 queries, while still rejecting RRSIGs that would definitely have resulted in a validation failure.
This commit is contained in:
@@ -100,6 +100,8 @@ struct dns_rdatasetmethods {
|
|||||||
isc_result_t (*addglue)(dns_rdataset_t *rdataset,
|
isc_result_t (*addglue)(dns_rdataset_t *rdataset,
|
||||||
dns_dbversion_t *version, dns_message_t *msg);
|
dns_dbversion_t *version, dns_message_t *msg);
|
||||||
dns_slabheader_t *(*getheader)(const dns_rdataset_t *rdataset);
|
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')
|
#define DNS_RDATASET_MAGIC ISC_MAGIC('D', 'N', 'S', 'R')
|
||||||
@@ -676,3 +678,14 @@ dns_rdataset_getheader(const dns_rdataset_t *rdataset);
|
|||||||
* Requires:
|
* Requires:
|
||||||
* \li 'rdataset' is a valid rdataset.
|
* \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.
|
||||||
|
*/
|
||||||
|
@@ -659,3 +659,18 @@ dns_rdataset_getheader(const dns_rdataset_t *rdataset) {
|
|||||||
|
|
||||||
return NULL;
|
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;
|
||||||
|
}
|
||||||
|
@@ -115,6 +115,9 @@ static void
|
|||||||
rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name);
|
rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name);
|
||||||
static dns_slabheader_t *
|
static dns_slabheader_t *
|
||||||
rdataset_getheader(const dns_rdataset_t *rdataset);
|
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. */
|
/*% Note: the "const void *" are just to make qsort happy. */
|
||||||
static int
|
static int
|
||||||
@@ -943,6 +946,7 @@ dns_rdatasetmethods_t dns_rdataslab_rdatasetmethods = {
|
|||||||
.setownercase = rdataset_setownercase,
|
.setownercase = rdataset_setownercase,
|
||||||
.getownercase = rdataset_getownercase,
|
.getownercase = rdataset_getownercase,
|
||||||
.getheader = rdataset_getheader,
|
.getheader = rdataset_getheader,
|
||||||
|
.equals = rdataset_equals,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Fixed RRSet helper macros */
|
/* 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;
|
dns_slabheader_t *header = (dns_slabheader_t *)rdataset->slab.raw;
|
||||||
return header - 1;
|
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);
|
||||||
|
}
|
||||||
|
@@ -6096,33 +6096,43 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_message_t *message,
|
|||||||
if (result == DNS_R_UNCHANGED) {
|
if (result == DNS_R_UNCHANGED) {
|
||||||
result = ISC_R_SUCCESS;
|
result = ISC_R_SUCCESS;
|
||||||
if (!need_validation &&
|
if (!need_validation &&
|
||||||
ardataset != NULL &&
|
ardataset != NULL)
|
||||||
NEGATIVE(ardataset))
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* The answer in the
|
* The answer in the
|
||||||
* cache is better than
|
* cache is better than
|
||||||
* the answer we found,
|
* the answer we found.
|
||||||
* and is a negative
|
* If it's a negative
|
||||||
* cache entry, so we
|
* cache entry, we
|
||||||
* must set eresult
|
* must set eresult
|
||||||
* appropriately.
|
* appropriately.
|
||||||
*/
|
*/
|
||||||
if (NXDOMAIN(ardataset)) {
|
if (NXDOMAIN(ardataset)) {
|
||||||
eresult =
|
eresult =
|
||||||
DNS_R_NCACHENXDOMAIN;
|
DNS_R_NCACHENXDOMAIN;
|
||||||
} else {
|
} else if (NEGATIVE(ardataset))
|
||||||
|
{
|
||||||
eresult =
|
eresult =
|
||||||
DNS_R_NCACHENXRRSET;
|
DNS_R_NCACHENXRRSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have a negative
|
* The cache wasn't updated
|
||||||
* response from the
|
* because something was
|
||||||
* cache so don't
|
* already there. If the
|
||||||
* attempt to add the
|
* data was the same as what
|
||||||
* RRSIG rrset.
|
* 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) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
Reference in New Issue
Block a user