diff --git a/bin/tests/system/additional/tests.sh b/bin/tests/system/additional/tests.sh index 193c9f9270..e1b0cfb823 100644 --- a/bin/tests/system/additional/tests.sh +++ b/bin/tests/system/additional/tests.sh @@ -279,7 +279,7 @@ n=$((n + 1)) echo_i "testing with 'minimal-any no;' ($n)" ret=0 $DIG $DIGOPTS -t ANY www.rt.example @10.53.0.1 >dig.out.$n || ret=1 -grep "ANSWER: 3, AUTHORITY: 2, ADDITIONAL: 2" dig.out.$n >/dev/null || ret=1 +grep "ANSWER: 3, AUTHORITY: 2, ADDITIONAL: 1" dig.out.$n >/dev/null || ret=1 if [ $ret -eq 1 ]; then echo_i "failed" status=$((status + 1)) diff --git a/lib/dns/db.c b/lib/dns/db.c index b07d76199e..19417acbfa 100644 --- a/lib/dns/db.c +++ b/lib/dns/db.c @@ -1401,7 +1401,7 @@ create_gluelist(dns_db_t *db, dns_dbversion_t *dbversion, dns_dbnode_t *dbnode, * in-bailiwick). */ - (void)dns_rdataset_additionaldata(rdataset, dns_rootname, add, &ctx); + (void)dns_rdataset_additionaldata(rdataset, dns_rootname, add, &ctx, 0); CMM_STORE_SHARED(gluelist->glue, ctx.glue); diff --git a/lib/dns/include/dns/rdataset.h b/lib/dns/include/dns/rdataset.h index 5a3fd22264..662f931446 100644 --- a/lib/dns/include/dns/rdataset.h +++ b/lib/dns/include/dns/rdataset.h @@ -54,6 +54,8 @@ #include #include +#define DNS_RDATASET_MAXADDITIONAL 13 + /* Fixed RRSet helper macros */ #define DNS_RDATASET_LENGTH 2; @@ -535,7 +537,8 @@ dns_rdataset_towirepartial(dns_rdataset_t *rdataset, isc_result_t dns_rdataset_additionaldata(dns_rdataset_t *rdataset, const dns_name_t *owner_name, - dns_additionaldatafunc_t add, void *arg); + dns_additionaldatafunc_t add, void *arg, + size_t limit); /*%< * For each rdata in rdataset, call 'add' for each name and type in the * rdata which is subject to additional section processing. @@ -554,10 +557,15 @@ dns_rdataset_additionaldata(dns_rdataset_t *rdataset, *\li If a call to dns_rdata_additionaldata() is not successful, the * result returned will be the result of dns_rdataset_additionaldata(). * + *\li If 'limit' is non-zero and the number of the rdatasets is larger + * than 'limit', no additional data will be processed. + * * Returns: * *\li #ISC_R_SUCCESS * + *\li #DNS_R_TOOMANYRECORDS in case rdataset count is larger than 'limit' + * *\li Any error that dns_rdata_additionaldata() can return. */ diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c index 9a0ee35b4e..1a6dc4d551 100644 --- a/lib/dns/rdataset.c +++ b/lib/dns/rdataset.c @@ -507,7 +507,8 @@ dns_rdataset_towire(dns_rdataset_t *rdataset, const dns_name_t *owner_name, isc_result_t dns_rdataset_additionaldata(dns_rdataset_t *rdataset, const dns_name_t *owner_name, - dns_additionaldatafunc_t add, void *arg) { + dns_additionaldatafunc_t add, void *arg, + size_t limit) { dns_rdata_t rdata = DNS_RDATA_INIT; isc_result_t result; @@ -519,6 +520,10 @@ dns_rdataset_additionaldata(dns_rdataset_t *rdataset, REQUIRE(DNS_RDATASET_VALID(rdataset)); REQUIRE((rdataset->attributes & DNS_RDATASETATTR_QUESTION) == 0); + if (limit != 0 && dns_rdataset_count(rdataset) > limit) { + return DNS_R_TOOMANYRECORDS; + } + result = dns_rdataset_first(rdataset); if (result != ISC_R_SUCCESS) { return result; diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 5a537145f6..28f1679c44 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -8583,7 +8583,7 @@ rctx_answer_any(respctx_t *rctx) { rdataset->trust = rctx->trust; (void)dns_rdataset_additionaldata(rdataset, rctx->aname, - check_related, rctx); + check_related, rctx, 0); } return ISC_R_SUCCESS; @@ -8631,7 +8631,7 @@ rctx_answer_match(respctx_t *rctx) { rctx->ardataset->attributes |= DNS_RDATASETATTR_CACHE; rctx->ardataset->trust = rctx->trust; (void)dns_rdataset_additionaldata(rctx->ardataset, rctx->aname, - check_related, rctx); + check_related, rctx, 0); for (sigrdataset = ISC_LIST_HEAD(rctx->aname->list); sigrdataset != NULL; @@ -8838,7 +8838,7 @@ rctx_authority_positive(respctx_t *rctx) { */ (void)dns_rdataset_additionaldata( rdataset, name, check_related, - rctx); + rctx, 0); done = true; } } @@ -9345,8 +9345,12 @@ rctx_referral(respctx_t *rctx) { */ INSIST(rctx->ns_rdataset != NULL); FCTX_ATTR_SET(fctx, FCTX_ATTR_GLUING); + + /* + * Mark the glue records in the additional section to be cached. + */ (void)dns_rdataset_additionaldata(rctx->ns_rdataset, rctx->ns_name, - check_related, rctx); + check_related, rctx, 0); #if CHECK_FOR_GLUE_IN_ANSWER /* * Look in the answer section for "glue" that is incorrectly @@ -9358,8 +9362,9 @@ rctx_referral(respctx_t *rctx) { if (rctx->glue_in_answer && (fctx->type == dns_rdatatype_aaaa || fctx->type == dns_rdatatype_a)) { - (void)dns_rdataset_additionaldata( - rctx->ns_rdataset, rctx->ns_name, check_answer, fctx); + (void)dns_rdataset_additionaldata(rctx->ns_rdataset, + rctx->ns_name, check_answer, + fctx, 0); } #endif /* if CHECK_FOR_GLUE_IN_ANSWER */ FCTX_ATTR_CLR(fctx, FCTX_ATTR_GLUING); @@ -9461,7 +9466,7 @@ again: if (CHASE(rdataset)) { rdataset->attributes &= ~DNS_RDATASETATTR_CHASE; (void)dns_rdataset_additionaldata( - rdataset, name, check_related, rctx); + rdataset, name, check_related, rctx, 0); rescan = true; } } diff --git a/lib/ns/query.c b/lib/ns/query.c index 29000be3ee..2b8f4c47ad 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -2146,7 +2146,8 @@ addname: if (trdataset != NULL && dns_rdatatype_followadditional(type)) { if (client->additionaldepth++ < client->view->max_restarts) { eresult = dns_rdataset_additionaldata( - trdataset, fname, query_additional_cb, qctx); + trdataset, fname, query_additional_cb, qctx, + DNS_RDATASET_MAXADDITIONAL); } client->additionaldepth--; } @@ -2244,7 +2245,7 @@ regular: * We don't care if dns_rdataset_additionaldata() fails. */ (void)dns_rdataset_additionaldata(rdataset, name, query_additional_cb, - qctx); + qctx, DNS_RDATASET_MAXADDITIONAL); CTRACE(ISC_LOG_DEBUG(3), "query_additional: done"); } @@ -2270,7 +2271,8 @@ query_addrrset(query_ctx_t *qctx, dns_name_t **namep, * To the current response for 'client', add the answer RRset * '*rdatasetp' and an optional signature set '*sigrdatasetp', with * owner name '*namep', to section 'section', unless they are - * already there. Also add any pertinent additional data. + * already there. Also add any pertinent additional data, unless + * the query was for type ANY. * * If 'dbuf' is not NULL, then '*namep' is the name whose data is * stored in 'dbuf'. In this case, query_addrrset() guarantees that @@ -2325,7 +2327,9 @@ query_addrrset(query_ctx_t *qctx, dns_name_t **namep, */ query_addtoname(mname, rdataset); query_setorder(qctx, mname, rdataset); - query_additional(qctx, mname, rdataset); + if (qctx->qtype != dns_rdatatype_any) { + query_additional(qctx, mname, rdataset); + } /* * Note: we only add SIGs if we've added the type they cover, so