diff --git pdns/axfr-retriever.cc pdns/axfr-retriever.cc index adac75b48..21c9f3b92 100644 --- pdns/axfr-retriever.cc +++ pdns/axfr-retriever.cc @@ -125,52 +125,50 @@ int AXFRRetriever::getChunk(Resolver::res_t &res, vector* records, ui timeoutReadn(len, timeout); d_receivedBytes += (uint16_t) len; - MOADNSParser mdp(false, d_buf.data(), len); - - int err = mdp.d_header.rcode; + try { + MOADNSParser mdp(false, d_buf.data(), len); - if(err) { - throw ResolverException("AXFR chunk error: " + RCode::to_s(err)); - } + int err = mdp.d_header.rcode; + if (err != 0) { + throw ResolverException("AXFR chunk error: " + RCode::to_s(err)); + } - if(mdp.d_header.tc) { - throw ResolverException("AXFR chunk had TC bit set"); - } + if(mdp.d_header.tc) { + throw ResolverException("AXFR chunk had TC bit set"); + } - try { d_tsigVerifier.check(std::string(d_buf.data(), len), mdp); - } - catch(const std::runtime_error& re) { - throw ResolverException(re.what()); - } - if(!records) { - err = parseResult(mdp, DNSName(), 0, 0, &res); - - if (!err) { - for(const auto& answer : mdp.d_answers) { - if (answer.d_type == QType::SOA) { - d_soacount++; + if (records == nullptr) { + err = parseResult(mdp, DNSName(), 0, 0, &res); + if (err == 0) { + for(const auto& answer : mdp.d_answers) { + if (answer.d_type == QType::SOA) { + d_soacount++; + } } } } - } - else { - records->clear(); - records->reserve(mdp.d_answers.size()); + else { + records->clear(); + records->reserve(mdp.d_answers.size()); - for(auto& r: mdp.d_answers) { - if (r.d_type == QType::SOA) { - d_soacount++; - } + for(auto& r: mdp.d_answers) { + if (r.d_type == QType::SOA) { + d_soacount++; + } - records->push_back(std::move(r)); + records->push_back(std::move(r)); + } } } + catch(const std::runtime_error& re) { + throw ResolverException(re.what()); + } return true; } void AXFRRetriever::timeoutReadn(uint16_t bytes, uint16_t timeoutsec) diff --git pdns/comfun.cc pdns/comfun.cc index 01a1fff2c..e2e046c7a 100644 --- pdns/comfun.cc +++ pdns/comfun.cc @@ -548,8 +548,11 @@ try else { cerr<<"Unknown mode "<topAllocatorsString(20)<(answer); - if (!content) { - g_log<(answer); + if (!content) { + g_log<(answer); - if (!content) { - g_log<(answer); + if (!content) { + g_log<empty()) - throw ResolverException("SOA query to '" + remote->toLogString() + "' produced response without domain name (RCode: " + RCode::to_s(mdp.d_header.rcode) + ")"); - - if(mdp.d_answers.empty()) - throw ResolverException("Query to '" + remote->toLogString() + "' for SOA of '" + domain->toLogString() + "' produced no results (RCode: " + RCode::to_s(mdp.d_header.rcode) + ")"); - - if(mdp.d_qtype != QType::SOA) - throw ResolverException("Query to '" + remote->toLogString() + "' for SOA of '" + domain->toLogString() + "' returned wrong record type"); - - if(mdp.d_header.rcode != 0) - throw ResolverException("Query to '" + remote->toLogString() + "' for SOA of '" + domain->toLogString() + "' returned Rcode " + RCode::to_s(mdp.d_header.rcode)); - - *theirInception = *theirExpire = 0; - bool gotSOA=false; - for(const MOADNSParser::answers_t::value_type& drc : mdp.d_answers) { - if(drc.d_type == QType::SOA && drc.d_name == *domain) { - auto src = getRR(drc); - if (src) { - *theirSerial = src->d_st.serial; - gotSOA = true; - } + bool gotSOA{false}; + try { + MOADNSParser mdp(false, (char*)buf, err); + *id=mdp.d_header.id; + *domain = mdp.d_qname; + + if(domain->empty()) { + throw ResolverException("SOA query to '" + remote->toLogString() + "' produced response without domain name (RCode: " + RCode::to_s(mdp.d_header.rcode) + ")"); + } + + if(mdp.d_answers.empty()) { + throw ResolverException("Query to '" + remote->toLogString() + "' for SOA of '" + domain->toLogString() + "' produced no results (RCode: " + RCode::to_s(mdp.d_header.rcode) + ")"); + } + + if(mdp.d_qtype != QType::SOA) { + throw ResolverException("Query to '" + remote->toLogString() + "' for SOA of '" + domain->toLogString() + "' returned wrong record type"); } - if(drc.d_type == QType::RRSIG && drc.d_name == *domain) { - auto rrc = getRR(drc); - if(rrc && rrc->d_type == QType::SOA) { - *theirInception= std::max(*theirInception, rrc->d_siginception); - *theirExpire = std::max(*theirExpire, rrc->d_sigexpire); + + if(mdp.d_header.rcode != 0) { + throw ResolverException("Query to '" + remote->toLogString() + "' for SOA of '" + domain->toLogString() + "' returned Rcode " + RCode::to_s(mdp.d_header.rcode)); + } + + *theirInception = *theirExpire = 0; + for(const MOADNSParser::answers_t::value_type& drc : mdp.d_answers) { + if(drc.d_type == QType::SOA && drc.d_name == *domain) { + auto src = getRR(drc); + if (src) { + *theirSerial = src->d_st.serial; + gotSOA = true; + } + } + if(drc.d_type == QType::RRSIG && drc.d_name == *domain) { + auto rrc = getRR(drc); + if(rrc && rrc->d_type == QType::SOA) { + *theirInception= std::max(*theirInception, rrc->d_siginception); + *theirExpire = std::max(*theirExpire, rrc->d_sigexpire); + } } } } - if(!gotSOA) + catch (const MOADNSException& exc) { + throw ResolverException("SOA Query to '" + remote->toLogString() + "' produced ill-formed response: " + exc.what()); + } + if(!gotSOA) { throw ResolverException("Query to '" + remote->toLogString() + "' for SOA of '" + domain->toLogString() + "' did not return a SOA"); + } return true; } int Resolver::resolve(const ComboAddress& to, const DNSName &domain, int type, Resolver::res_t* res, const ComboAddress &local) { @@ -335,10 +345,13 @@ int Resolver::resolve(const ComboAddress& to, const DNSName &domain, int type, R return parseResult(mdp, domain, type, id, res); } catch(ResolverException &re) { throw ResolverException(re.reason+" from "+to.toLogString()); } + catch (const MOADNSException& exc) { + throw ResolverException(std::string(exc.what()) + " from " + to.toLogString()); + } } int Resolver::resolve(const ComboAddress& ipport, const DNSName &domain, int type, Resolver::res_t* res) { ComboAddress local; local.sin4.sin_family = 0; diff --git pdns/stubresolver.cc pdns/stubresolver.cc index 64615ba8e..84f7a95e2 100644 --- pdns/stubresolver.cc +++ pdns/stubresolver.cc @@ -165,25 +165,31 @@ int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& r } } catch (...) { continue; } - MOADNSParser mdp(false, reply); - if (mdp.d_header.rcode == RCode::ServFail) { - continue; - } + try { + MOADNSParser mdp(false, reply); + if (mdp.d_header.rcode == RCode::ServFail) { + continue; + } - for (const auto& answer : mdp.d_answers) { - if (answer.d_place == 1 && answer.d_type == qtype) { - DNSZoneRecord zrr; - zrr.dr = answer; - zrr.auth = true; - ret.push_back(zrr); + for (const auto& answer : mdp.d_answers) { + if (answer.d_place == 1 && answer.d_type == qtype) { + DNSZoneRecord zrr; + zrr.dr = answer; + zrr.auth = true; + ret.push_back(std::move(zrr)); + } } + g_log << Logger::Debug << logPrefix << "Question for '" << queryNameType << "' got answered by " << dest.toString() << endl; + return mdp.d_header.rcode; + } + catch (const MOADNSException& exc) { + g_log << Logger::Debug << logPrefix << "Question for '" << queryNameType << "' got ill-formed answer from " << dest.toString() << ": " << exc.what() << endl; + continue; } - g_log << Logger::Debug << logPrefix << "Question for '" << queryNameType << "' got answered by " << dest.toString() << endl; - return mdp.d_header.rcode; } return RCode::ServFail; } int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& ret, const EDNSSubnetOpts* d_eso)