]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Be smarter about refusing to add many RR types to the database
authorOndřej Surý <ondrej@isc.org>
Mon, 17 Jun 2024 09:40:40 +0000 (11:40 +0200)
committerOndřej Surý <ondrej@isc.org>
Mon, 29 Jul 2024 10:27:25 +0000 (12:27 +0200)
Instead of outright refusing to add new RR types to the cache, be a bit
smarter:

1. If the new header type is in our priority list, we always add either
   positive or negative entry at the beginning of the list.

2. If the new header type is negative entry, and we are over the limit,
   we mark it as ancient immediately, so it gets evicted from the cache
   as soon as possible.

3. Otherwise add the new header after the priority headers (or at the
   head of the list).

4. If we are over the limit, evict the last entry on the normal header
   list.

(cherry picked from commit 57cd34441a1b4ecc9874a4a106c2c95b8d7a3120)

lib/dns/rbtdb.c

index 4332215c77b63620d9ac706489c274b83d33a527..5179f942fb54457e96d1f0f805e3cfc7df5f8aea 100644 (file)
@@ -6260,19 +6260,13 @@ update_recordsandxfrsize(bool add, rbtdb_version_t *rbtversion,
        RWUNLOCK(&rbtversion->rwlock, isc_rwlocktype_write);
 }
 
-#ifndef DNS_RBTDB_MAX_RTYPES
-#define DNS_RBTDB_MAX_RTYPES 100
-#endif /* DNS_RBTDB_MAX_RTYPES */
-
 static bool
 overmaxtype(dns_rbtdb_t *rbtdb, uint32_t ntypes) {
-       UNUSED(rbtdb);
-
-       if (DNS_RBTDB_MAX_RTYPES == 0) {
+       if (rbtdb->maxtypepername == 0) {
                return (false);
        }
 
-       return (ntypes >= DNS_RBTDB_MAX_RTYPES);
+       return (ntypes >= rbtdb->maxtypepername);
 }
 
 static bool
@@ -6370,7 +6364,6 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, const dns_name_t *nodename,
                                        set_ttl(rbtdb, topheader, 0);
                                        mark_header_ancient(rbtdb, topheader);
                                }
-                               ntypes = 0; /* Always add the negative entry */
                                goto find_header;
                        }
                        /*
@@ -6395,11 +6388,9 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, const dns_name_t *nodename,
                         * check for an extant non-ancient NODATA ncache
                         * entry which covers the same type as the RRSIG.
                         */
-                       ntypes = 0;
                        for (topheader = rbtnode->data; topheader != NULL;
                             topheader = topheader->next)
                        {
-                               ++ntypes;
                                if ((topheader->type ==
                                     RBTDB_RDATATYPE_NCACHEANY) ||
                                    (newheader->type == sigtype &&
@@ -6444,12 +6435,16 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, const dns_name_t *nodename,
                }
        }
 
-       ntypes = 0;
        for (topheader = rbtnode->data; topheader != NULL;
             topheader = topheader->next)
        {
-               ++ntypes;
-               if (prio_type(topheader->type)) {
+               if (IS_CACHE(rbtdb) && ACTIVE(topheader, now)) {
+                       ++ntypes;
+                       expireheader = topheader;
+               } else if (!IS_CACHE(rbtdb)) {
+                       ++ntypes;
+               }
+               if (prio_header(topheader)) {
                        prioheader = topheader;
                }
                if (topheader->type == newheader->type ||
@@ -6806,9 +6801,7 @@ find_header:
                        /*
                         * No rdatasets of the given type exist at the node.
                         */
-                       if (rbtdb->maxtypepername > 0 &&
-                           ntypes >= rbtdb->maxtypepername)
-                       {
+                       if (!IS_CACHE(rbtdb) && overmaxtype(rbtdb, ntypes)) {
                                free_rdataset(rbtdb, rbtdb->common.mctx,
                                              newheader);
                                return (DNS_R_TOOMANYRECORDS);