diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index 7e52231501..05f7d769fd 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -4620,5 +4620,16 @@ n=$((n + 1)) if [ "$ret" -ne 0 ]; then echo_i "failed"; fi status=$((status + ret)) +echo_i "test that RRSIGS are returned for glue name with CD=1 ($n)" +ret=0 +dig_with_opts @10.53.0.4 ns3.secure.example A +cd >dig.out.ns4.test$n +grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns4.test$n >/dev/null || ret=1 +grep "ns3\.secure\.example\..[0-9]*.IN.A.10\.53\.0.3" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ns3\.secure\.example\..[0-9]*.IN.RRSIG.A " dig.out.ns4.test$n >/dev/null || ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + echo_i "exit status: $status" [ $status -eq 0 ] || exit 1 diff --git a/lib/dns/dnsrps.c b/lib/dns/dnsrps.c index e1bf958e57..3cbc98583c 100644 --- a/lib/dns/dnsrps.c +++ b/lib/dns/dnsrps.c @@ -996,7 +996,6 @@ static dns_rdatasetmethods_t rpsdb_rdataset_methods = { NULL, NULL, NULL, - NULL }; static dns_rdatasetitermethods_t rpsdb_rdatasetiter_methods = { diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h index 5eb2cea58f..882b568b68 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -287,6 +287,7 @@ struct dns_dbonupdatelistener { #define DNS_DBADD_EXACT 0x04 #define DNS_DBADD_EXACTTTL 0x08 #define DNS_DBADD_PREFETCH 0x10 +#define DNS_DBADD_EQUALOK 0x20 /*@}*/ /*% @@ -1228,6 +1229,10 @@ dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, * the old and new rdata sets. If #DNS_DBADD_EXACTTTL is set then both * the old and new rdata sets must have the same ttl. * + * \li If the #DNS_DBADD_EQUALOK option is set, and the database is not + * changed, compare the old and new rdatasets; if they are equal, + * return #ISC_R_SUCCESS instead of #DNS_R_UNCHANGED. + * * \li The 'now' field is ignored if 'db' is a zone database. If 'db' is * a cache database, then the added rdataset will expire no later than * now + rdataset->ttl. @@ -1257,8 +1262,12 @@ dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, * Returns: * * \li #ISC_R_SUCCESS - * \li #DNS_R_UNCHANGED The operation did not change - * anything. \li #ISC_R_NOMEMORY \li #DNS_R_NOTEXACT + * \li #DNS_R_UNCHANGED The operation did not change anything. + * \li #ISC_R_NOMEMORY + * \li #DNS_R_NOTEXACT The TTL didn't match and #DNS_DBADD_EXACTTTL + * was set, or there was a partial overlap + * between the old and new rdatasets and + * DNS_DBADD_EXACT was set. * * \li Other results are possible, depending upon the database * implementation used. diff --git a/lib/dns/include/dns/rdataset.h b/lib/dns/include/dns/rdataset.h index fec02474cf..caa49c5845 100644 --- a/lib/dns/include/dns/rdataset.h +++ b/lib/dns/include/dns/rdataset.h @@ -86,8 +86,6 @@ typedef struct dns_rdatasetmethods { void (*getownercase)(const dns_rdataset_t *rdataset, dns_name_t *name); isc_result_t (*addglue)(dns_rdataset_t *rdataset, dns_dbversion_t *version, dns_message_t *msg); - bool (*equals)(const dns_rdataset_t *rdataset1, - const dns_rdataset_t *rdataset2); } dns_rdatasetmethods_t; #define DNS_RDATASET_MAGIC ISC_MAGIC('D', 'N', 'S', 'R') @@ -631,14 +629,4 @@ dns_trust_totext(dns_trust_t trust); * Display trust in textual form. */ -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. - */ ISC_LANG_ENDDECLS diff --git a/lib/dns/keytable.c b/lib/dns/keytable.c index 215afa340b..bab4db0a75 100644 --- a/lib/dns/keytable.c +++ b/lib/dns/keytable.c @@ -91,7 +91,6 @@ static dns_rdatasetmethods_t methods = { NULL, NULL, NULL, /* addglue */ - NULL, /* equals */ }; static void diff --git a/lib/dns/ncache.c b/lib/dns/ncache.c index 4018aa9738..c99c2665ae 100644 --- a/lib/dns/ncache.c +++ b/lib/dns/ncache.c @@ -525,7 +525,6 @@ static dns_rdatasetmethods_t rdataset_methods = { NULL, /* setownercase */ NULL, /* getownercase */ NULL, /* addglue */ - NULL, /* equals */ }; isc_result_t diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 54363c0319..82cb74db26 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -610,9 +610,6 @@ rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name); static isc_result_t rdataset_addglue(dns_rdataset_t *rdataset, dns_dbversion_t *version, dns_message_t *msg); -static bool -rdataset_equals(const dns_rdataset_t *rdataset1, - const dns_rdataset_t *rdataset2); static void free_gluetable(rbtdb_version_t *version); static isc_result_t @@ -633,8 +630,7 @@ static dns_rdatasetmethods_t rdataset_methods = { rdataset_disassociate, rdataset_clearprefetch, rdataset_setownercase, rdataset_getownercase, - rdataset_addglue, - rdataset_equals }; + rdataset_addglue }; static dns_rdatasetmethods_t slab_methods = { rdataset_disassociate, @@ -653,7 +649,6 @@ static dns_rdatasetmethods_t slab_methods = { NULL, /* setownercase */ NULL, /* getownercase */ NULL, /* addglue */ - NULL, /* equals */ }; static void @@ -6510,13 +6505,22 @@ find_header: if (rbtversion == NULL && trust < header->trust && (ACTIVE(header, now) || header_nx)) { - free_rdataset(rbtdb, rbtdb->common.mctx, newheader); - if (addedrdataset != NULL) { - bind_rdataset(rbtdb, rbtnode, header, now, - isc_rwlocktype_write, - addedrdataset); + result = DNS_R_UNCHANGED; + bind_rdataset(rbtdb, rbtnode, header, now, + isc_rwlocktype_write, addedrdataset); + if (ACTIVE(header, now) && + (options & DNS_DBADD_EQUALOK) != 0 && + dns_rdataslab_equalx( + (unsigned char *)header, + (unsigned char *)newheader, + (unsigned int)(sizeof(*newheader)), + rbtdb->common.rdclass, + (dns_rdatatype_t)header->type)) + { + result = ISC_R_SUCCESS; } - return DNS_R_UNCHANGED; + free_rdataset(rbtdb, rbtdb->common.mctx, newheader); + return result; } /* @@ -10398,23 +10402,6 @@ no_glue: /* UNREACHABLE */ } -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; - } - - uint8_t *header1 = (uint8_t *)rdataset1->private3 - - sizeof(rdatasetheader_t); - uint8_t *header2 = (uint8_t *)rdataset2->private3 - - sizeof(rdatasetheader_t); - return dns_rdataslab_equalx(header1, header2, sizeof(rdatasetheader_t), - rdataset1->rdclass, rdataset2->type); -} - /*% * Routines for LRU-based cache management. */ diff --git a/lib/dns/rdatalist.c b/lib/dns/rdatalist.c index 5cccea5149..98036f9cb3 100644 --- a/lib/dns/rdatalist.c +++ b/lib/dns/rdatalist.c @@ -43,7 +43,6 @@ static dns_rdatasetmethods_t methods = { isc__rdatalist_setownercase, isc__rdatalist_getownercase, NULL, /* addglue */ - NULL, /* equals */ }; void diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c index 67508716d7..e190156fa7 100644 --- a/lib/dns/rdataset.c +++ b/lib/dns/rdataset.c @@ -197,7 +197,6 @@ static dns_rdatasetmethods_t question_methods = { NULL, /* setownercase */ NULL, /* getownercase */ NULL, /* addglue */ - NULL, /* equals */ }; void @@ -753,18 +752,3 @@ dns_rdataset_addglue(dns_rdataset_t *rdataset, dns_dbversion_t *version, return (rdataset->methods->addglue)(rdataset, version, msg); } - -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/resolver.c b/lib/dns/resolver.c index ff845ec1d8..2c354f565e 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -6331,7 +6331,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_message_t *message, bool have_answer = false; isc_result_t result, eresult = ISC_R_SUCCESS; dns_fetchevent_t *event = NULL; - unsigned int options; + unsigned int options = 0, equalok = 0; isc_task_t *task; bool fail; unsigned int valoptions = 0; @@ -6548,6 +6548,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_message_t *message, } if (!need_validation || !ANSWER(rdataset)) { options = 0; + equalok = 0; if (ANSWER(rdataset) && rdataset->type != dns_rdatatype_rrsig) { @@ -6573,10 +6574,23 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_message_t *message, { options |= DNS_DBADD_FORCE; } + /* + * If we're validating and passing the added + * rdataset back to the caller, then we ask + * dns_db_addrdataset() to compare the old and + * new rdatasets whenever the result would + * normally have been DNS_R_UNCHANGED, and to + * return ISC_R_SUCCESS if they compare equal. + * This allows us to continue and cache RRSIGs + * in that case. + */ + if (!need_validation && ardataset != NULL) { + equalok = DNS_DBADD_EQUALOK; + } addedrdataset = ardataset; result = dns_db_addrdataset( fctx->cache, node, NULL, now, rdataset, - options, addedrdataset); + options | equalok, addedrdataset); if (result == DNS_R_UNCHANGED) { result = ISC_R_SUCCESS; if (!need_validation && @@ -6600,25 +6614,11 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_message_t *message, DNS_R_NCACHENXRRSET; } continue; - } else if (!need_validation && - ardataset != NULL && - sigrdataset != NULL && - !dns_rdataset_equals( - rdataset, ardataset)) - { - /* - * 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, and we - * should carry on caching - * it. Otherwise, move on. - */ + } + if (equalok) { continue; } + result = ISC_R_SUCCESS; } if (result != ISC_R_SUCCESS) { break; diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c index 40fe6f7ab2..b29931e662 100644 --- a/lib/dns/sdb.c +++ b/lib/dns/sdb.c @@ -1440,7 +1440,6 @@ static dns_rdatasetmethods_t sdb_rdataset_methods = { NULL, /* setownercase */ NULL, /* getownercase */ NULL, /* addglue */ - NULL, /* equals */ }; static void diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c index ebd7fdd50b..259d768797 100644 --- a/lib/dns/sdlz.c +++ b/lib/dns/sdlz.c @@ -1452,7 +1452,6 @@ static dns_rdatasetmethods_t rdataset_methods = { NULL, /* setownercase */ NULL, /* getownercase */ NULL, /* addglue */ - NULL, /* equals */ }; static void