]> granicus.if.org Git - pdns/commitdiff
Add tests for ecs-cache-limit-ttl
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Wed, 27 Mar 2019 12:17:06 +0000 (13:17 +0100)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Wed, 27 Mar 2019 12:46:19 +0000 (13:46 +0100)
pdns/pdns_recursor.cc
pdns/recursordist/docs/settings.rst
pdns/recursordist/test-syncres_cc.cc
pdns/syncres.cc

index 712b5dae7f5ceb8630dd3b89f9a9d7eec08248a1..d89be18c96d4993c0d529f873f1553d9a750efd4 100644 (file)
@@ -4271,7 +4271,6 @@ int main(int argc, char **argv)
     ::arg().set("ecs-minimum-ttl-override", "Set under adverse conditions, a minimum TTL for records in ECS-specific answers")="0";
     ::arg().set("ecs-cache-limit-ttl", "Minimum TTL to cache ECS response")="0";
     ::arg().set("edns-subnet-whitelist", "List of netmasks and domains that we should enable EDNS subnet for")="";
-    ::arg().set("edns-subnet-whitelist", "List of netmasks and domains that we should enable EDNS subnet for")="";
     ::arg().set("ecs-add-for", "List of client netmasks for which EDNS Client Subnet will be added")="0.0.0.0/0, ::/0, " LOCAL_NETS_INVERSE;
     ::arg().set("ecs-scope-zero-address", "Address to send to whitelisted authoritative servers for incoming queries with ECS prefix-length source of 0")="";
     ::arg().setSwitch( "use-incoming-edns-subnet", "Pass along received EDNS Client Subnet information")="no";
index a1b692b49b3e8218aca57bb67c4becd3b00af58e..21a698a0193f77ceb4c29e81ec3d50fdbbafec71 100644 (file)
@@ -425,6 +425,8 @@ Can be set at runtime using ``rec_control set-ecs-minimum-ttl 3600``.
 
 ``ecs-cache-limit-ttl``
 -----------------------
+.. versionadded:: 4.1.12
+
 -  Integer
 -  Default: 0 (disabled)
 
index 322e792a8935f1297bbed3e95cbc2b0ad672d106..a2ed49b8a2ba696f77cb09c69838f199816bb106 100644 (file)
@@ -132,6 +132,7 @@ static void init(bool debug=false)
   SyncRes::s_ecsipv6limit = 56;
   SyncRes::s_ecsipv4cachelimit = 24;
   SyncRes::s_ecsipv6cachelimit = 56;
+  SyncRes::s_ecscachelimitttl = 0;
   SyncRes::s_rootNXTrust = true;
   SyncRes::s_minimumTTL = 0;
   SyncRes::s_minimumECSTTL = 0;
@@ -2181,6 +2182,85 @@ BOOST_AUTO_TEST_CASE(test_ecs_cache_limit_denied) {
   BOOST_REQUIRE_EQUAL(cached.size(), 0);
 }
 
