const ComboAddress ns("192.0.2.1:53");
const ComboAddress forwardedNS("192.0.2.42:53");
+ size_t queriesCount = 0;
SyncRes::AuthDomain ad;
- ad.d_rdForward = false;
+ ad.d_rdForward = true;
ad.d_servers.push_back(forwardedNS);
(*SyncRes::t_sstorage.domainmap)[target] = ad;
- sr->setAsyncCallback([forwardedNS](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, bool* chained) {
+ sr->setAsyncCallback([forwardedNS, &queriesCount](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, bool* chained) {
+
+ queriesCount++;
if (ip == forwardedNS) {
- BOOST_CHECK_EQUAL(sendRDQuery, false);
+ BOOST_CHECK_EQUAL(sendRDQuery, true);
- setLWResult(res, 0, true, false, true);
+ /* set AA=0, we are a recursor */
+ setLWResult(res, 0, false, false, true);
addRecordToLW(res, domain, QType::A, "192.0.2.42");
return 1;
}
int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_CHECK_EQUAL(ret.size(), 1);
+ BOOST_CHECK_EQUAL(queriesCount, 1);
+
+ /* now make sure we can resolve from the cache (see #6340
+ where the entries were added to the cache but not retrieved,
+ because the recursor doesn't set the AA bit and we require
+ it. We fixed it by not requiring the AA bit for forward-recurse
+ answers. */
+ ret.clear();
+ res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+ BOOST_CHECK_EQUAL(res, RCode::NoError);
+ BOOST_CHECK_EQUAL(ret.size(), 1);
+ BOOST_CHECK_EQUAL(queriesCount, 1);
}
BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_nord) {
DNSName authname(qname);
bool wasForwardedOrAuthZone = false;
bool wasAuthZone = false;
+ bool wasForwardRecurse = false;
domainmap_t::const_iterator iter = getBestAuthZone(&authname);
if(iter != t_sstorage.domainmap->end()) {
+ const auto& domain = iter->second;
wasForwardedOrAuthZone = true;
- const vector<ComboAddress>& servers = iter->second.d_servers;
- if(servers.empty()) {
+
+ if (domain.isAuth()) {
wasAuthZone = true;
+ } else if (domain.shouldRecurse()) {
+ wasForwardRecurse = true;
}
}
- if(!d_skipCNAMECheck && doCNAMECacheCheck(qname, qtype, ret, depth, res, state, wasAuthZone)) { // will reroute us if needed
+ if(!d_skipCNAMECheck && doCNAMECacheCheck(qname, qtype, ret, depth, res, state, wasAuthZone, wasForwardRecurse)) { // will reroute us if needed
d_wasOutOfBand = wasAuthZone;
return res;
}
- if(doCacheCheck(qname, authname, wasForwardedOrAuthZone, wasAuthZone, qtype, ret, depth, res, state)) {
+ if(doCacheCheck(qname, authname, wasForwardedOrAuthZone, wasAuthZone, wasForwardRecurse, qtype, ret, depth, res, state)) {
// we done
d_wasOutOfBand = wasAuthZone;
return res;
return subdomain;
}
-bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>& ret, unsigned int depth, int &res, vState& state, bool wasAuthZone)
+bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>& ret, unsigned int depth, int &res, vState& state, bool wasAuthZone, bool wasForwardRecurse)
{
string prefix;
if(doLog()) {
vector<std::shared_ptr<RRSIGRecordContent>> signatures;
vector<std::shared_ptr<DNSRecord>> authorityRecs;
bool wasAuth;
- if(t_RC->get(d_now.tv_sec, qname, QType(QType::CNAME), d_requireAuthData, &cset, d_incomingECSFound ? d_incomingECSNetwork : d_requestor, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &state, &wasAuth) > 0) {
+ /* we don't require auth data for forward-recurse lookups */
+ if(t_RC->get(d_now.tv_sec, qname, QType(QType::CNAME), !wasForwardRecurse && d_requireAuthData, &cset, d_incomingECSFound ? d_incomingECSNetwork : d_requestor, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &state, &wasAuth) > 0) {
for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
if (j->d_class != QClass::IN) {
}
}
-bool SyncRes::doCacheCheck(const DNSName &qname, const DNSName& authname, bool wasForwardedOrAuthZone, bool wasAuthZone, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res, vState& state)
+bool SyncRes::doCacheCheck(const DNSName &qname, const DNSName& authname, bool wasForwardedOrAuthZone, bool wasAuthZone, bool wasForwardRecurse, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res, vState& state)
{
bool giveNegative=false;
vector<std::shared_ptr<DNSRecord>> authorityRecs;
uint32_t ttl=0;
bool wasCachedAuth;
- if(t_RC->get(d_now.tv_sec, sqname, sqt, d_requireAuthData, &cset, d_incomingECSFound ? d_incomingECSNetwork : d_requestor, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &cachedState, &wasCachedAuth) > 0) {
+ if(t_RC->get(d_now.tv_sec, sqname, sqt, !wasForwardRecurse && d_requireAuthData, &cset, d_incomingECSFound ? d_incomingECSNetwork : d_requestor, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &cachedState, &wasCachedAuth) > 0) {
LOG(prefix<<sqname<<": Found cache hit for "<<sqt.getName()<<": ");
bool doOOBResolve(const AuthDomain& domain, const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int& res);
bool doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res);
domainmap_t::const_iterator getBestAuthZone(DNSName* qname) const;
- bool doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res, vState& state, bool wasAuthZone);
- bool doCacheCheck(const DNSName &qname, const DNSName& authname, bool wasForwardedOrAuthZone, bool wasAuthZone, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res, vState& state);
+ bool doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res, vState& state, bool wasAuthZone, bool wasForwardRecurse);
+ bool doCacheCheck(const DNSName &qname, const DNSName& authname, bool wasForwardedOrAuthZone, bool wasAuthZone, bool wasForwardRecurse, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res, vState& state);
void getBestNSFromCache(const DNSName &qname, const QType &qtype, vector<DNSRecord>&bestns, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>& beenthere);
DNSName getBestNSNamesFromCache(const DNSName &qname, const QType &qtype, NsSet& nsset, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>&beenthere);