]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Limit the additional processing for large RDATA sets
authorOndřej Surý <ondrej@isc.org>
Thu, 14 Nov 2024 09:37:29 +0000 (10:37 +0100)
committerAndoni Duarte Pintado <andoni@isc.org>
Wed, 15 Jan 2025 12:57:27 +0000 (13:57 +0100)
When answering queries, don't add data to the additional section if
the answer has more than 13 names in the RDATA.  This limits the
number of lookups into the database(s) during a single client query,
reducing query processing load.

Also, don't append any additional data to type=ANY queries. The
answer to ANY is already big enough.

(cherry picked from commit a1982cf1bb95c818aa7b58988b5611dec80f2408)

bin/tests/system/additional/tests.sh
lib/dns/db.c
lib/dns/include/dns/rdataset.h
lib/dns/rdataset.c
lib/dns/resolver.c
lib/ns/query.c

index 193c9f9270aeb68b25d5677c861d0ff4705e4233..e1b0cfb82337b328f94b605c1d1d13bfa1c79162 100644 (file)
@@ -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))
index b07d76199e4b4f4a0446bcace544e05c28f7b1e4..19417acbfaafd0fbe8c51b1b43318155de9edd87 100644 (file)
@@ -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);
 
index 5a3fd222642942801639deb2d46b34844bc3a4af..662f9314463e14d3efbdaaa328072b54cda1f57b 100644 (file)
@@ -54,6 +54,8 @@
 #include <dns/rdatastruct.h>
 #include <dns/types.h>
 
+#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.
  */
 
index 9a0ee35b4edcae4bd94e7b346ec1ed9663c6ac4f..1a6dc4d551dcabe6fc161f410d009d0383ac9941 100644 (file)
@@ -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;
index 5a537145f66721a6af88fbe8f83ce7987ca968ac..28f1679c44bd5ef437ab175e89cfeaa678578bd0 100644 (file)
@@ -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;
                        }
                }
index 29000be3eebfb959043e5e4d2e9b3e93517dcae7..2b8f4c47adb74d92041b7f1724a22205ba02b128 100644 (file)
@@ -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