]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Add a function to extract an EDNS0Record from a DNS packet
authorRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 27 Feb 2019 11:06:53 +0000 (12:06 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 4 Apr 2019 09:46:26 +0000 (11:46 +0200)
pdns/dnsdist-ecs.cc
pdns/dnsdist-ecs.hh
pdns/dnsdist.cc
pdns/dnsdistdist/dnsdist-rules.hh
pdns/test-dnsdist_cc.cc

index 56422e48a8a992ca5cceb60be62598c072924144..9390a55df858d1164d0e832a3066e803c379da2e 100644 (file)
@@ -464,9 +464,7 @@ static int removeEDNSOptionFromOptions(unsigned char* optionsStart, const uint16
 
 int removeEDNSOptionFromOPT(char* optStart, size_t* optLen, const uint16_t optionCodeToRemove)
 {
-  /* we need at least:
-     root label (1), type (2), class (2), ttl (4) + rdlen (2)*/
-  if (*optLen < 11) {
+  if (*optLen < optRecordMinimumSize) {
     return EINVAL;
   }
   const unsigned char* end = (const unsigned char*) optStart + *optLen;
@@ -490,15 +488,13 @@ int removeEDNSOptionFromOPT(char* optStart, size_t* optLen, const uint16_t optio
 
 bool isEDNSOptionInOpt(const std::string& packet, const size_t optStart, const size_t optLen, const uint16_t optionCodeToFind, size_t* optContentStart, uint16_t* optContentLen)
 {
-  /* we need at least:
-   root label (1), type (2), class (2), ttl (4) + rdlen (2)*/
-  if (optLen < 11) {
+  if (optLen < optRecordMinimumSize) {
     return false;
   }
   size_t p = optStart + 9;
   uint16_t rdLen = (0x100*packet.at(p) + packet.at(p+1));
   p += sizeof(rdLen);
-  if (rdLen > (optLen - 11)) {
+  if (rdLen > (optLen - optRecordMinimumSize)) {
     return false;
   }
 
@@ -741,3 +737,31 @@ bool queryHasEDNS(const DNSQuestion& dq)
 
   return false;
 }
+
+bool getEDNS0Record(const DNSQuestion& dq, EDNS0Record& edns0)
+{
+  uint16_t optStart;
+  size_t optLen = 0;
+  bool last = false;
+  const char * packet = reinterpret_cast<const char*>(dq.dh);
+  std::string packetStr(packet, dq.len);
+  int res = locateEDNSOptRR(packetStr, &optStart, &optLen, &last);
+  if (res != 0) {
+    // no EDNS OPT RR
+    return false;
+  }
+
+  if (optLen < optRecordMinimumSize) {
+    return false;
+  }
+
+  if (optStart < dq.len && packetStr.at(optStart) != 0) {
+    // OPT RR Name != '.'
+    return false;
+  }
+
+  static_assert(sizeof(EDNS0Record) == sizeof(uint32_t), "sizeof(EDNS0Record) must match sizeof(uint32_t) AKA RR TTL size");
+  // copy out 4-byte "ttl" (really the EDNS0 record), after root label (1) + type (2) + class (2).
+  memcpy(&edns0, packet + optStart + 5, sizeof edns0);
+  return true;
+}
index 7c3739f443c2546c46101c4935169c9207c48496..767575723f059ca4320dfb89c88a055fb37fb300 100644 (file)
@@ -21,6 +21,9 @@
  */
 #pragma once
 
+// root label (1), type (2), class (2), ttl (4) + rdlen (2)
+static const size_t optRecordMinimumSize = 11;
+
 extern size_t g_EdnsUDPPayloadSize;
 extern uint16_t g_PayloadSizeSelfGenAnswers;
 
@@ -42,3 +45,4 @@ bool parseEDNSOptions(DNSQuestion& dq);
 
 int getEDNSZ(const DNSQuestion& dq);
 bool queryHasEDNS(const DNSQuestion& dq);
+bool getEDNS0Record(const DNSQuestion& dq, EDNS0Record& edns0);
index 07f587e923a8d48a110f3bcfb1d4c97a28effb97..1e02ceb85f1a8d83781f1aabc4c2cefa00e96729 100644 (file)
@@ -156,7 +156,7 @@ try
     hadEDNS = getEDNSUDPPayloadSizeAndZ(packet, *len, &payloadSize, &z);
   }
 
-  *len=(uint16_t) (sizeof(dnsheader)+consumed+DNS_TYPE_SIZE+DNS_CLASS_SIZE);
+  *len=static_cast<uint16_t>(sizeof(dnsheader)+consumed+DNS_TYPE_SIZE+DNS_CLASS_SIZE);
   struct dnsheader* dh = reinterpret_cast<struct dnsheader*>(packet);
   dh->ancount = dh->arcount = dh->nscount = 0;
 
@@ -537,7 +537,7 @@ try {
         char * response = packet;
         size_t responseSize = sizeof(packet);
 
-        if (got < static_cast<ssize_t>(sizeof(dnsheader)))
+        if (got < 0 || static_cast<size_t>(got) < sizeof(dnsheader))
           continue;
 
         uint16_t responseLen = static_cast<uint16_t>(got);
index 7361a4808c71c4b256e90289bfd98c31f5219de7..bbc4ff2056735d74af71f92d0c8396ad405f67a3 100644 (file)
@@ -863,30 +863,10 @@ public:
       return false;
     }
 
-    uint16_t optStart;
-    size_t optLen = 0;
-    bool last = false;
-    const char * packet = reinterpret_cast<const char*>(dq->dh);
-    std::string packetStr(packet, dq->len);
-    int res = locateEDNSOptRR(packetStr, &optStart, &optLen, &last);
-    if (res != 0) {
-      // no EDNS OPT RR
-      return d_extrcode == 0;
-    }
-
-    // root label (1), type (2), class (2), ttl (4) + rdlen (2)
-    if (optLen < 11) {
-      return false;
-    }
-
-    if (optStart < dq->len && packet[optStart] != 0) {
-      // OPT RR Name != '.'
+    EDNS0Record edns0;
+    if (!getEDNS0Record(*dq, edns0)) {
       return false;
     }
-    EDNS0Record edns0;
-    static_assert(sizeof(EDNS0Record) == sizeof(uint32_t), "sizeof(EDNS0Record) must match sizeof(uint32_t) AKA RR TTL size");
-    // copy out 4-byte "ttl" (really the EDNS0 record), after root label (1) + type (2) + class (2).
-    memcpy(&edns0, packet + optStart + 5, sizeof edns0);
 
     return d_extrcode == edns0.extRCode;
   }
@@ -907,30 +887,10 @@ public:
   }
   bool matches(const DNSQuestion* dq) const override
   {
-    uint16_t optStart;
-    size_t optLen = 0;
-    bool last = false;
-    const char * packet = reinterpret_cast<const char*>(dq->dh);
-    std::string packetStr(packet, dq->len);
-    int res = locateEDNSOptRR(packetStr, &optStart, &optLen, &last);
-    if (res != 0) {
-      // no EDNS OPT RR
-      return false;
-    }
-
-    // root label (1), type (2), class (2), ttl (4) + rdlen (2)
-    if (optLen < 11) {
-      return false;
-    }
-
-    if (optStart < dq->len && packetStr.at(optStart) != 0) {
-      // OPT RR Name != '.'
+    EDNS0Record edns0;
+    if (!getEDNS0Record(*dq, edns0)) {
       return false;
     }
-    EDNS0Record edns0;
-    static_assert(sizeof(EDNS0Record) == sizeof(uint32_t), "sizeof(EDNS0Record) must match sizeof(uint32_t) AKA RR TTL size");
-    // copy out 4-byte "ttl" (really the EDNS0 record), after root label (1) + type (2) + class (2).
-    memcpy(&edns0, packet + optStart + 5, sizeof edns0);
 
     return d_version < edns0.version;
   }
@@ -961,8 +921,7 @@ public:
       return false;
     }
 
-    // root label (1), type (2), class (2), ttl (4) + rdlen (2)
-    if (optLen < 11) {
+    if (optLen < optRecordMinimumSize) {
       return false;
     }
 
index 872592eadbf377c0ace3a900acb9cab799bc0eb3..f34968e7416f8a3f65739b823b08262c3bf1b79a 100644 (file)
@@ -1433,8 +1433,7 @@ BOOST_AUTO_TEST_CASE(test_isEDNSOptionInOpt) {
       return false;
     }
 
-    // root label (1), type (2), class (2), ttl (4) + rdlen (2)
-    if (optLen < 11) {
+    if (optLen < optRecordMinimumSize) {
       return false;
     }