records.push_back(rec);
}
-static void addRecordToList(std::vector<DNSRecord>& records, const std::string& name, uint16_t type, const std::string& content, DNSResourceRecord::Place place, uint32_t ttl)
-{
- addRecordToList(records, name, type, content, place, ttl);
-}
-
static void addRecordToLW(LWResult* res, const DNSName& name, uint16_t type, const std::string& content, DNSResourceRecord::Place place=DNSResourceRecord::ANSWER, uint32_t ttl=60)
{
addRecordToList(res->d_records, name, type, content, place, ttl);
BOOST_CHECK_EQUAL(queriesCount, 4);
}
+BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_skipped_cut) {
+ std::unique_ptr<SyncRes> sr;
+ initSR(sr, true, true);
+
+ g_dnssecmode = DNSSECMode::ValidateAll;
+
+ primeHints();
+ const DNSName target("www.sub.powerdns.com.");
+ const ComboAddress targetAddr("192.0.2.42");
+ testkeysset_t keys;
+
+ auto luaconfsCopy = g_luaconfs.getCopy();
+ luaconfsCopy.dsAnchors.clear();
+ generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
+ generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+ generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+
+ g_luaconfs.setState(luaconfsCopy);
+
+ size_t queriesCount = 0;
+
+ sr->setAsyncCallback([target,targetAddr,&queriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
+ queriesCount++;
+
+ if (type == QType::DS) {
+ if (domain == DNSName("sub.powerdns.com.")) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
+ addRRSIG(keys, res->d_records, DNSName("powerdns.com."), 300);
+ addNSECRecordToLW(domain, DNSName("z.powerdns.com."), { QType::NS }, 600, res->d_records);
+ addRRSIG(keys, res->d_records, DNSName("powerdns.com."), 300);
+ return 1;
+ }
+ else if (domain == DNSName("www.sub.powerdns.com.")) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, DNSName("sub.powerdns.com."), QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
+ return 1;
+ }
+ }
+ else if (type == QType::DNSKEY) {
+ if (domain == g_rootdnsname || domain == DNSName("com.")) {
+ setLWResult(res, 0, true, false, true);
+ addDNSKEY(keys, domain, 300, res->d_records);
+ addRRSIG(keys, res->d_records, domain, 300);
+ return 1;
+ }
+ else {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
+ return 1;
+ }
+ }
+ else if (domain == target) {
+ if (isRootServer(ip)) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addDS(DNSName("com."), 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, DNSName("."), 300);
+ addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.1:53")) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, DNSName("powerdns.com."), QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addDS(DNSName("powerdns.com."), 300, res->d_records, keys);
+ addRRSIG(keys, res->d_records, DNSName("com."), 300);
+ addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.2:53")) {
+ setLWResult(res, 0, true, false, true);
+ addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
+ return 1;
+ }
+ }
+
+ return 0;
+ });
+
+ vector<DNSRecord> ret;
+ int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 1);
+ BOOST_CHECK(ret[0].d_type == QType::A);
+ BOOST_CHECK_EQUAL(queriesCount, 5);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Insecure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 1);
+ BOOST_CHECK(ret[0].d_type == QType::A);
+ BOOST_CHECK_EQUAL(queriesCount, 5);
+}
+
+BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_ta_skipped_cut) {
+ std::unique_ptr<SyncRes> sr;
+ initSR(sr, true, true);
+
+ g_dnssecmode = DNSSECMode::ValidateAll;
+
+ primeHints();
+ const DNSName target("www.sub.powerdns.com.");
+ const ComboAddress targetAddr("192.0.2.42");
+ testkeysset_t keys;
+
+ auto luaconfsCopy = g_luaconfs.getCopy();
+ luaconfsCopy.dsAnchors.clear();
+ generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys, luaconfsCopy.dsAnchors);
+ /* No key material for .com */
+ /* But TA for sub.powerdns.com. */
+ generateKeyMaterial(DNSName("sub.powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::SHA256, keys);
+ luaconfsCopy.dsAnchors[DNSName("sub.powerdns.com.")].insert(keys[DNSName("sub.powerdns.com.")].second);
+ g_luaconfs.setState(luaconfsCopy);
+
+ size_t queriesCount = 0;
+
+ sr->setAsyncCallback([target,targetAddr,&queriesCount,keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) {
+ queriesCount++;
+
+ if (type == QType::DS) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
+ return 1;
+ }
+ else if (type == QType::DNSKEY) {
+ if (domain == g_rootdnsname || domain == DNSName("sub.powerdns.com.")) {
+ setLWResult(res, 0, true, false, true);
+ addDNSKEY(keys, domain, 300, res->d_records);
+ addRRSIG(keys, res->d_records, domain, 300);
+ return 1;
+ }
+ }
+ else if (domain == target) {
+ if (isRootServer(ip)) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
+ /* no DS */
+ addNSECRecordToLW(DNSName("com."), DNSName("dom."), { QType::NS }, 600, res->d_records);
+ addRRSIG(keys, res->d_records, DNSName("."), 300);
+ addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.1:53")) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, DNSName("powerdns.com."), QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
+ return 1;
+ }
+ else if (ip == ComboAddress("192.0.2.2:53")) {
+ setLWResult(res, 0, true, false, true);
+ addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
+ addRRSIG(keys, res->d_records, DNSName("sub.powerdns.com."), 300);
+ return 1;
+ }
+ }
+
+ return 0;
+ });
+
+ vector<DNSRecord> ret;
+ int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 1);
+ BOOST_CHECK(ret[0].d_type == QType::A);
+ BOOST_CHECK_EQUAL(queriesCount, 5);
+
+ /* again, to test the cache */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
+ BOOST_REQUIRE_EQUAL(ret.size(), 1);
+ BOOST_CHECK(ret[0].d_type == QType::A);
+ BOOST_CHECK_EQUAL(queriesCount, 5);
+}
+
BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_nodata) {
std::unique_ptr<SyncRes> sr;
initSR(sr, true);
return 1;
}
}
- else if (domain == target) {
- if (isRootServer(ip)) {
+ else {
+ if (target.isPartOf(domain) && isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
addNSECRecordToLW(DNSName("com."), DNSName("com."), { QType::NS }, 600, res->d_records);
return 1;
}
else if (ip == ComboAddress("192.0.2.1:53")) {
- setLWResult(res, 0, false, false, true);
- addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
- addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
+ if (target == domain) {
+ setLWResult(res, 0, false, false, true);
+ addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
+ addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
+ }
+ else if (domain == DNSName("com.")) {
+ setLWResult(res, 0, true, false, true);
+ addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
+ addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
+ }
return 1;
}
- else if (ip == ComboAddress("192.0.2.2:53")) {
+ else if (domain == target && ip == ComboAddress("192.0.2.2:53")) {
setLWResult(res, 0, true, false, true);
- addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
+ if (type == QType::NS) {
+ addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
+ }
+ else {
+ addRecordToLW(res, domain, QType::A, targetAddr.toString(), DNSResourceRecord::ANSWER, 3600);
+ }
/* No RRSIG in a now (thanks to TA) Secure zone -> Bogus*/
return 1;
}
NsSet nsset;
bool flawedNSSet=false;
+ const SyncRes::zonesStates_t cuts = computeZoneCuts(qname, g_rootdnsname, depth);
+
// the two retries allow getBestNSNamesFromCache&co to reprime the root
// hints, in case they ever go missing
for(int tries=0;tries<2 && nsset.empty();++tries) {
subdomain=getBestNSNamesFromCache(subdomain, qtype, nsset, &flawedNSSet, depth, beenthere); // pass beenthere to both occasions
}
- state = getValidationStatus(subdomain, depth);
+ state = getValidationStatus(cuts, subdomain);
+
LOG("Initial validation status for "<<qname<<" inherited from "<<subdomain<<" is "<<vStates[state]<<endl);
- if(!(res=doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, ret, depth, beenthere, state)))
+ if(!(res=doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, ret, depth, beenthere, state, cuts)))
return 0;
LOG(prefix<<qname<<": failed (res="<<res<<")"<<endl);
std::vector<DNSRecord> dsrecords;
vState state = Indeterminate;
- int rcode = doResolve(zone, QType(QType::DS), dsrecords, depth, beenthere, state);
+ int rcode = doResolve(zone, QType(QType::DS), dsrecords, depth + 1, beenthere, state);
d_skipCNAMECheck = oldSkipCNAME;
d_requireAuthData = oldRequireAuthData;
return Bogus;
}
+vState SyncRes::getValidationStatus(const SyncRes::zonesStates_t& cuts, const DNSName& subdomain)
+{
+ vState result = Indeterminate;
+
+ if (!validationEnabled()) {
+ return result;
+ }
+ DNSName name(subdomain);
+ do {
+ const auto& it = cuts.find(name);
+ if (it != cuts.cend()) {
+ return it->second;
+ }
+ }
+ while (name.chopOff());
+
+ return result;
+}
+
+#if 0
vState SyncRes::getValidationStatus(const DNSName& subdomain, unsigned int depth)
{
if (!validationEnabled()) {
return Secure;
}
+#endif /* 0 */
+
+SyncRes::zonesStates_t SyncRes::computeZoneCuts(const DNSName& begin, const DNSName& end, unsigned int depth)
+{
+ SyncRes::zonesStates_t cuts;
+ dsmap_t ds;
+ vState cutState = getDSRecords(end, ds, false, depth);
+ if (cutState == TA) {
+ cutState = Secure;
+ }
+ else if (cutState == NTA) {
+ cutState = Insecure;
+ }
+ cuts[end] = cutState;
+
+ cerr<<__func__<<", from "<<begin.toString()<<" to "<<end.toString()<<endl;
+
+#warning using d_requireAuthData here seems wrong
+ if (!validationEnabled() || !d_requireAuthData) {
+ return cuts;
+ }
+
+ if(!begin.isPartOf(end)) {
+ //throw PDNSException(end.toLogString() + " is not part of " + begin.toString());
+ cerr<<end.toLogString()<<" is not part of "<<begin.toString()<<endl;
+ }
+
+ DNSName qname(end);
+ std::vector<string> labelsToAdd = begin.makeRelative(end).getRawLabels();
+
+ while(qname != begin) {
+ bool foundCut = false;
+ if (labelsToAdd.empty())
+ break;
+
+ qname.prependRawLabel(labelsToAdd.back());
+ labelsToAdd.pop_back();
+ cerr<<"- Looking for a cut at "<<qname<<endl;
+
+ bool oldSkipCNAME = d_skipCNAMECheck;
+ bool oldRequireAuthData = d_requireAuthData;
+ d_skipCNAMECheck = true;
+ d_requireAuthData = false;
+
+ std::set<GetBestNSAnswer> beenthere;
+ std::vector<DNSRecord> nsrecords;
+
+ vState state = Indeterminate;
+ int rcode = doResolve(qname, QType(QType::NS), nsrecords, depth + 1, beenthere, state);
+ d_skipCNAMECheck = oldSkipCNAME;
+ d_requireAuthData = oldRequireAuthData;
+
+ if (rcode == RCode::NoError && !nsrecords.empty()) {
+ for (const auto& record : nsrecords) {
+ if(record.d_type != QType::NS || record.d_name != qname)
+ continue;
+ foundCut = true;
+ break;
+ }
+ if (foundCut) {
+ cerr<<"- Found cut at "<<qname<<endl;
+ dsmap_t ds;
+ cutState = getDSRecords(qname, ds, cutState == Insecure || cutState == Bogus, depth);
+ cerr<<"New state is "<<vStates[cutState]<<endl;
+ if (cutState == TA) {
+ cutState = Secure;
+ }
+ else if (cutState == NTA) {
+ cutState = Insecure;
+ }
+ cuts[qname] = cutState;
+ }
+ }
+ }
+
+ cerr<<"List of cuts from "<<begin<<" to "<<end<<endl;
+ for (const auto& cut : cuts) {
+ cerr<<" - "<<cut.first<<": "<<vStates[cut.second]<<endl;
+ }
+
+ return cuts;
+}
-void SyncRes::updateValidationStatusAfterReferral(const DNSName& oldauth, const DNSName& newauth, vState& state, unsigned int depth)
+void SyncRes::updateValidationStatusAfterReferral(const DNSName& qname, const DNSName& oldauth, const DNSName& newauth, vState& state, unsigned int depth)
{
if (!validationEnabled()) {
return;
return Bogus;
}
-RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, LWResult& lwr, const DNSName& qname, const DNSName& auth, bool wasForwarded, const boost::optional<Netmask> ednsmask, vState& state, bool& needWildcardProof)
+RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, LWResult& lwr, const DNSName& qname, const DNSName& auth, bool wasForwarded, const boost::optional<Netmask> ednsmask, vState& state, const SyncRes::zonesStates_t& cuts, bool& needWildcardProof)
{
struct CacheEntry
{
}
for(tcache_t::iterator i = tcache.begin(); i != tcache.end(); ++i) {
- vState recordState = state;
if(i->second.records.empty()) // this happens when we did store signatures, but passed on the records themselves
continue;
- if (validationEnabled() && state == Secure) {
+// vState recordState = state;
+ vState recordState = getValidationStatus(cuts, i->first.name);
+ cerr<<"Got status "<<vStates[recordState]<<" for record "<<i->first.name<<endl;
+
+ if (validationEnabled() && recordState == Secure) {
if (lwr.d_aabit) {
if (i->first.place != DNSResourceRecord::ADDITIONAL) {
/* the additional entries can be insecure,
return true;
}
-bool SyncRes::processAnswer(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType& qtype, DNSName& auth, bool wasForwarded, const boost::optional<Netmask> ednsmask, bool sendRDQuery, NsSet &nameservers, std::vector<DNSRecord>& ret, const DNSFilterEngine& dfe, bool* gotNewServers, int* rcode, vState& state)
+bool SyncRes::processAnswer(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType& qtype, DNSName& auth, bool wasForwarded, const boost::optional<Netmask> ednsmask, bool sendRDQuery, NsSet &nameservers, std::vector<DNSRecord>& ret, const DNSFilterEngine& dfe, bool* gotNewServers, int* rcode, vState& state, const SyncRes::zonesStates_t& cuts)
{
string prefix;
if(doLog()) {
}
bool needWildcardProof = false;
- *rcode = updateCacheFromRecords(depth, lwr, qname, auth, wasForwarded, ednsmask, state, needWildcardProof);
+ *rcode = updateCacheFromRecords(depth, lwr, qname, auth, wasForwarded, ednsmask, state, cuts, needWildcardProof);
if (*rcode != RCode::NoError) {
return true;
}
}
LOG("looping to them"<<endl);
*gotNewServers = true;
- updateValidationStatusAfterReferral(auth, newauth, state, depth);
+ //updateValidationStatusAfterReferral(qname, auth, newauth, state, depth);
auth=newauth;
return false;
*/
int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype,
vector<DNSRecord>&ret,
- unsigned int depth, set<GetBestNSAnswer>&beenthere, vState& state)
+ unsigned int depth, set<GetBestNSAnswer>&beenthere, vState& state, const SyncRes::zonesStates_t& cuts)
{
auto luaconfsLocal = g_luaconfs.getLocal();
string prefix;
lwr.d_aabit=true;
/* we have received an answer, are we done ? */
- bool done = processAnswer(depth, lwr, qname, qtype, auth, false, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state);
+ bool done = processAnswer(depth, lwr, qname, qtype, auth, false, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state, cuts);
if (done) {
return rcode;
}
t_sstorage.nsSpeeds[*tns].submit(*remoteIP, lwr.d_usec, &d_now);
/* we have received an answer, are we done ? */
- bool done = processAnswer(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state);
+ bool done = processAnswer(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state, cuts);
if (done) {
return rcode;
}
}
};
+ typedef std::map<DNSName,vState> zonesStates_t;
+
int doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret,
- unsigned int depth, set<GetBestNSAnswer>&beenthere, vState& state);
+ unsigned int depth, set<GetBestNSAnswer>&beenthere, vState& state, const zonesStates_t& cuts);
bool doResolveAtThisIP(const std::string& prefix, const DNSName& qname, const QType& qtype, LWResult& lwr, boost::optional<Netmask>& ednsmask, const DNSName& auth, bool const sendRDQuery, const DNSName& nsName, const ComboAddress& remoteIP, bool doTCP, bool* truncated);
- bool processAnswer(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType& qtype, DNSName& auth, bool wasForwarded, const boost::optional<Netmask> ednsmask, bool sendRDQuery, NsSet &nameservers, std::vector<DNSRecord>& ret, const DNSFilterEngine& dfe, bool* gotNewServers, int* rcode, vState& state);
+ bool processAnswer(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType& qtype, DNSName& auth, bool wasForwarded, const boost::optional<Netmask> ednsmask, bool sendRDQuery, NsSet &nameservers, std::vector<DNSRecord>& ret, const DNSFilterEngine& dfe, bool* gotNewServers, int* rcode, vState& state, const zonesStates_t& cuts);
int doResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, set<GetBestNSAnswer>& beenthere, vState& state);
bool doOOBResolve(const AuthDomain& domain, const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int& res) const;
bool throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, const QType& qtype, bool pierceDontQuery);
vector<ComboAddress> retrieveAddressesForNS(const std::string& prefix, const DNSName& qname, vector<DNSName >::const_iterator& tns, const unsigned int depth, set<GetBestNSAnswer>& beenthere, const vector<DNSName >& rnameservers, NsSet& nameservers, bool& sendRDQuery, bool& pierceDontQuery, bool& flawedNSSet);
- RCode::rcodes_ updateCacheFromRecords(unsigned int depth, LWResult& lwr, const DNSName& qname, const DNSName& auth, bool wasForwarded, const boost::optional<Netmask>, vState& state, bool& needWildcardProof);
+ RCode::rcodes_ updateCacheFromRecords(unsigned int depth, LWResult& lwr, const DNSName& qname, const DNSName& auth, bool wasForwarded, const boost::optional<Netmask>, vState& state, const zonesStates_t& cuts, bool& needWildcardProof);
bool processRecords(const std::string& prefix, const DNSName& qname, const QType& qtype, const DNSName& auth, LWResult& lwr, const bool sendRDQuery, vector<DNSRecord>& ret, set<DNSName>& nsset, DNSName& newtarget, DNSName& newauth, bool& realreferral, bool& negindic, vState& state, bool needWildcardProof);
bool doSpecialNamesResolve(const DNSName &qname, const QType &qtype, const uint16_t qclass, vector<DNSRecord> &ret);
bool validationEnabled() const;
uint32_t computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, uint32_t signaturesTTL) const;
void updateValidationState(vState& state, const vState stateUpdate);
- void updateValidationStatusAfterReferral(const DNSName& oldauth, const DNSName& newauth, vState& state, unsigned int depth);
+ void updateValidationStatusAfterReferral(const DNSName& qname, const DNSName& oldauth, const DNSName& newauth, vState& state, unsigned int depth);
vState validateRecordsWithSigs(unsigned int depth, const DNSName& name, const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures);
vState validateDNSKeys(const DNSName& zone, const std::vector<DNSRecord>& dnskeys, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, unsigned int depth);
vState getDSRecords(const DNSName& zone, dsmap_t& ds, bool onlyTA, unsigned int depth);
vState getDNSKeys(const DNSName& signer, skeyset_t& keys, unsigned int depth);
void getDenialValidationState(NegCache::NegCacheEntry& ne, vState& state, const dState expectedState, bool allowOptOut);
vState getTA(const DNSName& zone, dsmap_t& ds);
- vState getValidationStatus(const DNSName& subdomain, unsigned int depth);
+ vState getValidationStatus(const zonesStates_t& cuts, const DNSName& subdomain);
+
+ zonesStates_t computeZoneCuts(const DNSName& begin, const DNSName& end, unsigned int depth);
void setUpdatingRootNS()
{