Note that PowerDNS deviates from RFC 2181 (section 5.4.1) in this
respect.
+Starting with version 4.7.0, there is a mechanism to save the
+parent NS set if it contains *more* names than the child NS set.
+This allows fallback to the saved parent NS set on resolution errors
+using the child specified NS set.
+As experience shows, this configuration error is encountered in the
+wild often enough to warrant this workaround.
+See :ref:`setting-save-parent-ns-set`.
+
+
Some small things
------------------
Default is 'yes' now, was 'no' before 4.0.0
+.. _setting-save-parent-ns-set:
+
+``save-parent-ns-set``
+----------------------
+.. versionadded:: 4.7.0
+
+- Boolean
+- Default: yes
+
+If set, a parent (non-authoritative) ``NS`` set is saved if it contains more entries than a newly encountered child (authoritative) ``NS`` set for the same domain.
+The saved parent ``NS`` set is tried if resolution using the child ``NS`` set fails.
+
.. _setting-security-poll-suffix:
``security-poll-suffix``
These addresses will then be used for future queries to authoritative nameservers.
This has the consequence that authoritative nameservers will be contacted over IPv6 in more case than before.
+New settings
+^^^^^^^^^^^^
+- The :ref:`settings-save-parent-ns-set` setting has been introduced, enabling fall-back cases if the parent ``NS`` set contains names not in the child ``NS`` set.
+
Deprecated and changed settings
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- The :ref:`setting-hint-file` gained a special value ``no`` to indicate that no hint file should not processed. The hint processing code is also made less verbose.
SyncRes::s_dot_to_port_853 = ::arg().mustDo("dot-to-port-853");
SyncRes::s_event_trace_enabled = ::arg().asNum("event-trace-enabled");
+ SyncRes::s_save_parent_ns_set = ::arg().mustDo("save-parent-ns-set");
if (SyncRes::s_tcp_fast_open_connect) {
checkFastOpenSysctl(true);
::arg().set("tcp-out-max-queries", "Maximum total number of queries per TCP/DoT connection, 0 means no limit") = "0";
::arg().set("tcp-out-max-idle-per-thread", "Maximum number of idle TCP/DoT connections per thread") = "100";
::arg().setSwitch("structured-logging", "Prefer structured logging") = "yes";
+ ::arg().setSwitch("save-parent-ns-set", "Save parent NS set to be used if child NS set fails") = "yes";
::arg().setCmd("help", "Provide a helpful message");
::arg().setCmd("version", "Print version string");
bool SyncRes::s_tcp_fast_open_connect;
bool SyncRes::s_dot_to_port_853;
int SyncRes::s_event_trace_enabled;
+bool SyncRes::s_save_parent_ns_set;
#define LOG(x) if(d_lm == Log) { g_log <<Logger::Warning << x; } else if(d_lm == Store) { d_trace << x; }
res = doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, ret, depth, beenthere, state, stopAtDelegation, nullptr);
- if (res == -1) {
+ if (res == -1 && s_save_parent_ns_set) {
// It did not work out, lets check if we have a saved parent NS set
map<DNSName, vector<ComboAddress>> fallBack;
{
if (doCache) {
// Check if we are going to replace a non-auth (parent) NS recordset
- if (isAA && i->first.type == QType::NS) {
+ if (isAA && i->first.type == QType::NS && s_save_parent_ns_set) {
rememberParentSetIfNeeded(i->first.name, i->second.records, depth);
}
g_recCache->replace(d_now.tv_sec, i->first.name, i->first.type, i->second.records, i->second.signatures, authorityRecs, i->first.type == QType::DS ? true : isAA, auth, i->first.place == DNSResourceRecord::ANSWER ? ednsmask : boost::none, d_routingTag, recordState, remoteIP);
static const int event_trace_to_pb = 1;
static const int event_trace_to_log = 2;
static int s_event_trace_enabled;
-
+ static bool s_save_parent_ns_set;
+
std::unordered_map<std::string,bool> d_discardedPolicies;
DNSFilterEngine::Policy d_appliedPolicy;
std::unordered_set<std::string> d_policyTags;