]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Limit packet and record cache entry size
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Mon, 5 Jan 2026 13:52:02 +0000 (14:52 +0100)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Mon, 9 Feb 2026 12:24:40 +0000 (13:24 +0100)
Signed-off-by: Otto Moerbeek <otto.moerbeek@open-xchange.com>
pdns/recursordist/pdns_recursor.cc
pdns/recursordist/rec-main.cc
pdns/recursordist/rec-rust-lib/table.py
pdns/recursordist/recpacketcache.cc
pdns/recursordist/recpacketcache.hh
pdns/recursordist/recursor_cache.cc
pdns/recursordist/recursor_cache.hh
pdns/recursordist/test-recursorcache_cc.cc

index a8b47c07a29b4e97000bf2b8d961dc22bfbb727a..34f2b7c17fa15df2b0943d52c6c9ec2dc13efc2c 100644 (file)
@@ -1764,7 +1764,7 @@ void startDoResolve(void* arg) // NOLINT(readability-function-cognitive-complexi
 #endif
     }
 
-    const bool intoPC = g_packetCache && !variableAnswer && !resolver.wasVariable();
+    const bool intoPC = g_packetCache && !variableAnswer && !resolver.wasVariable() && (RecursorPacketCache::s_maxEntrySize == 0 || packet.size() <= RecursorPacketCache::s_maxEntrySize);
     if (intoPC) {
       minTTL = capPacketCacheTTL(*packetWriter.getHeader(), minTTL, seenAuthSOA);
       g_packetCache->insertResponsePacket(comboWriter->d_tag, comboWriter->d_qhash, std::move(comboWriter->d_query), comboWriter->d_mdp.d_qname,
index 8abf028781aea3cbbec70a5d6e8edea2fd6c9dde..7e3b12e6220ceb6d693653a82bd76ebb3954146c 100644 (file)
@@ -3239,6 +3239,8 @@ int main(int argc, char** argv)
       pdns::RecResolve::setInstanceParameters(arg()["server-id"], ttl, interval, selfResolveCheck, []() { reloadZoneConfiguration(g_yamlSettings); });
     }
 
+    MemRecursorCache::s_maxEntrySize = ::arg().asNum("max-recordcache-entry-size");
+    RecursorPacketCache::s_maxEntrySize = ::arg().asNum("max-packetcache-entry-size");
     g_recCache = std::make_unique<MemRecursorCache>(::arg().asNum("record-cache-shards"));
     g_negCache = std::make_unique<NegCache>(::arg().asNum("record-cache-shards") / 8);
     if (!::arg().mustDo("disable-packetcache")) {
index 2a0e63cb2fdab50303978eaa0ae3a2d402828fb5..4f2beb2c946db663e9f6035ceeb59162b77cdb00 100644 (file)
@@ -1520,6 +1520,19 @@ See :ref:`handling-of-root-hints` for more information on this.
  ''',
      'versionchanged': ('4.1.0', 'The minimum value of this setting is 15. i.e. setting this to lower than 15 will make this value 15.')
     },
+    {
+        'name' : 'max_entry_size',
+        'section' : 'recordcache',
+        'oldname': 'max-recordcache-entry-size',
+        'type' : LType.Uint64,
+        'default' : '8192',
+        'help' : 'maximum storage size of a recordset stored in record cache',
+        'doc' : '''
+Maximum size of storage used by a single record cache entry. Entries larger than this number will not be stored.
+Zero means no limit.
+''',
+    'versionadded': ['5.1.10', '5.2.8', '5.3.5', '5.4.0'],
+    },
     {
         'name' : 'max_concurrent_requests_per_tcp_connection',
         'section' : 'incoming',
@@ -1596,6 +1609,19 @@ Maximum number of Packet Cache entries. Sharded and shared by all threads since
 ''',
         'runtime': 'set-max-packetcache-entries',
     },
+    {
+        'name' : 'max_entry_size',
+        'section' : 'packetcache',
+        'oldname' : 'max-packetcache-entry-size',
+        'type' : LType.Uint64,
+        'default' : '8192',
+        'help' : 'maximum size of a packet stored in the the packet cache',
+        'doc' : '''
+Maximum size of packets stored in the packet cache. Packets larger than this number will not be stored.
+Zero means no limit.
+''',
+    'versionadded': ['5.1.10', '5.2.8', '5.3.5', '5.4.0'],
+    },
     {
         'name' : 'max_qperq',
         'section' : 'outgoing',
index ec99fe58f5f27c55ace62929c0974c7011ea50cd..93a1a82a637ffc0c0db014384029b5d7f298db18 100644 (file)
@@ -11,6 +11,7 @@
 #include "rec-taskqueue.hh"
 
 unsigned int RecursorPacketCache::s_refresh_ttlperc{0};
+uint32_t RecursorPacketCache::s_maxEntrySize{8192};
 
 void RecursorPacketCache::setShardSizes(size_t shardSize)
 {
index e11906ec367395c3936ae689d77ebfcfb009cf69..7922be65195a4501a446f3103106bdf5eaf4d343 100644 (file)
@@ -46,6 +46,7 @@ class RecursorPacketCache : public PacketCache
 {
 public:
   static unsigned int s_refresh_ttlperc;
+  static uint32_t s_maxEntrySize;
 
   struct PBData
   {
index 55ff55ab01abee535122d65235b1031912fbe292..94dc86de48a941aaf52ad27cbbcf840951527cdb 100644 (file)
@@ -76,6 +76,7 @@
 uint16_t MemRecursorCache::s_maxServedStaleExtensions;
 uint16_t MemRecursorCache::s_maxRRSetSize = 256;
 bool MemRecursorCache::s_limitQTypeAny = true;
+uint32_t MemRecursorCache::s_maxEntrySize = 8192;
 
 const MemRecursorCache::AuthRecs MemRecursorCache::s_emptyAuthRecs = std::make_shared<MemRecursorCache::AuthRecsVec>();
 const MemRecursorCache::SigRecs MemRecursorCache::s_emptySigRecs = std::make_shared<MemRecursorCache::SigRecsVec>();
@@ -89,6 +90,7 @@ void MemRecursorCache::resetStaticsForTests()
   SyncRes::s_minimumTTL = 0;
   s_maxRRSetSize = 256;
   s_limitQTypeAny = true;
+  s_maxEntrySize = 8192;
 }
 
 MemRecursorCache::MemRecursorCache(size_t mapsCount) :
@@ -762,6 +764,10 @@ void MemRecursorCache::replace(time_t now, const DNSName& qname, const QType qty
     }
   }
 
+  auto storeSize = cacheEntry.sizeEstimate();
+  if (s_maxEntrySize > 0 && storeSize > s_maxEntrySize) {
+    return;
+  }
   if (!isNew) {
     moveCacheItemToBack<SequencedTag>(lockedShard->d_map, stored);
   }
index bc70193ad8ba0f5ab2044a8e5f10c2a8717eec18..d2d12b174354094165f550c675030850349d507d 100644 (file)
@@ -56,6 +56,7 @@ public:
   // but mark it as too big. Subsequent gets will cause an ImmediateServFailException to be thrown.
   static uint16_t s_maxRRSetSize;
   static bool s_limitQTypeAny;
+  static uint32_t s_maxEntrySize;
 
   [[nodiscard]] size_t size() const;
   [[nodiscard]] size_t bytes();
index 42d9a274c343aec1225c279b1daf2f0bb5c4074a..3ed068b7b20a7dccfaa35febed50a74d2bdbb5be 100644 (file)
@@ -395,6 +395,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheSimpleDistantFuture)
 BOOST_AUTO_TEST_CASE(test_RecursorCacheBig)
 {
   MemRecursorCache::resetStaticsForTests();
+  MemRecursorCache::s_maxEntrySize = 64 * 1024;
   MemRecursorCache MRC;
 
   std::vector<DNSRecord> records;