+BOOST_AUTO_TEST_CASE(test_ecs_cache_ttllimit_allowed) {
+    std::unique_ptr<SyncRes> sr;
+    initSR(sr);
+
+    primeHints();
+
+    const DNSName target("www.powerdns.com.");
+
+    SyncRes::addEDNSDomain(DNSName("powerdns.com."));
+
+    EDNSSubnetOpts incomingECS;
+    incomingECS.source = Netmask("192.0.2.128/32");
+    sr->setQuerySource(ComboAddress(), boost::optional<const EDNSSubnetOpts&>(incomingECS));
+    SyncRes::s_ecscachelimitttl = 30;
+
+    sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+
+      BOOST_REQUIRE(srcmask);
+      BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
+
+      setLWResult(res, 0, true, false, true);
+      addRecordToLW(res, target, QType::A, "192.0.2.1");
+
+      return 1;
+    });
+
+    const time_t now = sr->getNow().tv_sec;
+    vector<DNSRecord> ret;
+    int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+    BOOST_CHECK_EQUAL(res, RCode::NoError);
+    BOOST_CHECK_EQUAL(ret.size(), 1);
+
+    /* should have been cached */
+    const ComboAddress who("192.0.2.128");
+    vector<DNSRecord> cached;
+    BOOST_REQUIRE_GT(t_RC->get(now, target, QType(QType::A), true, &cached, who), 0);
+    BOOST_REQUIRE_EQUAL(cached.size(), 1);
+}
+
+BOOST_AUTO_TEST_CASE(test_ecs_cache_ttllimit_notallowed) {
+    std::unique_ptr<SyncRes> sr;
+    initSR(sr);
+
+    primeHints();
+
+    const DNSName target("www.powerdns.com.");
+
+    SyncRes::addEDNSDomain(DNSName("powerdns.com."));
+
+    EDNSSubnetOpts incomingECS;
+    incomingECS.source = Netmask("192.0.2.128/32");
+    sr->setQuerySource(ComboAddress(), boost::optional<const EDNSSubnetOpts&>(incomingECS));
+    SyncRes::s_ecscachelimitttl = 100;
+
+    sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+
+      BOOST_REQUIRE(srcmask);
+      BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
+
+      setLWResult(res, 0, true, false, true);
+      addRecordToLW(res, target, QType::A, "192.0.2.1");
+
+      return 1;
+    });
+
+    const time_t now = sr->getNow().tv_sec;
+    vector<DNSRecord> ret;
+    int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+    BOOST_CHECK_EQUAL(res, RCode::NoError);
+    BOOST_CHECK_EQUAL(ret.size(), 1);
+
+    /* should have NOT been cached because TTL of 60 is too small */
+    const ComboAddress who("192.0.2.128");
+    vector<DNSRecord> cached;
+    BOOST_REQUIRE_LT(t_RC->get(now, target, QType(QType::A), true, &cached, who), 0);
+    BOOST_REQUIRE_EQUAL(cached.size(), 0);
+}
+
+
 BOOST_AUTO_TEST_CASE(test_ns_speed) {
   std::unique_ptr<SyncRes> sr;
   initSR(sr);
index c0412b388beffbabbe1a8b0d2fd2f32545fbba9c..52c75c8d279d098143c47d8e8be99b32af58ccd7 100644 (file)
@@ -121,8 +121,8 @@ static void accountAuthLatency(int usec, int family)
 SyncRes::SyncRes(const struct timeval& now) :  d_authzonequeries(0), d_outqueries(0), d_tcpoutqueries(0), d_throttledqueries(0), d_timeouts(0), d_unreachables(0),
                                               d_totUsec(0), d_now(now),
                                               d_cacheonly(false), d_doDNSSEC(false), d_doEDNS0(false), d_lm(s_lm)
-
-{
+                                                 
+{ 
 }
 
 /** everything begins here - this is the entry point just after receiving a packet */
@@ -435,10 +435,10 @@ uint64_t SyncRes::doDumpThrottleMap(int fd)
    Another cause of "No answer" may simply be a network condition.
    Nonsense answers are a clearer indication this host won't be able to do DNSSEC evah.
 
-   Previous implementations have suffered from turning off DNSSEC questions for an authoritative server based on timeouts.
+   Previous implementations have suffered from turning off DNSSEC questions for an authoritative server based on timeouts. 
    A clever idea is to only turn off DNSSEC if we know a domain isn't signed anyhow. The problem with that really
-   clever idea however is that at this point in PowerDNS, we may simply not know that yet. All the DNSSEC thinking happens
-   elsewhere. It may not have happened yet.
+   clever idea however is that at this point in PowerDNS, we may simply not know that yet. All the DNSSEC thinking happens 
+   elsewhere. It may not have happened yet. 
 
    For now this means we can't be clever, but will turn off DNSSEC if you reply with FormError or gibberish.
 */
@@ -449,19 +449,19 @@ int SyncRes::asyncresolveWrapper(const ComboAddress& ip, bool ednsMANDATORY, con
      the goal is to get as many remotes as possible on the highest level of EDNS support
      The levels are:
 
-     0) UNKNOWN Unknown state
+     0) UNKNOWN Unknown state 
      1) EDNS: Honors EDNS0
      2) EDNSIGNORANT: Ignores EDNS0, gives replies without EDNS0
      3) NOEDNS: Generates FORMERR on EDNS queries
 
      Everybody starts out assumed to be '0'.
      If '0', send out EDNS0
-        If you FORMERR us, go to '3',
+        If you FORMERR us, go to '3', 
         If no EDNS in response, go to '2'
      If '1', send out EDNS0
         If FORMERR, downgrade to 3
      If '2', keep on including EDNS0, see what happens
-        Same behaviour as 0
+        Same behaviour as 0 
      If '3', send bare queries
   */
 
@@ -485,7 +485,7 @@ int SyncRes::asyncresolveWrapper(const ComboAddress& ip, bool ednsMANDATORY, con
   int ret;
   for(int tries = 0; tries < 3; ++tries) {
     //    cerr<<"Remote '"<<ip.toString()<<"' currently in mode "<<mode<<endl;
-
+    
     if(mode==EDNSStatus::NOEDNS) {
       g_stats.noEdnsOutQueries++;
       EDNSLevel = 0; // level != mode
@@ -526,11 +526,11 @@ int SyncRes::asyncresolveWrapper(const ComboAddress& ip, bool ednsMANDATORY, con
        mode = EDNSStatus::EDNSOK;
        //      cerr<<"We find that "<<ip.toString()<<" is EDNS OK!"<<endl;
       }
-
+      
     }
     if(oldmode != mode || !ednsstatus->modeSetAt)
       ednsstatus->modeSetAt=d_now.tv_sec;
-    //    cerr<<"Result: ret="<<ret<<", EDNS-level: "<<EDNSLevel<<", haveEDNS: "<<res->d_haveEDNS<<", new mode: "<<mode<<endl;
+    //    cerr<<"Result: ret="<<ret<<", EDNS-level: "<<EDNSLevel<<", haveEDNS: "<<res->d_haveEDNS<<", new mode: "<<mode<<endl;  
     return ret;
   }
   return ret;
@@ -1280,7 +1280,7 @@ bool SyncRes::doCacheCheck(const DNSName &qname, const DNSName& authname, bool w
       DNSRecord dr;
       dr.d_type=QType::RRSIG;
       dr.d_name=sqname;
-      dr.d_ttl=ttl;
+      dr.d_ttl=ttl; 
       dr.d_content=signature;
       dr.d_place = DNSResourceRecord::ANSWER;
       dr.d_class=QClass::IN;
@@ -3205,7 +3205,7 @@ int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<D
     g_log<<Logger::Error<<"Failed to resolve "<<qname.toLogString()<<", got an exception"<<endl;
     ret.clear();
   }
-
+  
   return res;
 }