]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Add unit tests for Extended Error parsing
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 29 Aug 2023 09:03:07 +0000 (11:03 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 11 Sep 2023 08:37:09 +0000 (10:37 +0200)
pdns/dnsdistdist/Makefile.am
pdns/dnsdistdist/dnsdist-edns.cc
pdns/dnsdistdist/ednsextendederror.cc [new symlink]
pdns/dnsdistdist/ednsextendederror.hh [new symlink]
pdns/dnsdistdist/test-dnsdistedns.cc [new file with mode: 0644]
pdns/dnswriter.hh
pdns/ednsextendederror.cc [new file with mode: 0644]
pdns/ednsextendederror.hh [new file with mode: 0644]
pdns/recursordist/ednsextendederror.cc [changed from file to symlink]
pdns/recursordist/ednsextendederror.hh [changed from file to symlink]

index 1a80477586f7cff531b72c3f3f3c9c4a228ce850..770a5ccfe44f1070db3cc812899ffc9f6ed393fc 100644 (file)
@@ -301,6 +301,7 @@ testrunner_SOURCES = \
        dnswriter.cc dnswriter.hh \
        dolog.hh \
        ednscookies.cc ednscookies.hh \
+       ednsextendederror.cc ednsextendederror.hh \
        ednsoptions.cc ednsoptions.hh \
        ednssubnet.cc ednssubnet.hh \
        ext/luawrapper/include/LuaContext.hpp \
@@ -332,6 +333,7 @@ testrunner_SOURCES = \
        test-dnsdistasync.cc \
        test-dnsdistbackend_cc.cc \
        test-dnsdistdynblocks_hh.cc \
+       test-dnsdistedns.cc \
        test-dnsdistkvs_cc.cc \
        test-dnsdistlbpolicies_cc.cc \
        test-dnsdistluanetwork.cc \
index 794d11e6bdd004d376b9b333beefbf1d018c2b38..982fe3efef9134a8d92d3227e4eeb7d4799fb73d 100644 (file)
@@ -40,7 +40,7 @@ std::pair<std::optional<uint16_t>, std::optional<std::string>> getExtendedDNSErr
   size_t optContentStart = 0;
   uint16_t optContentLen = 0;
   uint16_t infoCode{0};
-  std::string extraText;
+  std::optional<std::string> extraText{std::nullopt};
   /* we need at least 2 bytes after the option length (info-code) */
   if (!isEDNSOptionInOpt(packet, optStart, optLen, EDNSOptionCode::EXTENDEDERROR, &optContentStart, &optContentLen) || optContentLen < sizeof(infoCode)) {
     return std::make_pair(std::nullopt, std::nullopt);
@@ -49,8 +49,9 @@ std::pair<std::optional<uint16_t>, std::optional<std::string>> getExtendedDNSErr
   infoCode = ntohs(infoCode);
 
   if (optContentLen > sizeof(infoCode)) {
-    extraText.resize(optContentLen - sizeof(infoCode));
-    memcpy(extraText.data(), &packet.at(optContentStart + sizeof(infoCode)), optContentLen - sizeof(infoCode));
+    extraText = std::string();
+    extraText->resize(optContentLen - sizeof(infoCode));
+    memcpy(extraText->data(), &packet.at(optContentStart + sizeof(infoCode)), optContentLen - sizeof(infoCode));
   }
   return std::make_pair(infoCode, std::move(extraText));
 }
diff --git a/pdns/dnsdistdist/ednsextendederror.cc b/pdns/dnsdistdist/ednsextendederror.cc
new file mode 120000 (symlink)
index 0000000..4f6ced0
--- /dev/null
@@ -0,0 +1 @@
+../ednsextendederror.cc
\ No newline at end of file
diff --git a/pdns/dnsdistdist/ednsextendederror.hh b/pdns/dnsdistdist/ednsextendederror.hh
new file mode 120000 (symlink)
index 0000000..2e5eee1
--- /dev/null
@@ -0,0 +1 @@
+../ednsextendederror.hh
\ No newline at end of file
diff --git a/pdns/dnsdistdist/test-dnsdistedns.cc b/pdns/dnsdistdist/test-dnsdistedns.cc
new file mode 100644 (file)
index 0000000..93e0e00
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_NO_MAIN
+
+#include <boost/test/unit_test.hpp>
+
+#include "dnsdist-edns.hh"
+#include "dnsname.hh"
+#include "dnswriter.hh"
+#include "ednscookies.hh"
+#include "ednsextendederror.hh"
+#include "ednsoptions.hh"
+#include "ednssubnet.hh"
+
+BOOST_AUTO_TEST_SUITE(test_dnsdist_edns)
+
+BOOST_AUTO_TEST_CASE(getExtendedDNSError)
+{
+  const DNSName name("www.powerdns.com.");
+
+  {
+    /* no EDNS */
+    PacketBuffer query;
+    GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
+    pw.getHeader()->rd = 1;
+    pw.commit();
+
+    auto [infoCode, extraText] = dnsdist::edns::getExtendedDNSError(query);
+    BOOST_CHECK(!infoCode);
+    BOOST_CHECK(!extraText);
+  }
+
+  {
+    /* EDNS but no EDE */
+    PacketBuffer query;
+    GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
+    pw.getHeader()->rd = 1;
+    pw.addOpt(512, 0, 0);
+    pw.commit();
+
+    auto [infoCode, extraText] = dnsdist::edns::getExtendedDNSError(query);
+    BOOST_CHECK(!infoCode);
+    BOOST_CHECK(!extraText);
+  }
+
+  {
+    /* EDE with a numerical code but no text */
+    PacketBuffer query;
+    GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
+    pw.getHeader()->rd = 1;
+    GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
+    const EDNSExtendedError ede{
+      .infoCode = static_cast<uint16_t>(EDNSExtendedError::code::NetworkError),
+      .extraText = ""};
+    opts.emplace_back(EDNSOptionCode::EXTENDEDERROR, makeEDNSExtendedErrorOptString(ede));
+    pw.addOpt(512, 0, 0, opts);
+    pw.commit();
+
+    auto [infoCode, extraText] = dnsdist::edns::getExtendedDNSError(query);
+    BOOST_CHECK(infoCode);
+    BOOST_CHECK_EQUAL(*infoCode, ede.infoCode);
+    BOOST_CHECK(!extraText);
+  }
+
+  {
+    /* EDE with both code and text */
+    PacketBuffer query;
+    GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
+    pw.getHeader()->rd = 1;
+    GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
+    const EDNSExtendedError ede{
+      .infoCode = static_cast<uint16_t>(EDNSExtendedError::code::Synthesized),
+      .extraText = "Synthesized from aggressive NSEC cache"};
+    opts.emplace_back(EDNSOptionCode::EXTENDEDERROR, makeEDNSExtendedErrorOptString(ede));
+    pw.addOpt(512, 0, 0, opts);
+    pw.commit();
+
+    auto [infoCode, extraText] = dnsdist::edns::getExtendedDNSError(query);
+    BOOST_CHECK(infoCode);
+    BOOST_CHECK_EQUAL(*infoCode, ede.infoCode);
+    BOOST_CHECK(extraText);
+    BOOST_CHECK_EQUAL(*extraText, ede.extraText);
+  }
+
+  {
+    /* EDE with truncated text */
+    PacketBuffer query;
+    GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
+    pw.getHeader()->rd = 1;
+    GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
+    const EDNSExtendedError ede{
+      .infoCode = static_cast<uint16_t>(EDNSExtendedError::code::Synthesized),
+      .extraText = "Synthesized from aggressive NSEC cache"};
+    opts.emplace_back(EDNSOptionCode::EXTENDEDERROR, makeEDNSExtendedErrorOptString(ede));
+    pw.addOpt(512, 0, 0, opts);
+    pw.commit();
+
+    /* truncate the EDE text by one byte */
+    query.resize(query.size() - 1U);
+
+    BOOST_CHECK_THROW(dnsdist::edns::getExtendedDNSError(query), std::range_error);
+  }
+
+  {
+    /* EDE before ECS */
+    PacketBuffer query;
+    GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
+    pw.getHeader()->rd = 1;
+    GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
+    const EDNSExtendedError ede{
+      .infoCode = static_cast<uint16_t>(EDNSExtendedError::code::Synthesized),
+      .extraText = "Synthesized from aggressive NSEC cache"};
+    opts.emplace_back(EDNSOptionCode::EXTENDEDERROR, makeEDNSExtendedErrorOptString(ede));
+    EDNSSubnetOpts ecsOpt;
+    ecsOpt.source = Netmask(ComboAddress("192.0.2.1"), 24U);
+    const auto ecsOptStr = makeEDNSSubnetOptsString(ecsOpt);
+    opts.emplace_back(EDNSOptionCode::ECS, ecsOptStr);
+    pw.addOpt(512, 0, 0, opts);
+    pw.commit();
+
+    auto [infoCode, extraText] = dnsdist::edns::getExtendedDNSError(query);
+    BOOST_CHECK(infoCode);
+    BOOST_CHECK_EQUAL(*infoCode, ede.infoCode);
+    BOOST_CHECK(extraText);
+    BOOST_CHECK_EQUAL(*extraText, ede.extraText);
+  }
+
+  {
+    /* EDE after ECS */
+    PacketBuffer query;
+    GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
+    pw.getHeader()->rd = 1;
+    GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
+    EDNSSubnetOpts ecsOpt;
+    ecsOpt.source = Netmask(ComboAddress("192.0.2.1"), 24U);
+    const auto ecsOptStr = makeEDNSSubnetOptsString(ecsOpt);
+    opts.emplace_back(EDNSOptionCode::ECS, ecsOptStr);
+    const EDNSExtendedError ede{
+      .infoCode = static_cast<uint16_t>(EDNSExtendedError::code::Synthesized),
+      .extraText = "Synthesized from aggressive NSEC cache"};
+    opts.emplace_back(EDNSOptionCode::EXTENDEDERROR, makeEDNSExtendedErrorOptString(ede));
+    pw.addOpt(512, 0, 0, opts);
+    pw.commit();
+
+    auto [infoCode, extraText] = dnsdist::edns::getExtendedDNSError(query);
+    BOOST_CHECK(infoCode);
+    BOOST_CHECK_EQUAL(*infoCode, ede.infoCode);
+    BOOST_CHECK(extraText);
+    BOOST_CHECK_EQUAL(*extraText, ede.extraText);
+  }
+
+  {
+    /* Cookie, EDE, padding */
+    PacketBuffer query;
+    GenericDNSPacketWriter<PacketBuffer> pw(query, name, QType::A, QClass::IN, 0);
+    pw.getHeader()->rd = 1;
+    GenericDNSPacketWriter<PacketBuffer>::optvect_t opts;
+    const EDNSCookiesOpt cookieOpt("deadbeefdeadbeef");
+    const auto cookieOptStr = cookieOpt.makeOptString();
+    opts.emplace_back(EDNSOptionCode::COOKIE, cookieOptStr);
+    const EDNSExtendedError ede{
+      .infoCode = static_cast<uint16_t>(EDNSExtendedError::code::Synthesized),
+      .extraText = "Synthesized from aggressive NSEC cache"};
+    opts.emplace_back(EDNSOptionCode::EXTENDEDERROR, makeEDNSExtendedErrorOptString(ede));
+    std::string paddingOptStr;
+    paddingOptStr.resize(42U);
+    opts.emplace_back(EDNSOptionCode::PADDING, paddingOptStr);
+    pw.addOpt(512, 0, 0, opts);
+    pw.commit();
+
+    auto [infoCode, extraText] = dnsdist::edns::getExtendedDNSError(query);
+    BOOST_CHECK(infoCode);
+    BOOST_CHECK_EQUAL(*infoCode, ede.infoCode);
+    BOOST_CHECK(extraText);
+    BOOST_CHECK_EQUAL(*extraText, ede.extraText);
+  }
+}
+
+BOOST_AUTO_TEST_SUITE_END();
index cfa4eb994750f5f83f0e01996501688600c7a278..4d6d28618242b27aea11e79d21e3b6826a371ebc 100644 (file)
@@ -69,7 +69,7 @@ public:
   void startRecord(const DNSName& name, uint16_t qtype, uint32_t ttl=3600, uint16_t qclass=QClass::IN, DNSResourceRecord::Place place=DNSResourceRecord::ANSWER, bool compress=true);
 
   /** Shorthand way to add an Opt-record, for example for EDNS0 purposes */
-  typedef vector<pair<uint16_t,std::string> > optvect_t;
+  using optvect_t = vector<pair<uint16_t,std::string> >;
   void addOpt(const uint16_t udpsize, const uint16_t extRCode, const uint16_t ednsFlags, const optvect_t& options=optvect_t(), const uint8_t version=0);
 
   /** needs to be called after the last record is added, but can be called again and again later on. Is called internally by startRecord too.
diff --git a/pdns/ednsextendederror.cc b/pdns/ednsextendederror.cc
new file mode 100644 (file)
index 0000000..5010e3d
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <limits>
+
+#include "ednsextendederror.hh"
+
+static bool getEDNSExtendedErrorOptFromStringView(const std::string_view& option, EDNSExtendedError& eee)
+{
+  if (option.size() < sizeof(uint16_t)) {
+    return false;
+  }
+  eee.infoCode = static_cast<uint8_t>(option.at(0)) * 256 + static_cast<uint8_t>(option.at(1));
+
+  if (option.size() > sizeof(uint16_t)) {
+    eee.extraText = std::string(&option.at(sizeof(uint16_t)), option.size() - sizeof(uint16_t));
+  }
+
+  return true;
+}
+
+bool getEDNSExtendedErrorOptFromString(const string& option, EDNSExtendedError& eee)
+{
+  return getEDNSExtendedErrorOptFromStringView(std::string_view(option), eee);
+}
+
+bool getEDNSExtendedErrorOptFromString(const char* option, unsigned int len, EDNSExtendedError& eee)
+{
+  return getEDNSExtendedErrorOptFromStringView(std::string_view(option, len), eee);
+}
+
+string makeEDNSExtendedErrorOptString(const EDNSExtendedError& eee)
+{
+  if (eee.extraText.size() > static_cast<size_t>(std::numeric_limits<uint16_t>::max() - 2)) {
+    throw std::runtime_error("Trying to create an EDNS Extended Error option with an extra text of size " + std::to_string(eee.extraText.size()));
+  }
+
+  string ret;
+  ret.reserve(sizeof(uint16_t) + eee.extraText.size());
+  ret.resize(sizeof(uint16_t));
+
+  ret[0] = static_cast<char>(static_cast<uint16_t>(eee.infoCode) / 256);
+  ret[1] = static_cast<char>(static_cast<uint16_t>(eee.infoCode) % 256);
+  ret.append(eee.extraText);
+
+  return ret;
+}
diff --git a/pdns/ednsextendederror.hh b/pdns/ednsextendederror.hh
new file mode 100644 (file)
index 0000000..5b264fc
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#pragma once
+#include "namespaces.hh"
+
+struct EDNSExtendedError
+{
+  enum class code : uint16_t
+  {
+    Other = 0,
+    UnsupportedDNSKEYAlgorithm = 1,
+    UnsupportedDSDigestType = 2,
+    StaleAnswer = 3,
+    ForgedAnswer = 4,
+    DNSSECIndeterminate = 5,
+    DNSSECBogus = 6,
+    SignatureExpired = 7,
+    SignatureNotYetValid = 8,
+    DNSKEYMissing = 9,
+    RRSIGsMissing = 10,
+    NoZoneKeyBitSet = 11,
+    NSECMissing = 12,
+    CachedError = 13,
+    NotReady = 14,
+    Blocked = 15,
+    Censored = 16,
+    Filtered = 17,
+    Prohibited = 18,
+    StaleNXDOMAINAnswer = 19,
+    NotAuthoritative = 20,
+    NotSupported = 21,
+    NoReachableAuthority = 22,
+    NetworkError = 23,
+    InvalidData = 24,
+    SignatureExpiredBeforeValid = 25,
+    TooEarly = 26,
+    UnsupportedNSEC3IterationsValue = 27,
+    UnableToConformToPolicy = 28,
+    Synthesized = 29,
+  };
+  uint16_t infoCode;
+  std::string extraText;
+};
+
+bool getEDNSExtendedErrorOptFromString(const char* option, unsigned int len, EDNSExtendedError& eee);
+bool getEDNSExtendedErrorOptFromString(const string& option, EDNSExtendedError& eee);
+string makeEDNSExtendedErrorOptString(const EDNSExtendedError& eee);
deleted file mode 100644 (file)
index 5010e3dba52dc87a3dab238d7fa081adcf8f1ad2..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * This file is part of PowerDNS or dnsdist.
- * Copyright -- PowerDNS.COM B.V. and its contributors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * In addition, for the avoidance of any doubt, permission is granted to
- * link this program with OpenSSL and to (re)distribute the binaries
- * produced as the result of such linking.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#include <limits>
-
-#include "ednsextendederror.hh"
-
-static bool getEDNSExtendedErrorOptFromStringView(const std::string_view& option, EDNSExtendedError& eee)
-{
-  if (option.size() < sizeof(uint16_t)) {
-    return false;
-  }
-  eee.infoCode = static_cast<uint8_t>(option.at(0)) * 256 + static_cast<uint8_t>(option.at(1));
-
-  if (option.size() > sizeof(uint16_t)) {
-    eee.extraText = std::string(&option.at(sizeof(uint16_t)), option.size() - sizeof(uint16_t));
-  }
-
-  return true;
-}
-
-bool getEDNSExtendedErrorOptFromString(const string& option, EDNSExtendedError& eee)
-{
-  return getEDNSExtendedErrorOptFromStringView(std::string_view(option), eee);
-}
-
-bool getEDNSExtendedErrorOptFromString(const char* option, unsigned int len, EDNSExtendedError& eee)
-{
-  return getEDNSExtendedErrorOptFromStringView(std::string_view(option, len), eee);
-}
-
-string makeEDNSExtendedErrorOptString(const EDNSExtendedError& eee)
-{
-  if (eee.extraText.size() > static_cast<size_t>(std::numeric_limits<uint16_t>::max() - 2)) {
-    throw std::runtime_error("Trying to create an EDNS Extended Error option with an extra text of size " + std::to_string(eee.extraText.size()));
-  }
-
-  string ret;
-  ret.reserve(sizeof(uint16_t) + eee.extraText.size());
-  ret.resize(sizeof(uint16_t));
-
-  ret[0] = static_cast<char>(static_cast<uint16_t>(eee.infoCode) / 256);
-  ret[1] = static_cast<char>(static_cast<uint16_t>(eee.infoCode) % 256);
-  ret.append(eee.extraText);
-
-  return ret;
-}
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..4f6ced0eb166a10aaeda9107936822805996c6a9
--- /dev/null
@@ -0,0 +1 @@
+../ednsextendederror.cc
\ No newline at end of file
deleted file mode 100644 (file)
index 5b264fcf69b6f2985ac39d8b5ba9a01e25ff924a..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * This file is part of PowerDNS or dnsdist.
- * Copyright -- PowerDNS.COM B.V. and its contributors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * In addition, for the avoidance of any doubt, permission is granted to
- * link this program with OpenSSL and to (re)distribute the binaries
- * produced as the result of such linking.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#pragma once
-#include "namespaces.hh"
-
-struct EDNSExtendedError
-{
-  enum class code : uint16_t
-  {
-    Other = 0,
-    UnsupportedDNSKEYAlgorithm = 1,
-    UnsupportedDSDigestType = 2,
-    StaleAnswer = 3,
-    ForgedAnswer = 4,
-    DNSSECIndeterminate = 5,
-    DNSSECBogus = 6,
-    SignatureExpired = 7,
-    SignatureNotYetValid = 8,
-    DNSKEYMissing = 9,
-    RRSIGsMissing = 10,
-    NoZoneKeyBitSet = 11,
-    NSECMissing = 12,
-    CachedError = 13,
-    NotReady = 14,
-    Blocked = 15,
-    Censored = 16,
-    Filtered = 17,
-    Prohibited = 18,
-    StaleNXDOMAINAnswer = 19,
-    NotAuthoritative = 20,
-    NotSupported = 21,
-    NoReachableAuthority = 22,
-    NetworkError = 23,
-    InvalidData = 24,
-    SignatureExpiredBeforeValid = 25,
-    TooEarly = 26,
-    UnsupportedNSEC3IterationsValue = 27,
-    UnableToConformToPolicy = 28,
-    Synthesized = 29,
-  };
-  uint16_t infoCode;
-  std::string extraText;
-};
-
-bool getEDNSExtendedErrorOptFromString(const char* option, unsigned int len, EDNSExtendedError& eee);
-bool getEDNSExtendedErrorOptFromString(const string& option, EDNSExtendedError& eee);
-string makeEDNSExtendedErrorOptString(const EDNSExtendedError& eee);
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..2e5eee19272470aa9125455ddd519f006c21c574
--- /dev/null
@@ -0,0 +1 @@
+../ednsextendederror.hh
\ No newline at end of file