]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Add test for duplicate SOA record in the dns64/NODATA case 14373/head
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Fri, 21 Jun 2024 14:31:24 +0000 (16:31 +0200)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Mon, 24 Jun 2024 07:18:53 +0000 (09:18 +0200)
pdns/recursordist/pdns_recursor.cc
regression-tests.recursor-dnssec/recursortests.py
regression-tests.recursor-dnssec/test_DNS64.py

index 2a121ce51ac581074ccaae9d7fd506d859c81e22..6f9b2839a1426936c8fd4bb673cce046eb6c441f 100644 (file)
@@ -789,18 +789,18 @@ int getFakeAAAARecords(const DNSName& qname, ComboAddress prefix, vector<DNSReco
     // Remove double SOA records
     std::set<DNSName> seenSOAs;
     ret.erase(std::remove_if(
-                             ret.begin(),
-                             ret.end(),
-                             [&seenSOAs](DNSRecord& record) {
-                               if (record.d_type == QType::SOA) {
-                                 if (seenSOAs.count(record.d_name) > 0) {
-                                   // We've had this SOA before, remove it
-                                   return true;
-                                 }
-                                 seenSOAs.insert(record.d_name);
-                               }
-                               return false;
-                             }),
+                ret.begin(),
+                ret.end(),
+                [&seenSOAs](DNSRecord& record) {
+                  if (record.d_type == QType::SOA) {
+                    if (seenSOAs.count(record.d_name) > 0) {
+                      // We've had this SOA before, remove it
+                      return true;
+                    }
+                    seenSOAs.insert(record.d_name);
+                  }
+                  return false;
+                }),
               ret.end());
   }
   t_Counters.at(rec::Counter::dns64prefixanswers)++;
index 9ad7dfeca730e1786a7948463a6920407d11a36f..1385c1281132fbcbcfc9cd2d6921fd560483eca8 100644 (file)
@@ -809,7 +809,7 @@ distributor-threads={threads}""".format(confdir=confdir,
         return message
 
     @classmethod
-    def sendTCPQuery(cls, query, timeout=2.0):
+    def sendTCPQuery(cls, query, timeout=2.0, decode=True, fwparams=dict()):
         sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         if timeout:
             sock.settimeout(timeout)
@@ -835,7 +835,9 @@ distributor-threads={threads}""".format(confdir=confdir,
 
         message = None
         if data:
-            message = dns.message.from_wire(data)
+            if not decode:
+                return data
+            message = dns.message.from_wire(data, **fwparams)
         return message
 
     @classmethod
index abf6fdb23ac20f726ab1a04693af5514869bbadc..3b1e671ff99353d9deb660ff15ef33d1ff8c8c5f 100644 (file)
@@ -32,9 +32,11 @@ class DNS64RecursorTest(RecursorTest):
 @ 3600 IN SOA {soa}
 www 3600 IN A 192.0.2.42
 www 3600 IN TXT "does exist"
+txt 3600 IN TXT "a and aaaa do not exist"
 aaaa 3600 IN AAAA 2001:db8::1
 cname 3600 IN CNAME cname2.example.dns64.
 cname2 3600 IN CNAME www.example.dns64.
+cname3 3600 IN CNAME txt.example.dns64.
 formerr 3600 IN A 192.0.2.43
 """.format(soa=cls._SOA))
 
@@ -107,6 +109,22 @@ formerr 3600 IN A 192.0.2.43
             for expected in expectedResults:
                 self.assertRRsetInAnswer(res, expected)
 
+    # there is a CNAME from the name to a name that is NODATA for both A and AAAA
+    # so we should get a NODATA with a single SOA record (#14362)
+    def testCNAMEToNoData(self):
+        qname = 'cname3.example.dns64.'
+
+        expectedAnswer = dns.rrset.from_text(qname, 0, dns.rdataclass.IN, 'CNAME', 'txt.example.dns64.')
+        query = dns.message.make_query(qname, 'AAAA', want_dnssec=True)
+        for method in ("sendUDPQuery", "sendTCPQuery"):
+            sender = getattr(self, method)
+            res = sender(query, 2.0, True, {"one_rr_per_rrset": True}) # we want to detect dups
+            self.assertRcodeEqual(res, dns.rcode.NOERROR)
+            self.assertEqual(len(res.answer), 1)
+            self.assertEqual(len(res.authority), 1)
+            self.assertRRsetInAnswer(res, expectedAnswer)
+            self.assertAuthorityHasSOA(res)
+
     # this type (AAAA) does not exist for this name and there is no A record either, we should get a NXDomain
     def testNXD(self):
         qname = 'nxd.example.dns64.'
@@ -117,6 +135,18 @@ formerr 3600 IN A 192.0.2.43
             res = sender(query)
             self.assertRcodeEqual(res, dns.rcode.NXDOMAIN)
 
+    # this type (AAAA) does not exist for this name and there is no A record either, we should get a NODATA as TXT does exist
+    def testNoData(self):
+        qname = 'txt.example.dns64.'
+
+        query = dns.message.make_query(qname, 'AAAA', want_dnssec=True)
+        for method in ("sendUDPQuery", "sendTCPQuery"):
+            sender = getattr(self, method)
+            res = sender(query, 2.0, True, {"one_rr_per_rrset": True}) # we want to detect dups
+            self.assertRcodeEqual(res, dns.rcode.NOERROR)
+            self.assertEqual(len(res.answer), 0)
+            self.assertEqual(len(res.authority), 1)
+
     # there is an AAAA record, we should get it
     def testExistingAAAA(self):
         qname = 'aaaa.example.dns64.'