logIncomingResponse(outgoingLogger, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, len, lwr->d_rcode, lwr->d_records, queryTime);
}
#endif
+ lwr->d_validpacket=true;
return 1; // this is "success", the error is set in lwr->d_rcode
}
logIncomingResponse(outgoingLogger, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, len, lwr->d_rcode, lwr->d_records, queryTime);
}
#endif
+ lwr->d_validpacket=true;
return 1;
}
catch(std::exception &mde) {
logIncomingResponse(outgoingLogger, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, len, lwr->d_rcode, lwr->d_records, queryTime);
}
#endif
+ lwr->d_validpacket=false;
return 1; // success - oddly enough
}
catch(...) {
vector<DNSRecord> d_records;
int d_rcode{0};
+ bool d_validpacket{false};
bool d_aabit{false}, d_tcbit{false};
uint32_t d_usec{0};
bool d_haveEDNS{false};
g_dnssecmode = mode;
}
-static void setLWResult(LWResult* res, int rcode, bool aa=false, bool tc=false, bool edns=false)
+static void setLWResult(LWResult* res, int rcode, bool aa=false, bool tc=false, bool edns=false, bool validpacket=true)
{
res->d_rcode = rcode;
res->d_aabit = aa;
res->d_tcbit = tc;
res->d_haveEDNS = edns;
+ res->d_validpacket = validpacket;
}
static void addRecordToLW(LWResult* res, const DNSName& name, uint16_t type, const std::string& content, DNSResourceRecord::Place place=DNSResourceRecord::ANSWER, uint32_t ttl=60)
BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(noEDNSServer), SyncRes::EDNSStatus::NOEDNS);
}
-BOOST_AUTO_TEST_CASE(test_edns_notimp_fallback) {
- std::unique_ptr<SyncRes> sr;
- initSR(sr);
-
- size_t queriesWithEDNS = 0;
- size_t queriesWithoutEDNS = 0;
-
- sr->setAsyncCallback([&queriesWithEDNS, &queriesWithoutEDNS](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) {
- if (EDNS0Level != 0) {
- queriesWithEDNS++;
- setLWResult(res, RCode::NotImp);
- return 1;
- }
-
- queriesWithoutEDNS++;
-
- if (domain == DNSName("powerdns.com") && type == QType::A && !doTCP) {
- setLWResult(res, 0, true, false, false);
- addRecordToLW(res, domain, QType::A, "192.0.2.1");
- return 1;
- }
-
- return 0;
- });
-
- primeHints();
-
- /* fake that the NS doesn't handle EDNS, check that we fallback */
- vector<DNSRecord> ret;
- int res = sr->beginResolve(DNSName("powerdns.com."), QType(QType::A), QClass::IN, ret);
- BOOST_CHECK_EQUAL(res, RCode::NoError);
- BOOST_CHECK_EQUAL(ret.size(), 1);
- BOOST_CHECK_EQUAL(queriesWithEDNS, 1);
- BOOST_CHECK_EQUAL(queriesWithoutEDNS, 1);
-}
-
BOOST_AUTO_TEST_CASE(test_tc_fallback_to_tcp) {
std::unique_ptr<SyncRes> sr;
initSR(sr);
0) UNKNOWN Unknown state
1) EDNS: Honors EDNS0
2) EDNSIGNORANT: Ignores EDNS0, gives replies without EDNS0
- 3) NOEDNS: Generates FORMERR/NOTIMP on EDNS queries
+ 3) NOEDNS: Generates FORMERR on EDNS queries
Everybody starts out assumed to be '0'.
If '0', send out EDNS0
return ret;
}
else if(mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSOK || mode == EDNSStatus::EDNSIGNORANT ) {
- if(res->d_rcode == RCode::FormErr || res->d_rcode == RCode::NotImp) {
+ if(res->d_validpacket && res->d_rcode == RCode::FormErr) {
// cerr<<"Downgrading to NOEDNS because of "<<RCode::to_s(res->d_rcode)<<" for query to "<<ip.toString()<<" for '"<<domain<<"'"<<endl;
mode = EDNSStatus::NOEDNS;
continue;
else if(!res->d_haveEDNS) {
if(mode != EDNSStatus::EDNSIGNORANT) {
mode = EDNSStatus::EDNSIGNORANT;
- // cerr<<"We find that "<<ip.toString()<<" is an EDNS-ignorer for '"<<domain<<"', moving to mode 3"<<endl;
+ // cerr<<"We find that "<<ip.toString()<<" is an EDNS-ignorer for '"<<domain<<"', moving to mode 2"<<endl;
}
}
else {