]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Fix an EDNS UDP payload size issue for UDP -> TCP only
authorRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 9 Jun 2021 10:06:52 +0000 (12:06 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 26 Aug 2021 14:30:27 +0000 (16:30 +0200)
pdns/dnsdist.cc
regression-tests.dnsdist/test_TCPOnly.py [new file with mode: 0644]

index 931d239b47c448267870349c017a9a1572d81513..35406444bef756f210c83ff053e05ac8b107f36b 100644 (file)
@@ -1325,6 +1325,7 @@ public:
     thread_local LocalStateHolder<vector<DNSDistResponseRuleAction>> localRespRuleActions = g_respruleactions.getLocal();
     DNSResponse dr = makeDNSResponseFromIDState(ids, response.d_buffer);
     if (response.d_buffer.size() > d_payloadSize) {
+      vinfolog("Got a response of size %d over TCP, while the initial UDP payload size was %d, truncating", response.d_buffer.size(), d_payloadSize);
       truncateTC(dr.getMutableData(), dr.getMaximumSize(), dr.qname->wirelength());
       dr.getHeader()->tc = true;
     }
@@ -1379,6 +1380,9 @@ public:
   {
     uint16_t z = 0;
     getEDNSUDPPayloadSizeAndZ(reinterpret_cast<const char*>(buffer.data()), buffer.size(), &d_payloadSize, &z);
+    if (d_payloadSize < 512) {
+      d_payloadSize = 512;
+    }
     query = InternalQuery(std::move(buffer), std::move(ids));
     downstream = ds;
     proxyProtocolPayloadSize = 0;
diff --git a/regression-tests.dnsdist/test_TCPOnly.py b/regression-tests.dnsdist/test_TCPOnly.py
new file mode 100644 (file)
index 0000000..7ada4ca
--- /dev/null
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+import dns
+
+from dnsdisttests import DNSDistTest
+
+class TestTCPOnly(DNSDistTest):
+
+    _config_template = """
+    newServer{address="127.0.0.1:%s", tcpOnly=true}
+    """
+
+    def testUDP(self):
+        """
+        TCP Only: UDP query is sent via TCP
+        """
+        name = 'udp.tcp-only.test.powerdns.com.'
+        query = dns.message.make_query(name, 'A', 'IN')
+        expectedResponse = dns.message.make_response(query)
+        rrset = dns.rrset.from_text(name,
+                                    60,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.A,
+                                    '127.0.0.1')
+        expectedResponse.answer.append(rrset)
+
+        (receivedQuery, receivedResponse) = self.sendUDPQuery(query, expectedResponse)
+        self.assertEqual(query, receivedQuery)
+        self.assertEqual(receivedResponse, expectedResponse)
+
+        if 'UDP Responder' in self._responsesCounter:
+            self.assertEqual(self._responsesCounter['UDP Responder'], 0)
+        if 'TCP Responder' in self._responsesCounter:
+            self.assertEqual(self._responsesCounter['TCP Responder'], 1)
+
+    def testTCP(self):
+        """
+        TCP Only: TCP query is sent via TCP
+        """
+        name = 'tcp.tcp-only.test.powerdns.com.'
+        query = dns.message.make_query(name, 'A', 'IN')
+        expectedResponse = dns.message.make_response(query)
+        rrset = dns.rrset.from_text(name,
+                                    60,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.A,
+                                    '127.0.0.1')
+        expectedResponse.answer.append(rrset)
+
+        (receivedQuery, receivedResponse) = self.sendTCPQuery(query, expectedResponse)
+        self.assertEqual(query, receivedQuery)
+        self.assertEqual(receivedResponse, expectedResponse)
+        if 'UDP Responder' in self._responsesCounter:
+            self.assertEqual(self._responsesCounter['UDP Responder'], 0)
+        if 'TCP Responder' in self._responsesCounter:
+            self.assertEqual(self._responsesCounter['TCP Responder'], 1)