2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "arguments.hh"
27 #include "cachecleaner.hh"
28 #include "dns_random.hh"
29 #include "dnsparser.hh"
30 #include "dnsrecords.hh"
31 #include "ednssubnet.hh"
33 #include "lua-recursor4.hh"
34 #include "rec-lua-conf.hh"
36 #include "validate-recursor.hh"
38 thread_local
SyncRes::ThreadLocalStorage
SyncRes::t_sstorage
;
40 std::unordered_set
<DNSName
> SyncRes::s_delegationOnly
;
41 std::unique_ptr
<NetmaskGroup
> SyncRes::s_dontQuery
{nullptr};
42 NetmaskGroup
SyncRes::s_ednssubnets
;
43 SuffixMatchNode
SyncRes::s_ednsdomains
;
44 string
SyncRes::s_serverID
;
45 SyncRes::LogMode
SyncRes::s_lm
;
47 unsigned int SyncRes::s_maxnegttl
;
48 unsigned int SyncRes::s_maxcachettl
;
49 unsigned int SyncRes::s_maxqperq
;
50 unsigned int SyncRes::s_maxtotusec
;
51 unsigned int SyncRes::s_maxdepth
;
52 unsigned int SyncRes::s_minimumTTL
;
53 unsigned int SyncRes::s_packetcachettl
;
54 unsigned int SyncRes::s_packetcacheservfailttl
;
55 unsigned int SyncRes::s_serverdownmaxfails
;
56 unsigned int SyncRes::s_serverdownthrottletime
;
57 std::atomic
<uint64_t> SyncRes::s_queries
;
58 std::atomic
<uint64_t> SyncRes::s_outgoingtimeouts
;
59 std::atomic
<uint64_t> SyncRes::s_outgoing4timeouts
;
60 std::atomic
<uint64_t> SyncRes::s_outgoing6timeouts
;
61 std::atomic
<uint64_t> SyncRes::s_outqueries
;
62 std::atomic
<uint64_t> SyncRes::s_tcpoutqueries
;
63 std::atomic
<uint64_t> SyncRes::s_throttledqueries
;
64 std::atomic
<uint64_t> SyncRes::s_dontqueries
;
65 std::atomic
<uint64_t> SyncRes::s_nodelegated
;
66 std::atomic
<uint64_t> SyncRes::s_unreachables
;
67 std::atomic
<uint64_t> SyncRes::s_ecsqueries
;
68 std::atomic
<uint64_t> SyncRes::s_ecsresponses
;
69 uint8_t SyncRes::s_ecsipv4limit
;
70 uint8_t SyncRes::s_ecsipv6limit
;
71 bool SyncRes::s_doIPv6
;
72 bool SyncRes::s_nopacketcache
;
73 bool SyncRes::s_rootNXTrust
;
74 bool SyncRes::s_noEDNS
;
76 #define LOG(x) if(d_lm == Log) { L <<Logger::Warning << x; } else if(d_lm == Store) { d_trace << x; }
78 static void accountAuthLatency(int usec
, int family
)
80 if(family
== AF_INET
) {
82 g_stats
.auth4Answers0_1
++;
84 g_stats
.auth4Answers1_10
++;
85 else if(usec
< 100000)
86 g_stats
.auth4Answers10_100
++;
87 else if(usec
< 1000000)
88 g_stats
.auth4Answers100_1000
++;
90 g_stats
.auth4AnswersSlow
++;
93 g_stats
.auth6Answers0_1
++;
95 g_stats
.auth6Answers1_10
++;
96 else if(usec
< 100000)
97 g_stats
.auth6Answers10_100
++;
98 else if(usec
< 1000000)
99 g_stats
.auth6Answers100_1000
++;
101 g_stats
.auth6AnswersSlow
++;
107 SyncRes::SyncRes(const struct timeval
& now
) : d_outqueries(0), d_tcpoutqueries(0), d_throttledqueries(0), d_timeouts(0), d_unreachables(0),
108 d_totUsec(0), d_now(now
),
109 d_cacheonly(false), d_doDNSSEC(false), d_doEDNS0(false), d_lm(s_lm
)
114 /** everything begins here - this is the entry point just after receiving a packet */
115 int SyncRes::beginResolve(const DNSName
&qname
, const QType
&qtype
, uint16_t qclass
, vector
<DNSRecord
>&ret
)
117 vState state
= Indeterminate
;
120 d_wasOutOfBand
=false;
122 if (doSpecialNamesResolve(qname
, qtype
, qclass
, ret
)) {
123 d_queryValidationState
= Insecure
;
127 if( (qtype
.getCode() == QType::AXFR
) || (qtype
.getCode() == QType::IXFR
))
130 if(qclass
==QClass::ANY
)
132 else if(qclass
!=QClass::IN
)
135 set
<GetBestNSAnswer
> beenthere
;
136 int res
=doResolve(qname
, qtype
, ret
, 0, beenthere
, state
);
137 d_queryValidationState
= state
;
141 /*! Handles all special, built-in names
142 * Fills ret with an answer and returns true if it handled the query.
144 * Handles the following queries (and their ANY variants):
147 * - localhost. IN AAAA
148 * - 1.0.0.127.in-addr.arpa. IN PTR
149 * - 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. IN PTR
150 * - version.bind. CH TXT
151 * - version.pdns. CH TXT
152 * - id.server. CH TXT
154 bool SyncRes::doSpecialNamesResolve(const DNSName
&qname
, const QType
&qtype
, const uint16_t qclass
, vector
<DNSRecord
> &ret
)
156 static const DNSName
arpa("1.0.0.127.in-addr.arpa."), ip6_arpa("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa."),
157 localhost("localhost."), versionbind("version.bind."), idserver("id.server."), versionpdns("version.pdns.");
159 bool handled
= false;
160 vector
<pair
<QType::typeenum
, string
> > answers
;
162 if ((qname
== arpa
|| qname
== ip6_arpa
) &&
163 qclass
== QClass::IN
) {
165 if (qtype
== QType::PTR
|| qtype
== QType::ANY
)
166 answers
.push_back({QType::PTR
, "localhost."});
169 if (qname
== localhost
&&
170 qclass
== QClass::IN
) {
172 if (qtype
== QType::A
|| qtype
== QType::ANY
)
173 answers
.push_back({QType::A
, "127.0.0.1"});
174 if (qtype
== QType::AAAA
|| qtype
== QType::ANY
)
175 answers
.push_back({QType::AAAA
, "::1"});
178 if ((qname
== versionbind
|| qname
== idserver
|| qname
== versionpdns
) &&
179 qclass
== QClass::CHAOS
) {
181 if (qtype
== QType::TXT
|| qtype
== QType::ANY
) {
182 if(qname
== versionbind
|| qname
== versionpdns
)
183 answers
.push_back({QType::TXT
, "\""+::arg()["version-string"]+"\""});
185 answers
.push_back({QType::TXT
, "\""+s_serverID
+"\""});
189 if (handled
&& !answers
.empty()) {
195 dr
.d_place
= DNSResourceRecord::ANSWER
;
198 for (const auto& ans
: answers
) {
199 dr
.d_type
= ans
.first
;
200 dr
.d_content
= DNSRecordContent::mastermake(ans
.first
, qclass
, ans
.second
);
209 //! This is the 'out of band resolver', in other words, the authoritative server
210 void SyncRes::AuthDomain::addSOA(std::vector
<DNSRecord
>& records
) const
212 SyncRes::AuthDomain::records_t::const_iterator ziter
= d_records
.find(boost::make_tuple(getName(), QType::SOA
));
213 if (ziter
!= d_records
.end()) {
214 DNSRecord dr
= *ziter
;
215 dr
.d_place
= DNSResourceRecord::AUTHORITY
;
216 records
.push_back(dr
);
219 // cerr<<qname<<": can't find SOA record '"<<getName()<<"' in our zone!"<<endl;
223 int SyncRes::AuthDomain::getRecords(const DNSName
& qname
, uint16_t qtype
, std::vector
<DNSRecord
>& records
) const
225 int result
= RCode::NoError
;
229 std::pair
<records_t::const_iterator
,records_t::const_iterator
> range
= d_records
.equal_range(tie(qname
));
231 SyncRes::AuthDomain::records_t::const_iterator ziter
;
232 bool somedata
= false;
234 for(ziter
= range
.first
; ziter
!= range
.second
; ++ziter
) {
237 if(qtype
== QType::ANY
|| ziter
->d_type
== qtype
|| ziter
->d_type
== QType::CNAME
) {
238 // let rest of nameserver do the legwork on this one
239 records
.push_back(*ziter
);
241 else if (ziter
->d_type
== QType::NS
&& ziter
->d_name
.countLabels() > getName().countLabels()) {
242 // we hit a delegation point!
243 DNSRecord dr
= *ziter
;
244 dr
.d_place
=DNSResourceRecord::AUTHORITY
;
245 records
.push_back(dr
);
249 if (!records
.empty()) {
250 /* We have found an exact match, we're done */
251 // cerr<<qname<<": exact match in zone '"<<getName()<<"'"<<endl;
256 /* We have records for that name, but not of the wanted qtype */
257 // cerr<<qname<<": found record in '"<<getName()<<"', but nothing of the right type, sending SOA"<<endl;
263 // cerr<<qname<<": nothing found so far in '"<<getName()<<"', trying wildcards"<<endl;
264 DNSName
wcarddomain(qname
);
265 while(wcarddomain
!= getName() && wcarddomain
.chopOff()) {
266 // cerr<<qname<<": trying '*."<<wcarddomain<<"' in "<<getName()<<endl;
267 range
= d_records
.equal_range(boost::make_tuple(g_wildcarddnsname
+ wcarddomain
));
268 if (range
.first
==range
.second
)
271 for(ziter
= range
.first
; ziter
!= range
.second
; ++ziter
) {
272 DNSRecord dr
= *ziter
;
273 // if we hit a CNAME, just answer that - rest of recursor will do the needful & follow
274 if(dr
.d_type
== qtype
|| qtype
== QType::ANY
|| dr
.d_type
== QType::CNAME
) {
276 dr
.d_place
= DNSResourceRecord::ANSWER
;
277 records
.push_back(dr
);
281 if (records
.empty()) {
285 // cerr<<qname<<": in '"<<getName()<<"', had wildcard match on '*."<<wcarddomain<<"'"<<endl;
289 /* Nothing for this name, no wildcard, let's see if there is some NS */
290 DNSName
nsdomain(qname
);
291 while (nsdomain
.chopOff() && nsdomain
!= getName()) {
292 range
= d_records
.equal_range(boost::make_tuple(nsdomain
,QType::NS
));
293 if(range
.first
== range
.second
)
296 for(ziter
= range
.first
; ziter
!= range
.second
; ++ziter
) {
297 DNSRecord dr
= *ziter
;
298 dr
.d_place
= DNSResourceRecord::AUTHORITY
;
299 records
.push_back(dr
);
303 if(records
.empty()) {
304 // cerr<<qname<<": no NS match in zone '"<<getName()<<"' either, handing out SOA"<<endl;
306 result
= RCode::NXDomain
;
312 bool SyncRes::doOOBResolve(const AuthDomain
& domain
, const DNSName
&qname
, const QType
&qtype
, vector
<DNSRecord
>&ret
, int& res
) const
314 res
= domain
.getRecords(qname
, qtype
.getCode(), ret
);
318 bool SyncRes::doOOBResolve(const DNSName
&qname
, const QType
&qtype
, vector
<DNSRecord
>&ret
, unsigned int depth
, int& res
)
323 prefix
.append(depth
, ' ');
326 DNSName
authdomain(qname
);
327 domainmap_t::const_iterator iter
=getBestAuthZone(&authdomain
);
328 if(iter
==t_sstorage
.domainmap
->end() || !iter
->second
.isAuth()) {
329 LOG(prefix
<<qname
<<": auth storage has no zone for this query!"<<endl
);
333 LOG(prefix
<<qname
<<": auth storage has data, zone='"<<authdomain
<<"'"<<endl
);
334 return doOOBResolve(iter
->second
, qname
, qtype
, ret
, res
);
337 void SyncRes::doEDNSDumpAndClose(int fd
)
339 FILE* fp
=fdopen(fd
, "w");
343 fprintf(fp
,"IP Address\tMode\tMode last updated at\n");
344 for(const auto& eds
: t_sstorage
.ednsstatus
) {
345 fprintf(fp
, "%s\t%d\t%s", eds
.first
.toString().c_str(), (int)eds
.second
.mode
, ctime(&eds
.second
.modeSetAt
));
351 uint64_t SyncRes::doDumpNSSpeeds(int fd
)
353 FILE* fp
=fdopen(dup(fd
), "w");
356 fprintf(fp
, "; nsspeed dump from thread follows\n;\n");
359 for(const auto& i
: t_sstorage
.nsSpeeds
)
362 fprintf(fp
, "%s -> ", i
.first
.toString().c_str());
363 for(const auto& j
: i
.second
.d_collection
)
365 // typedef vector<pair<ComboAddress, DecayingEwma> > collection_t;
366 fprintf(fp
, "%s/%f ", j
.first
.toString().c_str(), j
.second
.peek());
374 /* so here is the story. First we complete the full resolution process for a domain name. And only THEN do we decide
375 to also do DNSSEC validation, which leads to new queries. To make this simple, we *always* ask for DNSSEC records
376 so that if there are RRSIGs for a name, we'll have them.
378 However, some hosts simply can't answer questions which ask for DNSSEC. This can manifest itself as:
383 The cause of "No answer" may be fragmentation, and it is tempting to probe if smaller answers would get through.
384 Another cause of "No answer" may simply be a network condition.
385 Nonsense answers are a clearer indication this host won't be able to do DNSSEC evah.
387 Previous implementations have suffered from turning off DNSSEC questions for an authoritative server based on timeouts.
388 A clever idea is to only turn off DNSSEC if we know a domain isn't signed anyhow. The problem with that really
389 clever idea however is that at this point in PowerDNS, we may simply not know that yet. All the DNSSEC thinking happens
390 elsewhere. It may not have happened yet.
392 For now this means we can't be clever, but will turn off DNSSEC if you reply with FormError or gibberish.
395 int SyncRes::asyncresolveWrapper(const ComboAddress
& ip
, bool ednsMANDATORY
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, LWResult
* res
) const
397 /* what is your QUEST?
398 the goal is to get as many remotes as possible on the highest level of EDNS support
401 0) UNKNOWN Unknown state
402 1) EDNS: Honors EDNS0
403 2) EDNSIGNORANT: Ignores EDNS0, gives replies without EDNS0
404 3) NOEDNS: Generates FORMERR/NOTIMP on EDNS queries
406 Everybody starts out assumed to be '0'.
407 If '0', send out EDNS0
408 If you FORMERR us, go to '3',
409 If no EDNS in response, go to '2'
410 If '1', send out EDNS0
411 If FORMERR, downgrade to 3
412 If '2', keep on including EDNS0, see what happens
414 If '3', send bare queries
417 SyncRes::EDNSStatus
* ednsstatus
;
418 ednsstatus
= &t_sstorage
.ednsstatus
[ip
]; // does this include port? YES
420 if(ednsstatus
->modeSetAt
&& ednsstatus
->modeSetAt
+ 3600 < d_now
.tv_sec
) {
421 *ednsstatus
=SyncRes::EDNSStatus();
422 // cerr<<"Resetting EDNS Status for "<<ip.toString()<<endl);
425 SyncRes::EDNSStatus::EDNSMode
& mode
=ednsstatus
->mode
;
426 SyncRes::EDNSStatus::EDNSMode oldmode
= mode
;
428 auto luaconfsLocal
= g_luaconfs
.getLocal();
431 ctx
.d_initialRequestId
= d_initialRequestId
;
435 for(int tries
= 0; tries
< 3; ++tries
) {
436 // cerr<<"Remote '"<<ip.toString()<<"' currently in mode "<<mode<<endl;
438 if(mode
==EDNSStatus::NOEDNS
) {
439 g_stats
.noEdnsOutQueries
++;
440 EDNSLevel
= 0; // level != mode
442 else if(ednsMANDATORY
|| mode
==EDNSStatus::UNKNOWN
|| mode
==EDNSStatus::EDNSOK
|| mode
==EDNSStatus::EDNSIGNORANT
)
445 if (d_asyncResolve
) {
446 ret
= d_asyncResolve(ip
, domain
, type
, doTCP
, sendRDQuery
, EDNSLevel
, now
, srcmask
, ctx
, luaconfsLocal
->outgoingProtobufServer
, res
);
449 ret
=asyncresolve(ip
, domain
, type
, doTCP
, sendRDQuery
, EDNSLevel
, now
, srcmask
, ctx
, luaconfsLocal
->outgoingProtobufServer
, res
);
452 return ret
; // transport error, nothing to learn here
455 if(ret
== 0) { // timeout, not doing anything with it now
458 else if(mode
==EDNSStatus::UNKNOWN
|| mode
==EDNSStatus::EDNSOK
|| mode
== EDNSStatus::EDNSIGNORANT
) {
459 if(res
->d_rcode
== RCode::FormErr
|| res
->d_rcode
== RCode::NotImp
) {
460 // cerr<<"Downgrading to NOEDNS because of "<<RCode::to_s(res->d_rcode)<<" for query to "<<ip.toString()<<" for '"<<domain<<"'"<<endl;
461 mode
= EDNSStatus::NOEDNS
;
464 else if(!res
->d_haveEDNS
) {
465 if(mode
!= EDNSStatus::EDNSIGNORANT
) {
466 mode
= EDNSStatus::EDNSIGNORANT
;
467 // cerr<<"We find that "<<ip.toString()<<" is an EDNS-ignorer for '"<<domain<<"', moving to mode 3"<<endl;
471 mode
= EDNSStatus::EDNSOK
;
472 // cerr<<"We find that "<<ip.toString()<<" is EDNS OK!"<<endl;
476 if(oldmode
!= mode
|| !ednsstatus
->modeSetAt
)
477 ednsstatus
->modeSetAt
=d_now
.tv_sec
;
478 // cerr<<"Result: ret="<<ret<<", EDNS-level: "<<EDNSLevel<<", haveEDNS: "<<res->d_haveEDNS<<", new mode: "<<mode<<endl;
484 /*! This function will check the cache and go out to the internet if the answer is not in cache
486 * \param qname The name we need an answer for
488 * \param ret The vector of DNSRecords we need to fill with the answers
489 * \param depth The recursion depth we are in
491 * \return DNS RCODE or -1 (Error) or -2 (RPZ hit)
493 int SyncRes::doResolve(const DNSName
&qname
, const QType
&qtype
, vector
<DNSRecord
>&ret
, unsigned int depth
, set
<GetBestNSAnswer
>& beenthere
, vState
& state
)
498 prefix
.append(depth
, ' ');
501 LOG(prefix
<<qname
<<": Wants "<< (d_doDNSSEC
? "" : "NO ") << "DNSSEC processing, "<<(d_requireAuthData
? "" : "NO ")<<"auth data in query for "<<qtype
.getName()<<endl
);
503 state
= Indeterminate
;
505 if(s_maxdepth
&& depth
> s_maxdepth
)
506 throw ImmediateServFailException("More than "+std::to_string(s_maxdepth
)+" (max-recursion-depth) levels of recursion needed while resolving "+qname
.toLogString());
510 // This is a difficult way of expressing "this is a normal query", i.e. not getRootNS.
511 if(!(d_updatingRootNS
&& qtype
.getCode()==QType::NS
&& qname
.isRoot())) {
512 if(d_cacheonly
) { // very limited OOB support
514 LOG(prefix
<<qname
<<": Recursion not requested for '"<<qname
<<"|"<<qtype
.getName()<<"', peeking at auth/forward zones"<<endl
);
515 DNSName
authname(qname
);
516 domainmap_t::const_iterator iter
=getBestAuthZone(&authname
);
517 if(iter
!= t_sstorage
.domainmap
->end()) {
518 if(iter
->second
.isAuth()) {
520 d_wasOutOfBand
= doOOBResolve(qname
, qtype
, ret
, depth
, res
);
524 const vector
<ComboAddress
>& servers
= iter
->second
.d_servers
;
525 const ComboAddress remoteIP
= servers
.front();
526 LOG(prefix
<<qname
<<": forwarding query to hardcoded nameserver '"<< remoteIP
.toStringWithPort()<<"' for zone '"<<authname
<<"'"<<endl
);
528 boost::optional
<Netmask
> nm
;
529 res
=asyncresolveWrapper(remoteIP
, d_doDNSSEC
, qname
, qtype
.getCode(), false, false, &d_now
, nm
, &lwr
);
530 // filter out the good stuff from lwr.result()
532 for(const auto& rec
: lwr
.d_records
) {
533 if(rec
.d_place
== DNSResourceRecord::ANSWER
)
539 return RCode::ServFail
;
545 if(!d_skipCNAMECheck
&& doCNAMECacheCheck(qname
,qtype
,ret
,depth
,res
,state
)) // will reroute us if needed
548 if(doCacheCheck(qname
,qtype
,ret
,depth
,res
,state
)) // we done
555 LOG(prefix
<<qname
<<": No cache hit for '"<<qname
<<"|"<<qtype
.getName()<<"', trying to find an appropriate NS record"<<endl
);
557 DNSName
subdomain(qname
);
558 if(qtype
== QType::DS
) subdomain
.chopOff();
561 bool flawedNSSet
=false;
563 computeZoneCuts(qname
, g_rootdnsname
, depth
);
565 // the two retries allow getBestNSNamesFromCache&co to reprime the root
566 // hints, in case they ever go missing
567 for(int tries
=0;tries
<2 && nsset
.empty();++tries
) {
568 subdomain
=getBestNSNamesFromCache(subdomain
, qtype
, nsset
, &flawedNSSet
, depth
, beenthere
); // pass beenthere to both occasions
571 state
= getValidationStatus(subdomain
);
573 LOG(prefix
<<qname
<<": initial validation status for "<<qname
<<" inherited from "<<subdomain
<<" is "<<vStates
[state
]<<endl
);
575 if(!(res
=doResolveAt(nsset
, subdomain
, flawedNSSet
, qname
, qtype
, ret
, depth
, beenthere
, state
)))
578 LOG(prefix
<<qname
<<": failed (res="<<res
<<")"<<endl
);
583 return res
<0 ? RCode::ServFail
: res
;
587 // for testing purposes
588 static bool ipv6First(const ComboAddress
& a
, const ComboAddress
& b
)
590 return !(a
.sin4
.sin_family
< a
.sin4
.sin_family
);
594 /** This function explicitly goes out for A or AAAA addresses
596 vector
<ComboAddress
> SyncRes::getAddrs(const DNSName
&qname
, unsigned int depth
, set
<GetBestNSAnswer
>& beenthere
)
598 typedef vector
<DNSRecord
> res_t
;
601 typedef vector
<ComboAddress
> ret_t
;
605 bool oldRequireAuthData
= d_requireAuthData
;
606 d_requireAuthData
= false;
608 for(int j
=1; j
<2+s_doIPv6
; j
++)
623 vState newState
= Indeterminate
;
624 if(!doResolve(qname
, type
, res
,depth
+1, beenthere
, newState
) && !res
.empty()) { // this consults cache, OR goes out
625 for(res_t::const_iterator i
=res
.begin(); i
!= res
.end(); ++i
) {
626 if(i
->d_type
== QType::A
|| i
->d_type
== QType::AAAA
) {
627 if(auto rec
= std::dynamic_pointer_cast
<ARecordContent
>(i
->d_content
))
628 ret
.push_back(rec
->getCA(53));
629 else if(auto aaaarec
= std::dynamic_pointer_cast
<AAAARecordContent
>(i
->d_content
))
630 ret
.push_back(aaaarec
->getCA(53));
636 if(j
==1 && s_doIPv6
) { // we got an A record, see if we have some AAAA lying around
637 vector
<DNSRecord
> cset
;
638 if(t_RC
->get(d_now
.tv_sec
, qname
, QType(QType::AAAA
), false, &cset
, d_incomingECSFound
? d_incomingECSNetwork
: d_requestor
) > 0) {
639 for(auto k
=cset
.cbegin();k
!=cset
.cend();++k
) {
640 if(k
->d_ttl
> (unsigned int)d_now
.tv_sec
) {
641 if (auto drc
= std::dynamic_pointer_cast
<AAAARecordContent
>(k
->d_content
)) {
642 ComboAddress ca
=drc
->getCA(53);
653 d_requireAuthData
= oldRequireAuthData
;
656 random_shuffle(ret
.begin(), ret
.end(), dns_random
);
658 // move 'best' address for this nameserver name up front
659 nsspeeds_t::iterator best
= t_sstorage
.nsSpeeds
.find(qname
);
661 if(best
!= t_sstorage
.nsSpeeds
.end())
662 for(ret_t::iterator i
=ret
.begin(); i
!= ret
.end(); ++i
) {
663 if(*i
==best
->second
.d_best
) { // got the fastest one
666 *ret
.begin()=best
->second
.d_best
;
676 void SyncRes::getBestNSFromCache(const DNSName
&qname
, const QType
& qtype
, vector
<DNSRecord
>& bestns
, bool* flawedNSSet
, unsigned int depth
, set
<GetBestNSAnswer
>& beenthere
)
679 DNSName
subdomain(qname
);
682 prefix
.append(depth
, ' ');
688 LOG(prefix
<<qname
<<": Checking if we have NS in cache for '"<<subdomain
<<"'"<<endl
);
689 vector
<DNSRecord
> ns
;
690 *flawedNSSet
= false;
692 if(t_RC
->get(d_now
.tv_sec
, subdomain
, QType(QType::NS
), false, &ns
, d_incomingECSFound
? d_incomingECSNetwork
: d_requestor
) > 0) {
693 for(auto k
=ns
.cbegin();k
!=ns
.cend(); ++k
) {
694 if(k
->d_ttl
> (unsigned int)d_now
.tv_sec
) {
695 vector
<DNSRecord
> aset
;
697 const DNSRecord
& dr
=*k
;
698 auto nrr
= getRR
<NSRecordContent
>(dr
);
699 if(nrr
&& (!nrr
->getNS().isPartOf(subdomain
) || t_RC
->get(d_now
.tv_sec
, nrr
->getNS(), s_doIPv6
? QType(QType::ADDR
) : QType(QType::A
),
700 false, doLog() ? &aset
: 0, d_incomingECSFound
? d_incomingECSNetwork
: d_requestor
) > 5)) {
701 bestns
.push_back(dr
);
702 LOG(prefix
<<qname
<<": NS (with ip, or non-glue) in cache for '"<<subdomain
<<"' -> '"<<nrr
->getNS()<<"'"<<endl
);
703 LOG(prefix
<<qname
<<": within bailiwick: "<< nrr
->getNS().isPartOf(subdomain
));
705 LOG(", in cache, ttl="<<(unsigned int)(((time_t)aset
.begin()->d_ttl
- d_now
.tv_sec
))<<endl
);
708 LOG(", not in cache / did not look at cache"<<endl
);
713 LOG(prefix
<<qname
<<": NS in cache for '"<<subdomain
<<"', but needs glue ("<<nrr
->getNS()<<") which we miss or is expired"<<endl
);
718 if(!bestns
.empty()) {
719 GetBestNSAnswer answer
;
721 answer
.qtype
=qtype
.getCode();
722 for(const auto& dr
: bestns
)
723 answer
.bestns
.insert(make_pair(dr
.d_name
, getRR
<NSRecordContent
>(dr
)->getNS()));
725 if(beenthere
.count(answer
)) {
727 LOG(prefix
<<qname
<<": We have NS in cache for '"<<subdomain
<<"' but part of LOOP (already seen "<<answer
.qname
<<")! Trying less specific NS"<<endl
);
730 for( set
<GetBestNSAnswer
>::const_iterator j
=beenthere
.begin();j
!=beenthere
.end();++j
) {
731 bool neo
= !(*j
< answer
|| answer
<*j
);
732 LOG(prefix
<<qname
<<": beenthere"<<(neo
?"*":"")<<": "<<j
->qname
<<"|"<<DNSRecordContent::NumberToType(j
->qtype
)<<" ("<<(unsigned int)j
->bestns
.size()<<")"<<endl
);
737 beenthere
.insert(answer
);
738 LOG(prefix
<<qname
<<": We have NS in cache for '"<<subdomain
<<"' (flawedNSSet="<<*flawedNSSet
<<")"<<endl
);
743 LOG(prefix
<<qname
<<": no valid/useful NS in cache for '"<<subdomain
<<"'"<<endl
);
745 if(subdomain
.isRoot() && !brokeloop
) {
746 // We lost the root NS records
748 LOG(prefix
<<qname
<<": reprimed the root"<<endl
);
749 /* let's prevent an infinite loop */
750 if (!d_updatingRootNS
) {
751 getRootNS(d_now
, d_asyncResolve
);
754 } while(subdomain
.chopOff());
757 SyncRes::domainmap_t::const_iterator
SyncRes::getBestAuthZone(DNSName
* qname
) const
759 SyncRes::domainmap_t::const_iterator ret
;
761 ret
=t_sstorage
.domainmap
->find(*qname
);
762 if(ret
!=t_sstorage
.domainmap
->end())
764 }while(qname
->chopOff());
768 /** doesn't actually do the work, leaves that to getBestNSFromCache */
769 DNSName
SyncRes::getBestNSNamesFromCache(const DNSName
&qname
, const QType
& qtype
, NsSet
& nsset
, bool* flawedNSSet
, unsigned int depth
, set
<GetBestNSAnswer
>&beenthere
)
771 DNSName
subdomain(qname
);
772 DNSName
authdomain(qname
);
774 domainmap_t::const_iterator iter
=getBestAuthZone(&authdomain
);
775 if(iter
!=t_sstorage
.domainmap
->end()) {
776 if( iter
->second
.isAuth() )
777 // this gets picked up in doResolveAt, the empty DNSName, combined with the
778 // empty vector means 'we are auth for this zone'
779 nsset
.insert({DNSName(), {{}, false}});
781 // Again, picked up in doResolveAt. An empty DNSName, combined with a
782 // non-empty vector of ComboAddresses means 'this is a forwarded domain'
783 // This is actually picked up in retrieveAddressesForNS called from doResolveAt.
784 nsset
.insert({DNSName(), {iter
->second
.d_servers
, iter
->second
.shouldRecurse() }});
789 vector
<DNSRecord
> bestns
;
790 getBestNSFromCache(subdomain
, qtype
, bestns
, flawedNSSet
, depth
, beenthere
);
792 for(auto k
=bestns
.cbegin() ; k
!= bestns
.cend(); ++k
) {
793 // The actual resolver code will not even look at the ComboAddress or bool
794 nsset
.insert({std::dynamic_pointer_cast
<NSRecordContent
>(k
->d_content
)->getNS(), {{}, false}});
795 if(k
==bestns
.cbegin())
801 bool SyncRes::doCNAMECacheCheck(const DNSName
&qname
, const QType
&qtype
, vector
<DNSRecord
>& ret
, unsigned int depth
, int &res
, vState
& state
)
806 prefix
.append(depth
, ' ');
809 if((depth
>9 && d_outqueries
>10 && d_throttledqueries
>5) || depth
> 15) {
810 LOG(prefix
<<qname
<<": recursing (CNAME or other indirection) too deep, depth="<<depth
<<endl
);
815 LOG(prefix
<<qname
<<": Looking for CNAME cache hit of '"<<qname
<<"|CNAME"<<"'"<<endl
);
816 vector
<DNSRecord
> cset
;
817 vector
<std::shared_ptr
<RRSIGRecordContent
>> signatures
;
818 vector
<std::shared_ptr
<DNSRecord
>> authorityRecs
;
820 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) {
822 for(auto j
=cset
.cbegin() ; j
!= cset
.cend() ; ++j
) {
823 if(j
->d_ttl
>(unsigned int) d_now
.tv_sec
) {
825 if (validationEnabled() && wasAuth
&& state
== Indeterminate
&& d_requireAuthData
) {
826 /* This means we couldn't figure out the state when this entry was cached,
827 most likely because we hadn't computed the zone cuts yet. */
828 /* make sure they are computed before validating */
829 computeZoneCuts(qname
, g_rootdnsname
, depth
);
831 vState recordState
= getValidationStatus(qname
);
832 if (recordState
== Secure
) {
833 LOG(prefix
<<qname
<<": got Indeterminate state from the CNAME cache, validating.."<<endl
);
834 state
= SyncRes::validateRecordsWithSigs(depth
, qname
, QType(QType::CNAME
), qname
, cset
, signatures
);
835 if (state
!= Indeterminate
) {
836 LOG(prefix
<<qname
<<": got Indeterminate state from the CNAME cache, new validation result is "<<vStates
[state
]<<endl
);
837 t_RC
->updateValidationStatus(d_now
.tv_sec
, qname
, QType(QType::CNAME
), d_incomingECSFound
? d_incomingECSNetwork
: d_requestor
, d_requireAuthData
, state
);
842 LOG(prefix
<<qname
<<": Found cache CNAME hit for '"<< qname
<< "|CNAME" <<"' to '"<<j
->d_content
->getZoneRepresentation()<<"', validation state is "<<vStates
[state
]<<endl
);
845 dr
.d_ttl
-=d_now
.tv_sec
;
848 for(const auto& signature
: signatures
) {
850 sigdr
.d_type
=QType::RRSIG
;
852 sigdr
.d_ttl
=j
->d_ttl
- d_now
.tv_sec
;
853 sigdr
.d_content
=signature
;
854 sigdr
.d_place
=DNSResourceRecord::ANSWER
;
855 sigdr
.d_class
=QClass::IN
;
856 ret
.push_back(sigdr
);
859 for(const auto& rec
: authorityRecs
) {
861 dr
.d_ttl
=j
->d_ttl
- d_now
.tv_sec
;
865 if(qtype
!= QType::CNAME
) { // perhaps they really wanted a CNAME!
866 set
<GetBestNSAnswer
>beenthere
;
868 vState cnameState
= Indeterminate
;
869 res
=doResolve(std::dynamic_pointer_cast
<CNAMERecordContent
>(j
->d_content
)->getTarget(), qtype
, ret
, depth
+1, beenthere
, cnameState
);
870 LOG(prefix
<<qname
<<": updating validation state for response to "<<qname
<<" from "<<vStates
[state
]<<" with the state from the CNAME quest: "<<vStates
[cnameState
]<<endl
);
871 updateValidationState(state
, cnameState
);
880 LOG(prefix
<<qname
<<": No CNAME cache hit of '"<< qname
<< "|CNAME" <<"' found"<<endl
);
885 * Convience function to push the records from records into ret with a new TTL
887 * \param records DNSRecords that need to go into ret
888 * \param ttl The new TTL for these records
889 * \param ret The vector of DNSRecords that should contian the records with the modified TTL
891 static void addTTLModifiedRecords(const vector
<DNSRecord
>& records
, const uint32_t ttl
, vector
<DNSRecord
>& ret
) {
892 for (const auto& rec
: records
) {
900 bool SyncRes::doCacheCheck(const DNSName
&qname
, const QType
&qtype
, vector
<DNSRecord
>&ret
, unsigned int depth
, int &res
, vState
& state
)
902 bool giveNegative
=false;
907 prefix
.append(depth
, ' ');
910 // sqname and sqtype are used contain 'higher' names if we have them (e.g. powerdns.com|SOA when we find a negative entry for doesnotexists.powerdns.com|A)
911 DNSName
sqname(qname
);
914 // cout<<"Lookup for '"<<qname<<"|"<<qtype.getName()<<"' -> "<<getLastLabel(qname)<<endl;
916 DNSName
authname(qname
);
918 bool wasForwardedOrAuth
= false;
919 bool wasAuth
= false;
920 domainmap_t::const_iterator iter
=getBestAuthZone(&authname
);
921 if(iter
!= t_sstorage
.domainmap
->end()) {
922 wasForwardedOrAuth
= true;
923 const vector
<ComboAddress
>& servers
= iter
->second
.d_servers
;
924 if(servers
.empty()) {
928 NegCache::NegCacheEntry ne
;
931 t_sstorage
.negcache
.getRootNXTrust(qname
, d_now
, ne
) &&
932 ne
.d_auth
.isRoot() &&
933 !(wasForwardedOrAuth
&& !authname
.isRoot())) { // when forwarding, the root may only neg-cache if it was forwarded to.
934 sttl
= ne
.d_ttd
- d_now
.tv_sec
;
935 LOG(prefix
<<qname
<<": Entire name '"<<qname
<<"', is negatively cached via '"<<ne
.d_auth
<<"' & '"<<ne
.d_name
<<"' for another "<<sttl
<<" seconds"<<endl
);
936 res
= RCode::NXDomain
;
938 cachedState
= ne
.d_validationState
;
940 else if (t_sstorage
.negcache
.get(qname
, qtype
, d_now
, ne
) &&
941 !(wasForwardedOrAuth
&& ne
.d_auth
!= authname
)) { // Only the authname nameserver can neg cache entries
943 sttl
= ne
.d_ttd
- d_now
.tv_sec
;
945 cachedState
= ne
.d_validationState
;
946 if(ne
.d_qtype
.getCode()) {
947 LOG(prefix
<<qname
<<": "<<qtype
.getName()<<" is negatively cached via '"<<ne
.d_auth
<<"' for another "<<sttl
<<" seconds"<<endl
);
948 res
= RCode::NoError
;
951 LOG(prefix
<<qname
<<": Entire name '"<<qname
<<"', is negatively cached via '"<<ne
.d_auth
<<"' for another "<<sttl
<<" seconds"<<endl
);
952 res
= RCode::NXDomain
;
955 addTTLModifiedRecords(ne
.DNSSECRecords
.records
, sttl
, ret
);
956 addTTLModifiedRecords(ne
.DNSSECRecords
.signatures
, sttl
, ret
);
961 // Transplant SOA to the returned packet
962 addTTLModifiedRecords(ne
.authoritySOA
.records
, sttl
, ret
);
964 addTTLModifiedRecords(ne
.authoritySOA
.signatures
, sttl
, ret
);
966 LOG(prefix
<<qname
<<": updating validation state with negative cache content for "<<qname
<<" to "<<vStates
[cachedState
]<<endl
);
971 vector
<DNSRecord
> cset
;
972 bool found
=false, expired
=false;
973 vector
<std::shared_ptr
<RRSIGRecordContent
>> signatures
;
974 vector
<std::shared_ptr
<DNSRecord
>> authorityRecs
;
977 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) {
979 LOG(prefix
<<sqname
<<": Found cache hit for "<<sqt
.getName()<<": ");
981 if (validationEnabled() && sqt
!= QType::DNSKEY
&& wasCachedAuth
&& cachedState
== Indeterminate
&& d_requireAuthData
) {
983 /* This means we couldn't figure out the state when this entry was cached,
984 most likely because we hadn't computed the zone cuts yet. */
985 /* make sure they are computed before validating */
986 computeZoneCuts(sqname
, g_rootdnsname
, depth
);
988 vState recordState
= getValidationStatus(qname
);
989 if (recordState
== Secure
) {
990 LOG(prefix
<<sqname
<<": got Indeterminate state from the cache, validating.."<<endl
);
991 cachedState
= SyncRes::validateRecordsWithSigs(depth
, sqname
, sqt
, sqname
, cset
, signatures
);
993 if (cachedState
!= Indeterminate
) {
994 LOG(prefix
<<qname
<<": got Indeterminate state from the cache, validation result is "<<vStates
[cachedState
]<<endl
);
995 t_RC
->updateValidationStatus(d_now
.tv_sec
, sqname
, sqt
, d_incomingECSFound
? d_incomingECSNetwork
: d_requestor
, d_requireAuthData
, cachedState
);
1000 for(auto j
=cset
.cbegin() ; j
!= cset
.cend() ; ++j
) {
1001 LOG(j
->d_content
->getZoneRepresentation());
1002 if(j
->d_ttl
>(unsigned int) d_now
.tv_sec
) {
1004 ttl
= (dr
.d_ttl
-=d_now
.tv_sec
);
1006 LOG("[ttl="<<dr
.d_ttl
<<"] ");
1015 for(const auto& signature
: signatures
) {
1017 dr
.d_type
=QType::RRSIG
;
1020 dr
.d_content
=signature
;
1021 dr
.d_place
= DNSResourceRecord::ANSWER
;
1022 dr
.d_class
=QClass::IN
;
1026 for(const auto& rec
: authorityRecs
) {
1033 if(found
&& !expired
) {
1036 d_wasOutOfBand
= wasAuth
;
1037 LOG(prefix
<<qname
<<": updating validation state with cache content for "<<qname
<<" to "<<vStates
[cachedState
]<<endl
);
1038 state
= cachedState
;
1042 LOG(prefix
<<qname
<<": cache had only stale entries"<<endl
);
1048 bool SyncRes::moreSpecificThan(const DNSName
& a
, const DNSName
&b
) const
1050 return (a
.isPartOf(b
) && a
.countLabels() > b
.countLabels());
1055 speedOrder(map
<DNSName
,double> &speeds
) : d_speeds(speeds
) {}
1056 bool operator()(const DNSName
&a
, const DNSName
&b
) const
1058 return d_speeds
[a
] < d_speeds
[b
];
1060 map
<DNSName
, double>& d_speeds
;
1063 inline vector
<DNSName
> SyncRes::shuffleInSpeedOrder(NsSet
&tnameservers
, const string
&prefix
)
1065 vector
<DNSName
> rnameservers
;
1066 rnameservers
.reserve(tnameservers
.size());
1067 for(const auto& tns
:tnameservers
) {
1068 rnameservers
.push_back(tns
.first
);
1070 map
<DNSName
, double> speeds
;
1072 for(const auto& val
: rnameservers
) {
1074 speed
=t_sstorage
.nsSpeeds
[val
].get(&d_now
);
1077 random_shuffle(rnameservers
.begin(),rnameservers
.end(), dns_random
);
1078 speedOrder
so(speeds
);
1079 stable_sort(rnameservers
.begin(),rnameservers
.end(), so
);
1082 LOG(prefix
<<"Nameservers: ");
1083 for(vector
<DNSName
>::const_iterator i
=rnameservers
.begin();i
!=rnameservers
.end();++i
) {
1084 if(i
!=rnameservers
.begin()) {
1086 if(!((i
-rnameservers
.begin())%3)) {
1087 LOG(endl
<<prefix
<<" ");
1090 LOG((i
->empty() ? string("<empty>") : i
->toString())<<"(" << (boost::format("%0.2f") % (speeds
[*i
]/1000.0)).str() <<"ms)");
1094 return rnameservers
;
1097 static bool magicAddrMatch(const QType
& query
, const QType
& answer
)
1099 if(query
.getCode() != QType::ADDR
)
1101 return answer
.getCode() == QType::A
|| answer
.getCode() == QType::AAAA
;
1104 static const set
<uint16_t> nsecTypes
= {QType::NSEC
, QType::NSEC3
};
1106 /* Fills the authoritySOA and DNSSECRecords fields from ne with those found in the records
1108 * \param records The records to parse for the authority SOA and NSEC(3) records
1109 * \param ne The NegCacheEntry to be filled out (will not be cleared, only appended to
1111 static void harvestNXRecords(const vector
<DNSRecord
>& records
, NegCache::NegCacheEntry
& ne
) {
1112 for(const auto& rec
: records
) {
1113 if(rec
.d_place
!= DNSResourceRecord::AUTHORITY
)
1114 // RFC 4035 section 3.1.3. indicates that NSEC records MUST be placed in
1115 // the AUTHORITY section. Section 3.1.1 indicates that that RRSIGs for
1116 // records MUST be in the same section as the records they cover.
1117 // Hence, we ignore all records outside of the AUTHORITY section.
1120 if(rec
.d_type
== QType::RRSIG
) {
1121 auto rrsig
= getRR
<RRSIGRecordContent
>(rec
);
1123 if(rrsig
->d_type
== QType::SOA
) {
1124 ne
.authoritySOA
.signatures
.push_back(rec
);
1126 if(nsecTypes
.count(rrsig
->d_type
)) {
1127 ne
.DNSSECRecords
.signatures
.push_back(rec
);
1132 if(rec
.d_type
== QType::SOA
) {
1133 ne
.authoritySOA
.records
.push_back(rec
);
1136 if(nsecTypes
.count(rec
.d_type
)) {
1137 ne
.DNSSECRecords
.records
.push_back(rec
);
1143 static cspmap_t
harvestCSPFromNE(const NegCache::NegCacheEntry
& ne
)
1146 for(const auto& rec
: ne
.DNSSECRecords
.signatures
) {
1147 if(rec
.d_type
== QType::RRSIG
) {
1148 auto rrc
= getRR
<RRSIGRecordContent
>(rec
);
1150 cspmap
[{rec
.d_name
,rrc
->d_type
}].signatures
.push_back(rrc
);
1154 for(const auto& rec
: ne
.DNSSECRecords
.records
) {
1155 cspmap
[{rec
.d_name
, rec
.d_type
}].records
.push_back(rec
.d_content
);
1160 // TODO remove after processRecords is fixed!
1161 // Adds the RRSIG for the SOA and the NSEC(3) + RRSIGs to ret
1162 static void addNXNSECS(vector
<DNSRecord
>&ret
, const vector
<DNSRecord
>& records
)
1164 NegCache::NegCacheEntry ne
;
1165 harvestNXRecords(records
, ne
);
1166 ret
.insert(ret
.end(), ne
.authoritySOA
.signatures
.begin(), ne
.authoritySOA
.signatures
.end());
1167 ret
.insert(ret
.end(), ne
.DNSSECRecords
.records
.begin(), ne
.DNSSECRecords
.records
.end());
1168 ret
.insert(ret
.end(), ne
.DNSSECRecords
.signatures
.begin(), ne
.DNSSECRecords
.signatures
.end());
1171 bool SyncRes::nameserversBlockedByRPZ(const DNSFilterEngine
& dfe
, const NsSet
& nameservers
)
1174 for (auto const &ns
: nameservers
) {
1175 d_appliedPolicy
= dfe
.getProcessingPolicy(ns
.first
, d_discardedPolicies
);
1176 if (d_appliedPolicy
.d_kind
!= DNSFilterEngine::PolicyKind::NoAction
) { // client query needs an RPZ response
1177 LOG(", however nameserver "<<ns
.first
<<" was blocked by RPZ policy '"<<(d_appliedPolicy
.d_name
? *d_appliedPolicy
.d_name
: "")<<"'"<<endl
);
1181 // Traverse all IP addresses for this NS to see if they have an RPN NSIP policy
1182 for (auto const &address
: ns
.second
.first
) {
1183 d_appliedPolicy
= dfe
.getProcessingPolicy(address
, d_discardedPolicies
);
1184 if (d_appliedPolicy
.d_kind
!= DNSFilterEngine::PolicyKind::NoAction
) { // client query needs an RPZ response
1185 LOG(", however nameserver "<<ns
.first
<<" IP address "<<address
.toString()<<" was blocked by RPZ policy '"<<(d_appliedPolicy
.d_name
? *d_appliedPolicy
.d_name
: "")<<"'"<<endl
);
1194 bool SyncRes::nameserverIPBlockedByRPZ(const DNSFilterEngine
& dfe
, const ComboAddress
& remoteIP
)
1197 d_appliedPolicy
= dfe
.getProcessingPolicy(remoteIP
, d_discardedPolicies
);
1198 if (d_appliedPolicy
.d_kind
!= DNSFilterEngine::PolicyKind::NoAction
) {
1199 LOG(" (blocked by RPZ policy '"+(d_appliedPolicy
.d_name
? *d_appliedPolicy
.d_name
: "")+"')");
1206 vector
<ComboAddress
> SyncRes::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
)
1208 vector
<ComboAddress
> result
;
1211 LOG(prefix
<<qname
<<": Trying to resolve NS '"<<*tns
<< "' ("<<1+tns
-rnameservers
.begin()<<"/"<<(unsigned int)rnameservers
.size()<<")"<<endl
);
1212 result
= getAddrs(*tns
, depth
+2, beenthere
);
1213 pierceDontQuery
=false;
1216 LOG(prefix
<<qname
<<": Domain has hardcoded nameserver");
1218 result
= nameservers
[*tns
].first
;
1219 if(result
.size() > 1) {
1224 sendRDQuery
= nameservers
[*tns
].second
;
1225 pierceDontQuery
=true;
1230 bool SyncRes::throttledOrBlocked(const std::string
& prefix
, const ComboAddress
& remoteIP
, const DNSName
& qname
, const QType
& qtype
, bool pierceDontQuery
)
1232 if(t_sstorage
.throttle
.shouldThrottle(d_now
.tv_sec
, boost::make_tuple(remoteIP
, "", 0))) {
1233 LOG(prefix
<<qname
<<": server throttled "<<endl
);
1234 s_throttledqueries
++; d_throttledqueries
++;
1237 else if(t_sstorage
.throttle
.shouldThrottle(d_now
.tv_sec
, boost::make_tuple(remoteIP
, qname
, qtype
.getCode()))) {
1238 LOG(prefix
<<qname
<<": query throttled "<<remoteIP
.toString()<<", "<<qname
<<"; "<<qtype
.getName()<<endl
);
1239 s_throttledqueries
++; d_throttledqueries
++;
1242 else if(!pierceDontQuery
&& s_dontQuery
&& s_dontQuery
->match(&remoteIP
)) {
1243 LOG(prefix
<<qname
<<": not sending query to " << remoteIP
.toString() << ", blocked by 'dont-query' setting" << endl
);
1250 bool SyncRes::validationEnabled() const
1252 return g_dnssecmode
!= DNSSECMode::Off
&& g_dnssecmode
!= DNSSECMode::ProcessNoValidate
;
1255 uint32_t SyncRes::computeLowestTTD(const std::vector
<DNSRecord
>& records
, const std::vector
<std::shared_ptr
<RRSIGRecordContent
> >& signatures
, uint32_t signaturesTTL
) const
1257 uint32_t lowestTTD
= std::numeric_limits
<uint32_t>::max();
1258 for(const auto& record
: records
)
1259 lowestTTD
= min(lowestTTD
, record
.d_ttl
);
1261 if (validationEnabled() && !signatures
.empty()) {
1262 /* if we are validating, we don't want to cache records after their signatures
1264 /* records TTL are now TTD, let's add 'now' to the signatures lowest TTL */
1265 lowestTTD
= min(lowestTTD
, static_cast<uint32_t>(signaturesTTL
+ d_now
.tv_sec
));
1267 for(const auto& sig
: signatures
) {
1268 if (sig
->d_siginception
<= d_now
.tv_sec
&& sig
->d_sigexpire
> d_now
.tv_sec
) {
1269 // we don't decerement d_sigexpire by 'now' because we actually want a TTD, not a TTL */
1270 lowestTTD
= min(lowestTTD
, static_cast<uint32_t>(sig
->d_sigexpire
));
1278 void SyncRes::updateValidationState(vState
& state
, const vState stateUpdate
)
1280 LOG(d_prefix
<<"validation state was "<<std::string(vStates
[state
])<<", state update is "<<std::string(vStates
[stateUpdate
])<<endl
);
1282 if (stateUpdate
== TA
) {
1285 else if (stateUpdate
== NTA
) {
1288 else if (stateUpdate
== Bogus
) {
1291 else if (state
== Indeterminate
) {
1292 state
= stateUpdate
;
1294 else if (stateUpdate
== Insecure
) {
1295 if (state
!= Bogus
) {
1299 LOG(d_prefix
<<" validation state is now "<<std::string(vStates
[state
])<<endl
);
1302 vState
SyncRes::getTA(const DNSName
& zone
, dsmap_t
& ds
)
1304 auto luaLocal
= g_luaconfs
.getLocal();
1306 if (luaLocal
->dsAnchors
.empty()) {
1307 /* We have no TA, everything is insecure */
1312 if (haveNegativeTrustAnchor(luaLocal
->negAnchors
, zone
, reason
)) {
1313 LOG(d_prefix
<<": got NTA for "<<zone
<<endl
);
1317 if (getTrustAnchor(luaLocal
->dsAnchors
, zone
, ds
)) {
1318 LOG(d_prefix
<<": got TA for "<<zone
<<endl
);
1322 if (zone
.isRoot()) {
1323 /* No TA for the root */
1327 return Indeterminate
;
1330 static size_t countSupportedDS(const dsmap_t
& dsmap
)
1334 for (const auto& ds
: dsmap
) {
1335 if (isSupportedDS(ds
)) {
1343 vState
SyncRes::getDSRecords(const DNSName
& zone
, dsmap_t
& ds
, bool taOnly
, unsigned int depth
)
1345 vState result
= getTA(zone
, ds
);
1347 if (result
!= Indeterminate
|| taOnly
) {
1348 if ((result
== Secure
|| result
== TA
) && countSupportedDS(ds
) == 0) {
1356 bool oldSkipCNAME
= d_skipCNAMECheck
;
1357 bool oldRequireAuthData
= d_requireAuthData
;
1358 d_skipCNAMECheck
= true;
1359 d_requireAuthData
= false;
1361 std::set
<GetBestNSAnswer
> beenthere
;
1362 std::vector
<DNSRecord
> dsrecords
;
1364 vState state
= Indeterminate
;
1365 int rcode
= doResolve(zone
, QType(QType::DS
), dsrecords
, depth
+ 1, beenthere
, state
);
1366 d_skipCNAMECheck
= oldSkipCNAME
;
1367 d_requireAuthData
= oldRequireAuthData
;
1369 if (rcode
== RCode::NoError
|| rcode
== RCode::NXDomain
) {
1370 if (state
== Secure
) {
1371 for (const auto& record
: dsrecords
) {
1372 if (record
.d_type
== QType::DS
) {
1373 const auto dscontent
= getRR
<DSRecordContent
>(record
);
1374 if (dscontent
&& isSupportedDS(*dscontent
)) {
1375 ds
.insert(*dscontent
);
1388 LOG(d_prefix
<<": returning Bogus state from "<<__func__
<<"("<<zone
<<")"<<endl
);
1392 bool SyncRes::haveExactValidationStatus(const DNSName
& domain
)
1394 if (!validationEnabled()) {
1397 const auto& it
= d_cutStates
.find(domain
);
1398 if (it
!= d_cutStates
.cend()) {
1404 vState
SyncRes::getValidationStatus(const DNSName
& subdomain
)
1406 vState result
= Indeterminate
;
1408 if (!validationEnabled()) {
1411 DNSName
name(subdomain
);
1413 const auto& it
= d_cutStates
.find(name
);
1414 if (it
!= d_cutStates
.cend()) {
1415 LOG(d_prefix
<<": got status "<<vStates
[it
->second
]<<" for name "<<subdomain
<<" (from "<<name
<<")"<<endl
);
1419 while (name
.chopOff());
1424 void SyncRes::computeZoneCuts(const DNSName
& begin
, const DNSName
& end
, unsigned int depth
)
1426 if(!begin
.isPartOf(end
)) {
1427 LOG(d_prefix
<<" "<<end
.toLogString()<<" is not part of "<<begin
.toString()<<endl
);
1428 throw PDNSException(end
.toLogString() + " is not part of " + begin
.toString());
1431 if (d_cutStates
.count(begin
) != 0) {
1436 vState cutState
= getDSRecords(end
, ds
, false, depth
);
1437 if (cutState
== TA
) {
1440 else if (cutState
== NTA
) {
1441 cutState
= Insecure
;
1443 LOG(d_prefix
<<": setting cut state for "<<end
<<" to "<<vStates
[cutState
]<<endl
);
1444 d_cutStates
[end
] = cutState
;
1446 if (!validationEnabled()) {
1451 std::vector
<string
> labelsToAdd
= begin
.makeRelative(end
).getRawLabels();
1453 bool oldSkipCNAME
= d_skipCNAMECheck
;
1454 bool oldRequireAuthData
= d_requireAuthData
;
1455 d_skipCNAMECheck
= true;
1456 d_requireAuthData
= false;
1458 while(qname
!= begin
) {
1459 bool foundCut
= false;
1460 if (labelsToAdd
.empty())
1463 qname
.prependRawLabel(labelsToAdd
.back());
1464 labelsToAdd
.pop_back();
1465 LOG(d_prefix
<<": - Looking for a cut at "<<qname
<<endl
);
1467 const auto cutIt
= d_cutStates
.find(qname
);
1468 if (cutIt
!= d_cutStates
.cend()) {
1469 if (cutIt
->second
!= Indeterminate
) {
1470 LOG(d_prefix
<<": - Cut already known at "<<qname
<<endl
);
1475 std::set
<GetBestNSAnswer
> beenthere
;
1476 std::vector
<DNSRecord
> nsrecords
;
1478 vState state
= Indeterminate
;
1479 /* temporarily mark as Indeterminate, so that we won't enter an endless loop
1480 trying to determine that zone cut again. */
1481 d_cutStates
[qname
] = state
;
1482 int rcode
= doResolve(qname
, QType(QType::NS
), nsrecords
, depth
+ 1, beenthere
, state
);
1484 if (rcode
== RCode::NoError
&& !nsrecords
.empty()) {
1485 for (const auto& record
: nsrecords
) {
1486 if(record
.d_type
!= QType::NS
|| record
.d_name
!= qname
)
1492 LOG(d_prefix
<<": - Found cut at "<<qname
<<endl
);
1493 /* if we get a Bogus state while retrieving the NS,
1494 the cut state is Bogus (we'll look for a (N)TA below though). */
1495 if (state
== Bogus
) {
1499 vState newState
= getDSRecords(qname
, ds
, cutState
== Insecure
|| cutState
== Bogus
, depth
);
1500 if (newState
!= Indeterminate
) {
1501 cutState
= newState
;
1503 LOG(d_prefix
<<": New state for "<<qname
<<" is "<<vStates
[cutState
]<<endl
);
1504 if (cutState
== TA
) {
1507 else if (cutState
== NTA
) {
1508 cutState
= Insecure
;
1510 d_cutStates
[qname
] = cutState
;
1514 /* remove the temporary cut */
1515 LOG(d_prefix
<<qname
<<": removing cut state for "<<qname
<<", was "<<vStates
[d_cutStates
[qname
]]<<endl
);
1516 d_cutStates
.erase(qname
);
1520 d_skipCNAMECheck
= oldSkipCNAME
;
1521 d_requireAuthData
= oldRequireAuthData
;
1523 LOG(d_prefix
<<": list of cuts from "<<begin
<<" to "<<end
<<endl
);
1524 for (const auto& cut
: d_cutStates
) {
1525 if (cut
.first
.isRoot() || (begin
.isPartOf(cut
.first
) && cut
.first
.isPartOf(end
))) {
1526 LOG(" - "<<cut
.first
<<": "<<vStates
[cut
.second
]<<endl
);
1531 vState
SyncRes::validateDNSKeys(const DNSName
& zone
, const std::vector
<DNSRecord
>& dnskeys
, const std::vector
<std::shared_ptr
<RRSIGRecordContent
> >& signatures
, unsigned int depth
)
1534 if (!signatures
.empty()) {
1535 DNSName signer
= getSigner(signatures
);
1537 if (!signer
.empty() && signer
.isPartOf(zone
)) {
1538 vState state
= getDSRecords(signer
, ds
, false, depth
);
1543 if (state
!= Secure
) {
1552 skeyset_t tentativeKeys
;
1553 std::vector
<shared_ptr
<DNSRecordContent
> > toSign
;
1555 for (const auto& dnskey
: dnskeys
) {
1556 if (dnskey
.d_type
== QType::DNSKEY
) {
1557 auto content
= getRR
<DNSKEYRecordContent
>(dnskey
);
1559 tentativeKeys
.insert(content
);
1560 toSign
.push_back(content
);
1565 LOG(d_prefix
<<": trying to validate "<<std::to_string(tentativeKeys
.size())<<" DNSKEYs with "<<std::to_string(ds
.size())<<" DS"<<endl
);
1566 skeyset_t validatedKeys
;
1567 validateDNSKeysAgainstDS(d_now
.tv_sec
, zone
, ds
, tentativeKeys
, toSign
, signatures
, validatedKeys
);
1569 LOG(d_prefix
<<": we now have "<<std::to_string(validatedKeys
.size())<<" DNSKEYs"<<endl
);
1571 /* if we found at least one valid RRSIG covering the set,
1572 all tentative keys are validated keys. Otherwise it means
1573 we haven't found at least one DNSKEY and a matching RRSIG
1574 covering this set, this looks Bogus. */
1575 if (validatedKeys
.size() != tentativeKeys
.size()) {
1576 LOG(d_prefix
<<": returning Bogus state from "<<__func__
<<"("<<zone
<<")"<<endl
);
1583 vState
SyncRes::getDNSKeys(const DNSName
& signer
, skeyset_t
& keys
, unsigned int depth
)
1585 std::vector
<DNSRecord
> records
;
1586 std::set
<GetBestNSAnswer
> beenthere
;
1587 LOG(d_prefix
<<"Retrieving DNSKeys for "<<signer
<<endl
);
1589 vState state
= Indeterminate
;
1590 /* following CNAME might lead to us to the wrong DNSKEY */
1591 bool oldSkipCNAME
= d_skipCNAMECheck
;
1592 d_skipCNAMECheck
= true;
1593 int rcode
= doResolve(signer
, QType(QType::DNSKEY
), records
, depth
+ 1, beenthere
, state
);
1594 d_skipCNAMECheck
= oldSkipCNAME
;
1596 if (rcode
== RCode::NoError
) {
1597 if (state
== Secure
) {
1598 for (const auto& key
: records
) {
1599 if (key
.d_type
== QType::DNSKEY
) {
1600 auto content
= getRR
<DNSKEYRecordContent
>(key
);
1602 keys
.insert(content
);
1607 LOG(d_prefix
<<"Retrieved "<<keys
.size()<<" DNSKeys for "<<signer
<<", state is "<<vStates
[state
]<<endl
);
1611 LOG(d_prefix
<<"Returning Bogus state from "<<__func__
<<"("<<signer
<<")"<<endl
);
1615 vState
SyncRes::validateRecordsWithSigs(unsigned int depth
, const DNSName
& qname
, const QType
& qtype
, const DNSName
& name
, const std::vector
<DNSRecord
>& records
, const std::vector
<std::shared_ptr
<RRSIGRecordContent
> >& signatures
)
1618 if (!signatures
.empty()) {
1619 const DNSName signer
= getSigner(signatures
);
1620 if (!signer
.empty() && name
.isPartOf(signer
)) {
1621 if (qtype
== QType::DNSKEY
&& signer
== qname
) {
1622 /* we are already retrieving those keys, sorry */
1623 return Indeterminate
;
1625 vState state
= getDNSKeys(signer
, keys
, depth
);
1626 if (state
!= Secure
) {
1631 LOG(d_prefix
<<"Bogus!"<<endl
);
1635 std::vector
<std::shared_ptr
<DNSRecordContent
> > recordcontents
;
1636 for (const auto& record
: records
) {
1637 recordcontents
.push_back(record
.d_content
);
1640 LOG(d_prefix
<<"Going to validate "<<recordcontents
.size()<< " record contents with "<<signatures
.size()<<" sigs and "<<keys
.size()<<" keys for "<<name
<<endl
);
1641 if (validateWithKeySet(d_now
.tv_sec
, name
, recordcontents
, signatures
, keys
, false)) {
1642 LOG(d_prefix
<<"Secure!"<<endl
);
1646 LOG(d_prefix
<<"Bogus!"<<endl
);
1650 RCode::rcodes_
SyncRes::updateCacheFromRecords(unsigned int depth
, LWResult
& lwr
, const DNSName
& qname
, const QType
& qtype
, const DNSName
& auth
, bool wasForwarded
, const boost::optional
<Netmask
> ednsmask
, vState
& state
, bool& needWildcardProof
)
1654 vector
<DNSRecord
> records
;
1655 vector
<shared_ptr
<RRSIGRecordContent
>> signatures
;
1656 uint32_t signaturesTTL
{std::numeric_limits
<uint32_t>::max()};
1662 DNSResourceRecord::Place place
;
1663 bool operator<(const CacheKey
& rhs
) const {
1664 return tie(name
, type
) < tie(rhs
.name
, rhs
.type
);
1667 typedef map
<CacheKey
, CacheEntry
> tcache_t
;
1673 prefix
.append(depth
, ' ');
1676 std::vector
<std::shared_ptr
<DNSRecord
>> authorityRecs
;
1677 bool isCNAMEAnswer
= false;
1678 for(const auto& rec
: lwr
.d_records
) {
1679 if(!isCNAMEAnswer
&& rec
.d_place
== DNSResourceRecord::ANSWER
&& rec
.d_type
== QType::CNAME
&& (!(qtype
==QType(QType::CNAME
))) && rec
.d_name
== qname
) {
1680 isCNAMEAnswer
= true;
1683 if(needWildcardProof
) {
1684 if (nsecTypes
.count(rec
.d_type
)) {
1685 authorityRecs
.push_back(std::make_shared
<DNSRecord
>(rec
));
1687 else if (rec
.d_type
== QType::RRSIG
) {
1688 auto rrsig
= getRR
<RRSIGRecordContent
>(rec
);
1689 if (rrsig
&& nsecTypes
.count(rrsig
->d_type
)) {
1690 authorityRecs
.push_back(std::make_shared
<DNSRecord
>(rec
));
1694 if(rec
.d_type
== QType::RRSIG
) {
1695 auto rrsig
= getRR
<RRSIGRecordContent
>(rec
);
1697 unsigned int labelCount
= rec
.d_name
.countLabels();
1698 /* As illustrated in rfc4035's Appendix B.6, the RRSIG label
1699 count can be lower than the name's label count if it was
1700 synthesized from the wildcard. Note that the difference might
1702 if (rec
.d_name
== qname
&& rrsig
->d_labels
< labelCount
) {
1703 LOG(prefix
<<qname
<<": RRSIG indicates the name was expanded from a wildcard, we need a wildcard proof"<<endl
);
1704 needWildcardProof
= true;
1707 // cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.d_name<<"'"<<endl;
1708 tcache
[{rec
.d_name
, rrsig
->d_type
, rec
.d_place
}].signatures
.push_back(rrsig
);
1709 tcache
[{rec
.d_name
, rrsig
->d_type
, rec
.d_place
}].signaturesTTL
= std::min(tcache
[{rec
.d_name
, rrsig
->d_type
, rec
.d_place
}].signaturesTTL
, rec
.d_ttl
);
1714 // reap all answers from this packet that are acceptable
1715 for(auto& rec
: lwr
.d_records
) {
1716 if(rec
.d_type
== QType::OPT
) {
1717 LOG(prefix
<<qname
<<": OPT answer '"<<rec
.d_name
<<"' from '"<<auth
<<"' nameservers" <<endl
);
1720 LOG(prefix
<<qname
<<": accept answer '"<<rec
.d_name
<<"|"<<DNSRecordContent::NumberToType(rec
.d_type
)<<"|"<<rec
.d_content
->getZoneRepresentation()<<"' from '"<<auth
<<"' nameservers? "<<(int)rec
.d_place
<<" ");
1721 if(rec
.d_type
== QType::ANY
) {
1722 LOG("NO! - we don't accept 'ANY' data"<<endl
);
1726 if(rec
.d_name
.isPartOf(auth
)) {
1727 if(rec
.d_type
== QType::RRSIG
) {
1728 LOG("RRSIG - separate"<<endl
);
1730 else if(lwr
.d_aabit
&& lwr
.d_rcode
==RCode::NoError
&& rec
.d_place
==DNSResourceRecord::ANSWER
&& ((rec
.d_type
!= QType::DNSKEY
&& rec
.d_type
!= QType::DS
) || rec
.d_name
!= auth
) && s_delegationOnly
.count(auth
)) {
1731 LOG("NO! Is from delegation-only zone"<<endl
);
1733 return RCode::NXDomain
;
1736 bool haveLogged
= false;
1737 if (!t_sstorage
.domainmap
->empty()) {
1738 // Check if we are authoritative for a zone in this answer
1739 DNSName
tmp_qname(rec
.d_name
);
1740 auto auth_domain_iter
=getBestAuthZone(&tmp_qname
);
1741 if(auth_domain_iter
!=t_sstorage
.domainmap
->end() &&
1742 auth
.countLabels() <= auth_domain_iter
->first
.countLabels()) {
1743 if (auth_domain_iter
->first
!= auth
) {
1744 LOG("NO! - we are authoritative for the zone "<<auth_domain_iter
->first
<<endl
);
1747 LOG("YES! - This answer was ");
1748 if (!wasForwarded
) {
1749 LOG("retrieved from the local auth store.");
1751 LOG("received from a server we forward to.");
1762 rec
.d_ttl
=min(s_maxcachettl
, rec
.d_ttl
);
1765 dr
.d_ttl
+= d_now
.tv_sec
;
1766 dr
.d_place
=DNSResourceRecord::ANSWER
;
1767 tcache
[{rec
.d_name
,rec
.d_type
,rec
.d_place
}].records
.push_back(dr
);
1775 for(tcache_t::iterator i
= tcache
.begin(); i
!= tcache
.end(); ++i
) {
1776 if((i
->second
.records
.size() + i
->second
.signatures
.size()) > 1) { // need to group the ttl to be the minimum of the RRSET (RFC 2181, 5.2)
1777 uint32_t lowestTTD
=computeLowestTTD(i
->second
.records
, i
->second
.signatures
, i
->second
.signaturesTTL
);
1779 for(auto& record
: i
->second
.records
)
1780 record
.d_ttl
= lowestTTD
; // boom
1783 // cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.name;
1784 // cout<<'|'<<DNSRecordContent::NumberToType(i->first.type)<<endl;
1787 for(tcache_t::iterator i
= tcache
.begin(); i
!= tcache
.end(); ++i
) {
1789 if(i
->second
.records
.empty()) // this happens when we did store signatures, but passed on the records themselves
1792 bool isAA
= lwr
.d_aabit
;
1793 if (isAA
&& isCNAMEAnswer
&& (i
->first
.place
!= DNSResourceRecord::ANSWER
|| i
->first
.type
!= QType::CNAME
)) {
1796 Note that the answer section of an authoritative answer normally
1797 contains only authoritative data. However when the name sought is an
1798 alias (see section 10.1.1) only the record describing that alias is
1799 necessarily authoritative. Clients should assume that other records
1800 may have come from the server's cache. Where authoritative answers
1801 are required, the client should query again, using the canonical name
1802 associated with the alias.
1807 vState recordState
= getValidationStatus(auth
);
1808 LOG(d_prefix
<<": got initial zone status "<<vStates
[recordState
]<<" for record "<<i
->first
.name
<<endl
);
1810 if (validationEnabled() && recordState
== Secure
) {
1812 if (i
->first
.place
!= DNSResourceRecord::ADDITIONAL
) {
1813 /* the additional entries can be insecure,
1815 "Glue address RRsets associated with delegations MUST NOT be signed"
1817 if (i
->first
.type
== QType::DNSKEY
&& i
->first
.place
== DNSResourceRecord::ANSWER
) {
1818 LOG(d_prefix
<<"Validating DNSKEY for "<<i
->first
.name
<<endl
);
1819 recordState
= validateDNSKeys(i
->first
.name
, i
->second
.records
, i
->second
.signatures
, depth
);
1822 LOG(d_prefix
<<"Validating non-additional record for "<<i
->first
.name
<<endl
);
1823 recordState
= validateRecordsWithSigs(depth
, qname
, qtype
, i
->first
.name
, i
->second
.records
, i
->second
.signatures
);
1824 /* we might have missed a cut (zone cut within the same auth servers), causing the NS query for an Insecure zone to seem Bogus during zone cut determination */
1825 if (qtype
== QType::NS
&& i
->second
.signatures
.empty() && recordState
== Bogus
&& haveExactValidationStatus(i
->first
.name
) && getValidationStatus(i
->first
.name
) == Indeterminate
) {
1826 recordState
= Indeterminate
;
1832 /* in a non authoritative answer, we only care about the DS record (or lack of) */
1833 if ((i
->first
.type
== QType::DS
|| i
->first
.type
== QType::NSEC
|| i
->first
.type
== QType::NSEC3
) && i
->first
.place
== DNSResourceRecord::AUTHORITY
) {
1834 LOG(d_prefix
<<"Validating DS record for "<<i
->first
.name
<<endl
);
1835 recordState
= validateRecordsWithSigs(depth
, qname
, qtype
, i
->first
.name
, i
->second
.records
, i
->second
.signatures
);
1839 updateValidationState(state
, recordState
);
1842 if (validationEnabled()) {
1843 LOG(d_prefix
<<"Skipping validation because the current state is "<<vStates
[recordState
]<<endl
);
1847 t_RC
->replace(d_now
.tv_sec
, i
->first
.name
, QType(i
->first
.type
), i
->second
.records
, i
->second
.signatures
, authorityRecs
, isAA
, i
->first
.place
== DNSResourceRecord::ANSWER
? ednsmask
: boost::none
, recordState
);
1849 if(i
->first
.place
== DNSResourceRecord::ANSWER
&& ednsmask
)
1853 return RCode::NoError
;
1856 void SyncRes::getDenialValidationState(NegCache::NegCacheEntry
& ne
, vState
& state
, const dState expectedState
, bool allowOptOut
)
1858 ne
.d_validationState
= state
;
1860 if (state
== Secure
) {
1861 cspmap_t csp
= harvestCSPFromNE(ne
);
1862 dState res
= getDenial(csp
, ne
.d_name
, ne
.d_qtype
.getCode());
1863 if (res
!= expectedState
) {
1864 if (res
== OPTOUT
&& allowOptOut
) {
1865 LOG(d_prefix
<<"OPT-out denial found for "<<ne
.d_name
<<", retuning Insecure"<<endl
);
1866 ne
.d_validationState
= Secure
;
1867 updateValidationState(state
, Insecure
);
1870 else if (res
== INSECURE
) {
1871 LOG(d_prefix
<<"Insecure denial found for "<<ne
.d_name
<<", retuning Insecure"<<endl
);
1872 ne
.d_validationState
= Insecure
;
1874 if (res
== NXDOMAIN
&& expectedState
== NXQTYPE
) {
1875 /* might happen for empty non-terminal, have fun */
1879 LOG(d_prefix
<<"Invalid denial found for "<<ne
.d_name
<<", retuning Bogus"<<endl
);
1880 ne
.d_validationState
= Bogus
;
1882 updateValidationState(state
, ne
.d_validationState
);
1887 bool SyncRes::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
)
1891 for(auto& rec
: lwr
.d_records
) {
1892 if (rec
.d_type
!=QType::OPT
&& rec
.d_class
!=QClass::IN
)
1895 if(rec
.d_place
==DNSResourceRecord::AUTHORITY
&& rec
.d_type
==QType::SOA
&&
1896 lwr
.d_rcode
==RCode::NXDomain
&& qname
.isPartOf(rec
.d_name
) && rec
.d_name
.isPartOf(auth
)) {
1897 LOG(prefix
<<qname
<<": got negative caching indication for name '"<<qname
<<"' (accept="<<rec
.d_name
.isPartOf(auth
)<<"), newtarget='"<<newtarget
<<"'"<<endl
);
1899 rec
.d_ttl
= min(rec
.d_ttl
, s_maxnegttl
);
1900 if(newtarget
.empty()) // only add a SOA if we're not going anywhere after this
1902 if(!wasVariable()) {
1903 NegCache::NegCacheEntry ne
;
1905 ne
.d_ttd
= d_now
.tv_sec
+ rec
.d_ttl
;
1907 ne
.d_qtype
= QType(0); // this encodes 'whole record'
1908 ne
.d_auth
= rec
.d_name
;
1909 harvestNXRecords(lwr
.d_records
, ne
);
1910 getDenialValidationState(ne
, state
, NXDOMAIN
, false);
1911 t_sstorage
.negcache
.add(ne
);
1912 if(s_rootNXTrust
&& ne
.d_auth
.isRoot() && auth
.isRoot()) {
1913 ne
.d_name
= ne
.d_name
.getLastLabel();
1914 t_sstorage
.negcache
.add(ne
);
1920 else if(rec
.d_place
==DNSResourceRecord::ANSWER
&& rec
.d_type
==QType::CNAME
&& (!(qtype
==QType(QType::CNAME
))) && rec
.d_name
== qname
) {
1922 if (auto content
= getRR
<CNAMERecordContent
>(rec
)) {
1923 newtarget
=content
->getTarget();
1926 else if((rec
.d_type
==QType::RRSIG
|| rec
.d_type
==QType::NSEC
|| rec
.d_type
==QType::NSEC3
) && rec
.d_place
==DNSResourceRecord::ANSWER
) {
1927 if(rec
.d_type
!= QType::RRSIG
|| rec
.d_name
== qname
)
1928 ret
.push_back(rec
); // enjoy your DNSSEC
1930 else if(needWildcardProof
&& (rec
.d_type
==QType::RRSIG
|| rec
.d_type
==QType::NSEC
|| rec
.d_type
==QType::NSEC3
) && rec
.d_place
==DNSResourceRecord::AUTHORITY
) {
1931 ret
.push_back(rec
); // enjoy your DNSSEC
1933 // for ANY answers we *must* have an authoritative answer, unless we are forwarding recursively
1934 else if(rec
.d_place
==DNSResourceRecord::ANSWER
&& rec
.d_name
== qname
&&
1936 rec
.d_type
==qtype
.getCode() || (lwr
.d_aabit
&& (qtype
==QType(QType::ANY
) || magicAddrMatch(qtype
, QType(rec
.d_type
)) ) ) || sendRDQuery
1940 LOG(prefix
<<qname
<<": answer is in: resolved to '"<< rec
.d_content
->getZoneRepresentation()<<"|"<<DNSRecordContent::NumberToType(rec
.d_type
)<<"'"<<endl
);
1945 else if(rec
.d_place
==DNSResourceRecord::AUTHORITY
&& rec
.d_type
==QType::NS
&& qname
.isPartOf(rec
.d_name
)) {
1946 if(moreSpecificThan(rec
.d_name
,auth
)) {
1948 LOG(prefix
<<qname
<<": got NS record '"<<rec
.d_name
<<"' -> '"<<rec
.d_content
->getZoneRepresentation()<<"'"<<endl
);
1952 LOG(prefix
<<qname
<<": got upwards/level NS record '"<<rec
.d_name
<<"' -> '"<<rec
.d_content
->getZoneRepresentation()<<"', had '"<<auth
<<"'"<<endl
);
1954 if (auto content
= getRR
<NSRecordContent
>(rec
)) {
1955 nsset
.insert(content
->getNS());
1958 else if(rec
.d_place
==DNSResourceRecord::AUTHORITY
&& rec
.d_type
==QType::DS
&& qname
.isPartOf(rec
.d_name
)) {
1959 LOG(prefix
<<qname
<<": got DS record '"<<rec
.d_name
<<"' -> '"<<rec
.d_content
->getZoneRepresentation()<<"'"<<endl
);
1961 else if(realreferral
&& rec
.d_place
==DNSResourceRecord::AUTHORITY
&& (rec
.d_type
==QType::NSEC
|| rec
.d_type
==QType::NSEC3
) && newauth
.isPartOf(auth
)) {
1962 /* we might have received a denial of the DS, let's check */
1963 if (state
== Secure
) {
1964 NegCache::NegCacheEntry ne
;
1966 ne
.d_ttd
= d_now
.tv_sec
+ rec
.d_ttl
;
1967 ne
.d_name
= newauth
;
1968 ne
.d_qtype
= QType::DS
;
1969 harvestNXRecords(lwr
.d_records
, ne
);
1970 cspmap_t csp
= harvestCSPFromNE(ne
);
1971 dState denialState
= getDenial(csp
, newauth
, QType::DS
);
1972 if (denialState
== NXQTYPE
|| denialState
== OPTOUT
|| denialState
== INSECURE
) {
1973 ne
.d_validationState
= Secure
;
1974 rec
.d_ttl
= min(s_maxnegttl
, rec
.d_ttl
);
1975 LOG(prefix
<<qname
<<": got negative indication of DS record for '"<<newauth
<<"'"<<endl
);
1976 updateValidationState(state
, Insecure
);
1977 auto cut
= d_cutStates
.find(newauth
);
1978 if (cut
!= d_cutStates
.end()) {
1979 if (cut
->second
== Indeterminate
) {
1980 cut
->second
= state
;
1984 LOG(prefix
<<qname
<<": setting cut state for "<<newauth
<<" to "<<vStates
[state
]<<endl
);
1985 d_cutStates
[newauth
] = state
;
1987 if(!wasVariable()) {
1988 t_sstorage
.negcache
.add(ne
);
1993 else if(!done
&& rec
.d_place
==DNSResourceRecord::AUTHORITY
&& rec
.d_type
==QType::SOA
&&
1994 lwr
.d_rcode
==RCode::NoError
&& qname
.isPartOf(rec
.d_name
)) {
1995 LOG(prefix
<<qname
<<": got negative caching indication for '"<< qname
<<"|"<<qtype
.getName()<<"'"<<endl
);
1997 if(!newtarget
.empty()) {
1998 LOG(prefix
<<qname
<<": Hang on! Got a redirect to '"<<newtarget
<<"' already"<<endl
);
2001 rec
.d_ttl
= min(s_maxnegttl
, rec
.d_ttl
);
2003 if(!wasVariable()) {
2004 NegCache::NegCacheEntry ne
;
2005 ne
.d_auth
= rec
.d_name
;
2006 ne
.d_ttd
= d_now
.tv_sec
+ rec
.d_ttl
;
2009 harvestNXRecords(lwr
.d_records
, ne
);
2010 getDenialValidationState(ne
, state
, NXQTYPE
, qtype
== QType::DS
);
2011 if(qtype
.getCode()) { // prevents us from blacking out a whole domain
2012 t_sstorage
.negcache
.add(ne
);
2023 bool SyncRes::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
)
2029 if(d_outqueries
+ d_throttledqueries
> s_maxqperq
) {
2030 throw ImmediateServFailException("more than "+std::to_string(s_maxqperq
)+" (max-qperq) queries sent while resolving "+qname
.toLogString());
2033 if(s_maxtotusec
&& d_totUsec
> s_maxtotusec
) {
2034 throw ImmediateServFailException("Too much time waiting for "+qname
.toLogString()+"|"+qtype
.getName()+", timeouts: "+std::to_string(d_timeouts
) +", throttles: "+std::to_string(d_throttledqueries
) + ", queries: "+std::to_string(d_outqueries
)+", "+std::to_string(d_totUsec
/1000)+"msec");
2038 LOG(prefix
<<qname
<<": using TCP with "<< remoteIP
.toStringWithPort() <<endl
);
2043 if(d_pdl
&& d_pdl
->preoutquery(remoteIP
, d_requestor
, qname
, qtype
, doTCP
, lwr
.d_records
, resolveret
)) {
2044 LOG(prefix
<<qname
<<": query handled by Lua"<<endl
);
2047 ednsmask
=getEDNSSubnetMask(d_requestor
, qname
, remoteIP
);
2049 LOG(prefix
<<qname
<<": Adding EDNS Client Subnet Mask "<<ednsmask
->toString()<<" to query"<<endl
);
2052 resolveret
= asyncresolveWrapper(remoteIP
, d_doDNSSEC
, qname
, qtype
.getCode(),
2053 doTCP
, sendRDQuery
, &d_now
, ednsmask
, &lwr
); // <- we go out on the wire!
2056 LOG(prefix
<<qname
<<": Received EDNS Client Subnet Mask "<<ednsmask
->toString()<<" on response"<<endl
);
2060 /* preoutquery killed the query by setting dq.rcode to -3 */
2061 if(resolveret
==-3) {
2062 throw ImmediateServFailException("Query killed by policy");
2065 d_totUsec
+= lwr
.d_usec
;
2066 accountAuthLatency(lwr
.d_usec
, remoteIP
.sin4
.sin_family
);
2068 if(resolveret
!= 1) {
2069 /* Error while resolving */
2070 if(resolveret
== 0) {
2073 LOG(prefix
<<qname
<<": timeout resolving after "<<lwr
.d_usec
/1000.0<<"msec "<< (doTCP
? "over TCP" : "")<<endl
);
2075 s_outgoingtimeouts
++;
2077 if(remoteIP
.sin4
.sin_family
== AF_INET
)
2078 s_outgoing4timeouts
++;
2080 s_outgoing6timeouts
++;
2082 else if(resolveret
== -2) {
2083 /* OS resource limit reached */
2084 LOG(prefix
<<qname
<<": hit a local resource limit resolving"<< (doTCP
? " over TCP" : "")<<", probable error: "<<stringerror()<<endl
);
2085 g_stats
.resourceLimits
++;
2088 /* -1 means server unreachable */
2091 LOG(prefix
<<qname
<<": error resolving from "<<remoteIP
.toString()<< (doTCP
? " over TCP" : "") <<", possible error: "<<strerror(errno
)<< endl
);
2094 if(resolveret
!= -2) { // don't account for resource limits, they are our own fault
2095 t_sstorage
.nsSpeeds
[nsName
].submit(remoteIP
, 1000000, &d_now
); // 1 sec
2097 // code below makes sure we don't filter COM or the root
2098 if (s_serverdownmaxfails
> 0 && (auth
!= g_rootdnsname
) && t_sstorage
.fails
.incr(remoteIP
) >= s_serverdownmaxfails
) {
2099 LOG(prefix
<<qname
<<": Max fails reached resolving on "<< remoteIP
.toString() <<". Going full throttle for "<< s_serverdownthrottletime
<<" seconds" <<endl
);
2100 // mark server as down
2101 t_sstorage
.throttle
.throttle(d_now
.tv_sec
, boost::make_tuple(remoteIP
, "", 0), s_serverdownthrottletime
, 10000);
2103 else if (resolveret
== -1) {
2104 // unreachable, 1 minute or 100 queries
2105 t_sstorage
.throttle
.throttle(d_now
.tv_sec
, boost::make_tuple(remoteIP
, qname
, qtype
.getCode()), 60, 100);
2109 t_sstorage
.throttle
.throttle(d_now
.tv_sec
, boost::make_tuple(remoteIP
, qname
, qtype
.getCode()), 10, 5);
2116 /* we got an answer */
2117 if(lwr
.d_rcode
==RCode::ServFail
|| lwr
.d_rcode
==RCode::Refused
) {
2118 LOG(prefix
<<qname
<<": "<<nsName
<<" ("<<remoteIP
.toString()<<") returned a "<< (lwr
.d_rcode
==RCode::ServFail
? "ServFail" : "Refused") << ", trying sibling IP or NS"<<endl
);
2119 t_sstorage
.throttle
.throttle(d_now
.tv_sec
, boost::make_tuple(remoteIP
, qname
, qtype
.getCode()), 60, 3);
2123 /* this server sent a valid answer, mark it backup up if it was down */
2124 if(s_serverdownmaxfails
> 0) {
2125 t_sstorage
.fails
.clear(remoteIP
);
2132 LOG(prefix
<<qname
<<": truncated bit set, over TCP?"<<endl
);
2133 /* let's treat that as a ServFail answer from this server */
2134 t_sstorage
.throttle
.throttle(d_now
.tv_sec
, boost::make_tuple(remoteIP
, qname
, qtype
.getCode()), 60, 3);
2144 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
)
2149 prefix
.append(depth
, ' ');
2153 for(auto& rec
: lwr
.d_records
) {
2154 rec
.d_ttl
= max(rec
.d_ttl
, s_minimumTTL
);
2158 bool needWildcardProof
= false;
2159 *rcode
= updateCacheFromRecords(depth
, lwr
, qname
, qtype
, auth
, wasForwarded
, ednsmask
, state
, needWildcardProof
);
2160 if (*rcode
!= RCode::NoError
) {
2164 LOG(prefix
<<qname
<<": determining status after receiving this packet"<<endl
);
2167 bool realreferral
=false, negindic
=false;
2171 bool done
= processRecords(prefix
, qname
, qtype
, auth
, lwr
, sendRDQuery
, ret
, nsset
, newtarget
, newauth
, realreferral
, negindic
, state
, needWildcardProof
);
2174 LOG(prefix
<<qname
<<": status=got results, this level of recursion done"<<endl
);
2175 *rcode
= RCode::NoError
;
2179 if(!newtarget
.empty()) {
2180 if(newtarget
== qname
) {
2181 LOG(prefix
<<qname
<<": status=got a CNAME referral to self, returning SERVFAIL"<<endl
);
2182 *rcode
= RCode::ServFail
;
2187 LOG(prefix
<<qname
<<": status=got a CNAME referral, but recursing too deep, returning SERVFAIL"<<endl
);
2188 *rcode
= RCode::ServFail
;
2192 LOG(prefix
<<qname
<<": status=got a CNAME referral, starting over with "<<newtarget
<<endl
);
2194 set
<GetBestNSAnswer
> beenthere2
;
2195 vState cnameState
= Indeterminate
;
2196 *rcode
= doResolve(newtarget
, qtype
, ret
, depth
+ 1, beenthere2
, cnameState
);
2197 LOG(prefix
<<qname
<<": updating validation state for response to "<<qname
<<" from "<<vStates
[state
]<<" with the state from the CNAME quest: "<<vStates
[cnameState
]<<endl
);
2198 updateValidationState(state
, cnameState
);
2202 if(lwr
.d_rcode
== RCode::NXDomain
) {
2203 LOG(prefix
<<qname
<<": status=NXDOMAIN, we are done "<<(negindic
? "(have negative SOA)" : "")<<endl
);
2206 addNXNSECS(ret
, lwr
.d_records
);
2208 *rcode
= RCode::NXDomain
;
2212 if(nsset
.empty() && !lwr
.d_rcode
&& (negindic
|| lwr
.d_aabit
|| sendRDQuery
)) {
2213 LOG(prefix
<<qname
<<": status=noerror, other types may exist, but we are done "<<(negindic
? "(have negative SOA) " : "")<<(lwr
.d_aabit
? "(have aa bit) " : "")<<endl
);
2216 addNXNSECS(ret
, lwr
.d_records
);
2218 *rcode
= RCode::NoError
;
2223 LOG(prefix
<<qname
<<": status=did not resolve, got "<<(unsigned int)nsset
.size()<<" NS, ");
2225 nameservers
.clear();
2226 for (auto const &nameserver
: nsset
) {
2228 d_appliedPolicy
= dfe
.getProcessingPolicy(nameserver
, d_discardedPolicies
);
2229 if (d_appliedPolicy
.d_kind
!= DNSFilterEngine::PolicyKind::NoAction
) { // client query needs an RPZ response
2230 LOG("however "<<nameserver
<<" was blocked by RPZ policy '"<<(d_appliedPolicy
.d_name
? *d_appliedPolicy
.d_name
: "")<<"'"<<endl
);
2235 nameservers
.insert({nameserver
, {{}, false}});
2237 LOG("looping to them"<<endl
);
2238 *gotNewServers
= true;
2248 * -1 in case of no results
2249 * -2 when a FilterEngine Policy was hit
2252 int SyncRes::doResolveAt(NsSet
&nameservers
, DNSName auth
, bool flawedNSSet
, const DNSName
&qname
, const QType
&qtype
,
2253 vector
<DNSRecord
>&ret
,
2254 unsigned int depth
, set
<GetBestNSAnswer
>&beenthere
, vState
& state
)
2256 auto luaconfsLocal
= g_luaconfs
.getLocal();
2260 prefix
.append(depth
, ' ');
2263 LOG(prefix
<<qname
<<": Cache consultations done, have "<<(unsigned int)nameservers
.size()<<" NS to contact");
2265 if (nameserversBlockedByRPZ(luaconfsLocal
->dfe
, nameservers
)) {
2271 for(;;) { // we may get more specific nameservers
2272 vector
<DNSName
> rnameservers
= shuffleInSpeedOrder(nameservers
, doLog() ? (prefix
+qname
.toString()+": ") : string() );
2274 for(auto tns
=rnameservers
.cbegin();;++tns
) {
2275 if(tns
==rnameservers
.cend()) {
2276 LOG(prefix
<<qname
<<": Failed to resolve via any of the "<<(unsigned int)rnameservers
.size()<<" offered NS at level '"<<auth
<<"'"<<endl
);
2277 if(!auth
.isRoot() && flawedNSSet
) {
2278 LOG(prefix
<<qname
<<": Ageing nameservers for level '"<<auth
<<"', next query might succeed"<<endl
);
2280 if(t_RC
->doAgeCache(d_now
.tv_sec
, auth
, QType::NS
, 10))
2281 g_stats
.nsSetInvalidations
++;
2286 // this line needs to identify the 'self-resolving' behaviour, but we get it wrong now
2287 if(qname
== *tns
&& qtype
.getCode()==QType::A
&& rnameservers
.size() > (size_t)(1+1*s_doIPv6
)) {
2288 LOG(prefix
<<qname
<<": Not using NS to resolve itself! ("<<(1+tns
-rnameservers
.cbegin())<<"/"<<rnameservers
.size()<<")"<<endl
);
2292 typedef vector
<ComboAddress
> remoteIPs_t
;
2293 remoteIPs_t remoteIPs
;
2294 remoteIPs_t::const_iterator remoteIP
;
2295 bool pierceDontQuery
=false;
2296 bool sendRDQuery
=false;
2297 boost::optional
<Netmask
> ednsmask
;
2299 const bool wasForwarded
= tns
->empty() && (!nameservers
[*tns
].first
.empty());
2300 int rcode
= RCode::NoError
;
2301 bool gotNewServers
= false;
2303 if(tns
->empty() && !wasForwarded
) {
2304 LOG(prefix
<<qname
<<": Domain is out-of-band"<<endl
);
2306 d_wasOutOfBand
= doOOBResolve(qname
, qtype
, lwr
.d_records
, depth
, lwr
.d_rcode
);
2310 /* we have received an answer, are we done ? */
2311 bool done
= processAnswer(depth
, lwr
, qname
, qtype
, auth
, false, ednsmask
, sendRDQuery
, nameservers
, ret
, luaconfsLocal
->dfe
, &gotNewServers
, &rcode
, state
);
2315 if (gotNewServers
) {
2320 /* if tns is empty, retrieveAddressesForNS() knows we have hardcoded servers (i.e. "forwards") */
2321 remoteIPs
= retrieveAddressesForNS(prefix
, qname
, tns
, depth
, beenthere
, rnameservers
, nameservers
, sendRDQuery
, pierceDontQuery
, flawedNSSet
);
2323 if(remoteIPs
.empty()) {
2324 LOG(prefix
<<qname
<<": Failed to get IP for NS "<<*tns
<<", trying next if available"<<endl
);
2329 bool hitPolicy
{false};
2330 LOG(prefix
<<qname
<<": Resolved '"<<auth
<<"' NS "<<*tns
<<" to: ");
2331 for(remoteIP
= remoteIPs
.cbegin(); remoteIP
!= remoteIPs
.cend(); ++remoteIP
) {
2332 if(remoteIP
!= remoteIPs
.cbegin()) {
2335 LOG(remoteIP
->toString());
2336 if(nameserverIPBlockedByRPZ(luaconfsLocal
->dfe
, *remoteIP
)) {
2341 if (hitPolicy
) //implies d_wantsRPZ
2345 for(remoteIP
= remoteIPs
.cbegin(); remoteIP
!= remoteIPs
.cend(); ++remoteIP
) {
2346 LOG(prefix
<<qname
<<": Trying IP "<< remoteIP
->toStringWithPort() <<", asking '"<<qname
<<"|"<<qtype
.getName()<<"'"<<endl
);
2348 if (throttledOrBlocked(prefix
, *remoteIP
, qname
, qtype
, pierceDontQuery
)) {
2352 bool truncated
= false;
2353 bool gotAnswer
= doResolveAtThisIP(prefix
, qname
, qtype
, lwr
, ednsmask
, auth
, sendRDQuery
,
2354 *tns
, *remoteIP
, false, &truncated
);
2355 if (gotAnswer
&& truncated
) {
2356 /* retry, over TCP this time */
2357 gotAnswer
= doResolveAtThisIP(prefix
, qname
, qtype
, lwr
, ednsmask
, auth
, sendRDQuery
,
2358 *tns
, *remoteIP
, true, &truncated
);
2365 LOG(prefix
<<qname
<<": Got "<<(unsigned int)lwr
.d_records
.size()<<" answers from "<<*tns
<<" ("<< remoteIP
->toString() <<"), rcode="<<lwr
.d_rcode
<<" ("<<RCode::to_s(lwr
.d_rcode
)<<"), aa="<<lwr
.d_aabit
<<", in "<<lwr
.d_usec
/1000<<"ms"<<endl
);
2367 /* // for you IPv6 fanatics :-)
2368 if(remoteIP->sin4.sin_family==AF_INET6)
2371 // cout<<"msec: "<<lwr.d_usec/1000.0<<", "<<g_avgLatency/1000.0<<'\n';
2373 t_sstorage
.nsSpeeds
[*tns
].submit(*remoteIP
, lwr
.d_usec
, &d_now
);
2375 /* we have received an answer, are we done ? */
2376 bool done
= processAnswer(depth
, lwr
, qname
, qtype
, auth
, wasForwarded
, ednsmask
, sendRDQuery
, nameservers
, ret
, luaconfsLocal
->dfe
, &gotNewServers
, &rcode
, state
);
2380 if (gotNewServers
) {
2384 t_sstorage
.throttle
.throttle(d_now
.tv_sec
, boost::make_tuple(*remoteIP
, qname
, qtype
.getCode()), 60, 100);
2387 if (gotNewServers
) {
2391 if(remoteIP
== remoteIPs
.cend()) // we tried all IP addresses, none worked
2400 boost::optional
<Netmask
> SyncRes::getEDNSSubnetMask(const ComboAddress
& local
, const DNSName
&dn
, const ComboAddress
& rem
)
2402 boost::optional
<Netmask
> result
;
2405 if(d_incomingECSFound
) {
2406 if (d_incomingECS
->source
.getBits() == 0) {
2407 /* RFC7871 says we MUST NOT send any ECS if the source scope is 0 */
2410 trunc
= d_incomingECSNetwork
;
2411 bits
= d_incomingECS
->source
.getBits();
2413 else if(!local
.isIPv4() || local
.sin4
.sin_addr
.s_addr
) { // detect unset 'requestor'
2415 bits
= local
.isIPv4() ? 32 : 128;
2418 /* nothing usable */
2422 if(s_ednsdomains
.check(dn
) || s_ednssubnets
.match(rem
)) {
2423 bits
= std::min(bits
, (trunc
.isIPv4() ? s_ecsipv4limit
: s_ecsipv6limit
));
2424 trunc
.truncate(bits
);
2425 return boost::optional
<Netmask
>(Netmask(trunc
, bits
));
2431 void SyncRes::parseEDNSSubnetWhitelist(const std::string
& wlist
)
2433 vector
<string
> parts
;
2434 stringtok(parts
, wlist
, ",; ");
2435 for(const auto& a
: parts
) {
2437 s_ednssubnets
.addMask(Netmask(a
));
2440 s_ednsdomains
.add(DNSName(a
));
2445 // used by PowerDNSLua - note that this neglects to add the packet count & statistics back to pdns_ercursor.cc
2446 int directResolve(const DNSName
& qname
, const QType
& qtype
, int qclass
, vector
<DNSRecord
>& ret
)
2449 gettimeofday(&now
, 0);
2452 int res
= sr
.beginResolve(qname
, QType(qtype
), qclass
, ret
);
2457 int SyncRes::getRootNS(struct timeval now
, asyncresolve_t asyncCallback
) {
2459 sr
.setDoEDNS0(true);
2460 sr
.setUpdatingRootNS();
2461 sr
.setDoDNSSEC(g_dnssecmode
!= DNSSECMode::Off
);
2462 sr
.setAsyncCallback(asyncCallback
);
2464 vector
<DNSRecord
> ret
;
2467 res
=sr
.beginResolve(g_rootdnsname
, QType(QType::NS
), 1, ret
);
2468 if (g_dnssecmode
!= DNSSECMode::Off
&& g_dnssecmode
!= DNSSECMode::ProcessNoValidate
) {
2469 auto state
= sr
.getValidationState();
2471 throw PDNSException("Got Bogus validation result for .|NS");
2475 catch(const PDNSException
& e
) {
2476 L
<<Logger::Error
<<"Failed to update . records, got an exception: "<<e
.reason
<<endl
;
2478 catch(const ImmediateServFailException
& e
) {
2479 L
<<Logger::Error
<<"Failed to update . records, got an exception: "<<e
.reason
<<endl
;
2481 catch(const std::exception
& e
) {
2482 L
<<Logger::Error
<<"Failed to update . records, got an exception: "<<e
.what()<<endl
;
2485 L
<<Logger::Error
<<"Failed to update . records, got an exception"<<endl
;
2489 L
<<Logger::Notice
<<"Refreshed . records"<<endl
;
2492 L
<<Logger::Error
<<"Failed to update . records, RCODE="<<res
<<endl
;