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 for(const auto& rec
: lwr
.d_records
) {
1678 if(needWildcardProof
) {
1679 if (nsecTypes
.count(rec
.d_type
)) {
1680 authorityRecs
.push_back(std::make_shared
<DNSRecord
>(rec
));
1682 else if (rec
.d_type
== QType::RRSIG
) {
1683 auto rrsig
= getRR
<RRSIGRecordContent
>(rec
);
1684 if (rrsig
&& nsecTypes
.count(rrsig
->d_type
)) {
1685 authorityRecs
.push_back(std::make_shared
<DNSRecord
>(rec
));
1689 if(rec
.d_type
== QType::RRSIG
) {
1690 auto rrsig
= getRR
<RRSIGRecordContent
>(rec
);
1692 unsigned int labelCount
= rec
.d_name
.countLabels();
1693 /* As illustrated in rfc4035's Appendix B.6, the RRSIG label
1694 count can be lower than the name's label count if it was
1695 synthesized from the wildcard. Note that the difference might
1697 if (rec
.d_name
== qname
&& rrsig
->d_labels
< labelCount
) {
1698 LOG(prefix
<<qname
<<": RRSIG indicates the name was expanded from a wildcard, we need a wildcard proof"<<endl
);
1699 needWildcardProof
= true;
1702 // cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.d_name<<"'"<<endl;
1703 tcache
[{rec
.d_name
, rrsig
->d_type
, rec
.d_place
}].signatures
.push_back(rrsig
);
1704 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
);
1709 // reap all answers from this packet that are acceptable
1710 for(auto& rec
: lwr
.d_records
) {
1711 if(rec
.d_type
== QType::OPT
) {
1712 LOG(prefix
<<qname
<<": OPT answer '"<<rec
.d_name
<<"' from '"<<auth
<<"' nameservers" <<endl
);
1715 LOG(prefix
<<qname
<<": accept answer '"<<rec
.d_name
<<"|"<<DNSRecordContent::NumberToType(rec
.d_type
)<<"|"<<rec
.d_content
->getZoneRepresentation()<<"' from '"<<auth
<<"' nameservers? "<<(int)rec
.d_place
<<" ");
1716 if(rec
.d_type
== QType::ANY
) {
1717 LOG("NO! - we don't accept 'ANY' data"<<endl
);
1721 if(rec
.d_name
.isPartOf(auth
)) {
1722 if(rec
.d_type
== QType::RRSIG
) {
1723 LOG("RRSIG - separate"<<endl
);
1725 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
)) {
1726 LOG("NO! Is from delegation-only zone"<<endl
);
1728 return RCode::NXDomain
;
1731 bool haveLogged
= false;
1732 if (!t_sstorage
.domainmap
->empty()) {
1733 // Check if we are authoritative for a zone in this answer
1734 DNSName
tmp_qname(rec
.d_name
);
1735 auto auth_domain_iter
=getBestAuthZone(&tmp_qname
);
1736 if(auth_domain_iter
!=t_sstorage
.domainmap
->end() &&
1737 auth
.countLabels() <= auth_domain_iter
->first
.countLabels()) {
1738 if (auth_domain_iter
->first
!= auth
) {
1739 LOG("NO! - we are authoritative for the zone "<<auth_domain_iter
->first
<<endl
);
1742 LOG("YES! - This answer was ");
1743 if (!wasForwarded
) {
1744 LOG("retrieved from the local auth store.");
1746 LOG("received from a server we forward to.");
1757 rec
.d_ttl
=min(s_maxcachettl
, rec
.d_ttl
);
1760 dr
.d_ttl
+= d_now
.tv_sec
;
1761 dr
.d_place
=DNSResourceRecord::ANSWER
;
1762 tcache
[{rec
.d_name
,rec
.d_type
,rec
.d_place
}].records
.push_back(dr
);
1770 for(tcache_t::iterator i
= tcache
.begin(); i
!= tcache
.end(); ++i
) {
1771 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)
1772 uint32_t lowestTTD
=computeLowestTTD(i
->second
.records
, i
->second
.signatures
, i
->second
.signaturesTTL
);
1774 for(auto& record
: i
->second
.records
)
1775 record
.d_ttl
= lowestTTD
; // boom
1778 // cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.name;
1779 // cout<<'|'<<DNSRecordContent::NumberToType(i->first.type)<<endl;
1782 for(tcache_t::iterator i
= tcache
.begin(); i
!= tcache
.end(); ++i
) {
1784 if(i
->second
.records
.empty()) // this happens when we did store signatures, but passed on the records themselves
1787 vState recordState
= getValidationStatus(auth
);
1788 LOG(d_prefix
<<": got initial zone status "<<vStates
[recordState
]<<" for record "<<i
->first
.name
<<endl
);
1790 if (validationEnabled() && recordState
== Secure
) {
1792 if (i
->first
.place
!= DNSResourceRecord::ADDITIONAL
) {
1793 /* the additional entries can be insecure,
1795 "Glue address RRsets associated with delegations MUST NOT be signed"
1797 if (i
->first
.type
== QType::DNSKEY
&& i
->first
.place
== DNSResourceRecord::ANSWER
) {
1798 LOG(d_prefix
<<"Validating DNSKEY for "<<i
->first
.name
<<endl
);
1799 recordState
= validateDNSKeys(i
->first
.name
, i
->second
.records
, i
->second
.signatures
, depth
);
1802 LOG(d_prefix
<<"Validating non-additional record for "<<i
->first
.name
<<endl
);
1803 recordState
= validateRecordsWithSigs(depth
, qname
, qtype
, i
->first
.name
, i
->second
.records
, i
->second
.signatures
);
1804 /* 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 */
1805 if (qtype
== QType::NS
&& i
->second
.signatures
.empty() && recordState
== Bogus
&& haveExactValidationStatus(i
->first
.name
) && getValidationStatus(i
->first
.name
) == Indeterminate
) {
1806 recordState
= Indeterminate
;
1812 /* for non authoritative answer, we only care about the DS record (or lack of) */
1813 if ((i
->first
.type
== QType::DS
|| i
->first
.type
== QType::NSEC
|| i
->first
.type
== QType::NSEC3
) && i
->first
.place
== DNSResourceRecord::AUTHORITY
) {
1814 LOG(d_prefix
<<"Validating DS record for "<<i
->first
.name
<<endl
);
1815 recordState
= validateRecordsWithSigs(depth
, qname
, qtype
, i
->first
.name
, i
->second
.records
, i
->second
.signatures
);
1819 updateValidationState(state
, recordState
);
1822 if (validationEnabled()) {
1823 LOG(d_prefix
<<"Skipping validation because the current state is "<<vStates
[recordState
]<<endl
);
1827 t_RC
->replace(d_now
.tv_sec
, i
->first
.name
, QType(i
->first
.type
), i
->second
.records
, i
->second
.signatures
, authorityRecs
, lwr
.d_aabit
, i
->first
.place
== DNSResourceRecord::ANSWER
? ednsmask
: boost::none
, recordState
);
1829 if(i
->first
.place
== DNSResourceRecord::ANSWER
&& ednsmask
)
1833 return RCode::NoError
;
1836 void SyncRes::getDenialValidationState(NegCache::NegCacheEntry
& ne
, vState
& state
, const dState expectedState
, bool allowOptOut
)
1838 ne
.d_validationState
= state
;
1840 if (state
== Secure
) {
1841 cspmap_t csp
= harvestCSPFromNE(ne
);
1842 dState res
= getDenial(csp
, ne
.d_name
, ne
.d_qtype
.getCode());
1843 if (res
!= expectedState
) {
1844 if (res
== OPTOUT
&& allowOptOut
) {
1845 LOG(d_prefix
<<"OPT-out denial found for "<<ne
.d_name
<<", retuning Insecure"<<endl
);
1846 ne
.d_validationState
= Secure
;
1847 updateValidationState(state
, Insecure
);
1850 else if (res
== INSECURE
) {
1851 LOG(d_prefix
<<"Insecure denial found for "<<ne
.d_name
<<", retuning Insecure"<<endl
);
1852 ne
.d_validationState
= Insecure
;
1854 if (res
== NXDOMAIN
&& expectedState
== NXQTYPE
) {
1855 /* might happen for empty non-terminal, have fun */
1859 LOG(d_prefix
<<"Invalid denial found for "<<ne
.d_name
<<", retuning Bogus"<<endl
);
1860 ne
.d_validationState
= Bogus
;
1862 updateValidationState(state
, ne
.d_validationState
);
1867 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
)
1871 for(auto& rec
: lwr
.d_records
) {
1872 if (rec
.d_type
!=QType::OPT
&& rec
.d_class
!=QClass::IN
)
1875 if(rec
.d_place
==DNSResourceRecord::AUTHORITY
&& rec
.d_type
==QType::SOA
&&
1876 lwr
.d_rcode
==RCode::NXDomain
&& qname
.isPartOf(rec
.d_name
) && rec
.d_name
.isPartOf(auth
)) {
1877 LOG(prefix
<<qname
<<": got negative caching indication for name '"<<qname
<<"' (accept="<<rec
.d_name
.isPartOf(auth
)<<"), newtarget='"<<newtarget
<<"'"<<endl
);
1879 rec
.d_ttl
= min(rec
.d_ttl
, s_maxnegttl
);
1880 if(newtarget
.empty()) // only add a SOA if we're not going anywhere after this
1882 if(!wasVariable()) {
1883 NegCache::NegCacheEntry ne
;
1885 ne
.d_ttd
= d_now
.tv_sec
+ rec
.d_ttl
;
1887 ne
.d_qtype
= QType(0); // this encodes 'whole record'
1888 ne
.d_auth
= rec
.d_name
;
1889 harvestNXRecords(lwr
.d_records
, ne
);
1890 getDenialValidationState(ne
, state
, NXDOMAIN
, false);
1891 t_sstorage
.negcache
.add(ne
);
1892 if(s_rootNXTrust
&& ne
.d_auth
.isRoot() && auth
.isRoot()) {
1893 ne
.d_name
= ne
.d_name
.getLastLabel();
1894 t_sstorage
.negcache
.add(ne
);
1900 else if(rec
.d_place
==DNSResourceRecord::ANSWER
&& rec
.d_type
==QType::CNAME
&& (!(qtype
==QType(QType::CNAME
))) && rec
.d_name
== qname
) {
1902 if (auto content
= getRR
<CNAMERecordContent
>(rec
)) {
1903 newtarget
=content
->getTarget();
1906 else if((rec
.d_type
==QType::RRSIG
|| rec
.d_type
==QType::NSEC
|| rec
.d_type
==QType::NSEC3
) && rec
.d_place
==DNSResourceRecord::ANSWER
) {
1907 if(rec
.d_type
!= QType::RRSIG
|| rec
.d_name
== qname
)
1908 ret
.push_back(rec
); // enjoy your DNSSEC
1910 else if(needWildcardProof
&& (rec
.d_type
==QType::RRSIG
|| rec
.d_type
==QType::NSEC
|| rec
.d_type
==QType::NSEC3
) && rec
.d_place
==DNSResourceRecord::AUTHORITY
) {
1911 ret
.push_back(rec
); // enjoy your DNSSEC
1913 // for ANY answers we *must* have an authoritative answer, unless we are forwarding recursively
1914 else if(rec
.d_place
==DNSResourceRecord::ANSWER
&& rec
.d_name
== qname
&&
1916 rec
.d_type
==qtype
.getCode() || (lwr
.d_aabit
&& (qtype
==QType(QType::ANY
) || magicAddrMatch(qtype
, QType(rec
.d_type
)) ) ) || sendRDQuery
1920 LOG(prefix
<<qname
<<": answer is in: resolved to '"<< rec
.d_content
->getZoneRepresentation()<<"|"<<DNSRecordContent::NumberToType(rec
.d_type
)<<"'"<<endl
);
1925 else if(rec
.d_place
==DNSResourceRecord::AUTHORITY
&& rec
.d_type
==QType::NS
&& qname
.isPartOf(rec
.d_name
)) {
1926 if(moreSpecificThan(rec
.d_name
,auth
)) {
1928 LOG(prefix
<<qname
<<": got NS record '"<<rec
.d_name
<<"' -> '"<<rec
.d_content
->getZoneRepresentation()<<"'"<<endl
);
1932 LOG(prefix
<<qname
<<": got upwards/level NS record '"<<rec
.d_name
<<"' -> '"<<rec
.d_content
->getZoneRepresentation()<<"', had '"<<auth
<<"'"<<endl
);
1934 if (auto content
= getRR
<NSRecordContent
>(rec
)) {
1935 nsset
.insert(content
->getNS());
1938 else if(rec
.d_place
==DNSResourceRecord::AUTHORITY
&& rec
.d_type
==QType::DS
&& qname
.isPartOf(rec
.d_name
)) {
1939 LOG(prefix
<<qname
<<": got DS record '"<<rec
.d_name
<<"' -> '"<<rec
.d_content
->getZoneRepresentation()<<"'"<<endl
);
1941 else if(realreferral
&& rec
.d_place
==DNSResourceRecord::AUTHORITY
&& (rec
.d_type
==QType::NSEC
|| rec
.d_type
==QType::NSEC3
) && newauth
.isPartOf(auth
)) {
1942 /* we might have received a denial of the DS, let's check */
1943 if (state
== Secure
) {
1944 NegCache::NegCacheEntry ne
;
1946 ne
.d_ttd
= d_now
.tv_sec
+ rec
.d_ttl
;
1947 ne
.d_name
= newauth
;
1948 ne
.d_qtype
= QType::DS
;
1949 harvestNXRecords(lwr
.d_records
, ne
);
1950 cspmap_t csp
= harvestCSPFromNE(ne
);
1951 dState denialState
= getDenial(csp
, newauth
, QType::DS
);
1952 if (denialState
== NXQTYPE
|| denialState
== OPTOUT
|| denialState
== INSECURE
) {
1953 ne
.d_validationState
= Secure
;
1954 rec
.d_ttl
= min(s_maxnegttl
, rec
.d_ttl
);
1955 LOG(prefix
<<qname
<<": got negative indication of DS record for '"<<newauth
<<"'"<<endl
);
1956 updateValidationState(state
, Insecure
);
1957 auto cut
= d_cutStates
.find(newauth
);
1958 if (cut
!= d_cutStates
.end()) {
1959 if (cut
->second
== Indeterminate
) {
1960 cut
->second
= state
;
1964 LOG(prefix
<<qname
<<": setting cut state for "<<newauth
<<" to "<<vStates
[state
]<<endl
);
1965 d_cutStates
[newauth
] = state
;
1967 if(!wasVariable()) {
1968 t_sstorage
.negcache
.add(ne
);
1973 else if(!done
&& rec
.d_place
==DNSResourceRecord::AUTHORITY
&& rec
.d_type
==QType::SOA
&&
1974 lwr
.d_rcode
==RCode::NoError
&& qname
.isPartOf(rec
.d_name
)) {
1975 LOG(prefix
<<qname
<<": got negative caching indication for '"<< qname
<<"|"<<qtype
.getName()<<"'"<<endl
);
1977 if(!newtarget
.empty()) {
1978 LOG(prefix
<<qname
<<": Hang on! Got a redirect to '"<<newtarget
<<"' already"<<endl
);
1981 rec
.d_ttl
= min(s_maxnegttl
, rec
.d_ttl
);
1983 if(!wasVariable()) {
1984 NegCache::NegCacheEntry ne
;
1985 ne
.d_auth
= rec
.d_name
;
1986 ne
.d_ttd
= d_now
.tv_sec
+ rec
.d_ttl
;
1989 harvestNXRecords(lwr
.d_records
, ne
);
1990 getDenialValidationState(ne
, state
, NXQTYPE
, qtype
== QType::DS
);
1991 if(qtype
.getCode()) { // prevents us from blacking out a whole domain
1992 t_sstorage
.negcache
.add(ne
);
2003 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
)
2009 if(d_outqueries
+ d_throttledqueries
> s_maxqperq
) {
2010 throw ImmediateServFailException("more than "+std::to_string(s_maxqperq
)+" (max-qperq) queries sent while resolving "+qname
.toLogString());
2013 if(s_maxtotusec
&& d_totUsec
> s_maxtotusec
) {
2014 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");
2018 LOG(prefix
<<qname
<<": using TCP with "<< remoteIP
.toStringWithPort() <<endl
);
2023 if(d_pdl
&& d_pdl
->preoutquery(remoteIP
, d_requestor
, qname
, qtype
, doTCP
, lwr
.d_records
, resolveret
)) {
2024 LOG(prefix
<<qname
<<": query handled by Lua"<<endl
);
2027 ednsmask
=getEDNSSubnetMask(d_requestor
, qname
, remoteIP
);
2029 LOG(prefix
<<qname
<<": Adding EDNS Client Subnet Mask "<<ednsmask
->toString()<<" to query"<<endl
);
2032 resolveret
= asyncresolveWrapper(remoteIP
, d_doDNSSEC
, qname
, qtype
.getCode(),
2033 doTCP
, sendRDQuery
, &d_now
, ednsmask
, &lwr
); // <- we go out on the wire!
2036 LOG(prefix
<<qname
<<": Received EDNS Client Subnet Mask "<<ednsmask
->toString()<<" on response"<<endl
);
2040 /* preoutquery killed the query by setting dq.rcode to -3 */
2041 if(resolveret
==-3) {
2042 throw ImmediateServFailException("Query killed by policy");
2045 d_totUsec
+= lwr
.d_usec
;
2046 accountAuthLatency(lwr
.d_usec
, remoteIP
.sin4
.sin_family
);
2048 if(resolveret
!= 1) {
2049 /* Error while resolving */
2050 if(resolveret
== 0) {
2053 LOG(prefix
<<qname
<<": timeout resolving after "<<lwr
.d_usec
/1000.0<<"msec "<< (doTCP
? "over TCP" : "")<<endl
);
2055 s_outgoingtimeouts
++;
2057 if(remoteIP
.sin4
.sin_family
== AF_INET
)
2058 s_outgoing4timeouts
++;
2060 s_outgoing6timeouts
++;
2062 else if(resolveret
== -2) {
2063 /* OS resource limit reached */
2064 LOG(prefix
<<qname
<<": hit a local resource limit resolving"<< (doTCP
? " over TCP" : "")<<", probable error: "<<stringerror()<<endl
);
2065 g_stats
.resourceLimits
++;
2068 /* -1 means server unreachable */
2071 LOG(prefix
<<qname
<<": error resolving from "<<remoteIP
.toString()<< (doTCP
? " over TCP" : "") <<", possible error: "<<strerror(errno
)<< endl
);
2074 if(resolveret
!= -2) { // don't account for resource limits, they are our own fault
2075 t_sstorage
.nsSpeeds
[nsName
].submit(remoteIP
, 1000000, &d_now
); // 1 sec
2077 // code below makes sure we don't filter COM or the root
2078 if (s_serverdownmaxfails
> 0 && (auth
!= g_rootdnsname
) && t_sstorage
.fails
.incr(remoteIP
) >= s_serverdownmaxfails
) {
2079 LOG(prefix
<<qname
<<": Max fails reached resolving on "<< remoteIP
.toString() <<". Going full throttle for "<< s_serverdownthrottletime
<<" seconds" <<endl
);
2080 // mark server as down
2081 t_sstorage
.throttle
.throttle(d_now
.tv_sec
, boost::make_tuple(remoteIP
, "", 0), s_serverdownthrottletime
, 10000);
2083 else if (resolveret
== -1) {
2084 // unreachable, 1 minute or 100 queries
2085 t_sstorage
.throttle
.throttle(d_now
.tv_sec
, boost::make_tuple(remoteIP
, qname
, qtype
.getCode()), 60, 100);
2089 t_sstorage
.throttle
.throttle(d_now
.tv_sec
, boost::make_tuple(remoteIP
, qname
, qtype
.getCode()), 10, 5);
2096 /* we got an answer */
2097 if(lwr
.d_rcode
==RCode::ServFail
|| lwr
.d_rcode
==RCode::Refused
) {
2098 LOG(prefix
<<qname
<<": "<<nsName
<<" ("<<remoteIP
.toString()<<") returned a "<< (lwr
.d_rcode
==RCode::ServFail
? "ServFail" : "Refused") << ", trying sibling IP or NS"<<endl
);
2099 t_sstorage
.throttle
.throttle(d_now
.tv_sec
, boost::make_tuple(remoteIP
, qname
, qtype
.getCode()), 60, 3);
2103 /* this server sent a valid answer, mark it backup up if it was down */
2104 if(s_serverdownmaxfails
> 0) {
2105 t_sstorage
.fails
.clear(remoteIP
);
2112 LOG(prefix
<<qname
<<": truncated bit set, over TCP?"<<endl
);
2113 /* let's treat that as a ServFail answer from this server */
2114 t_sstorage
.throttle
.throttle(d_now
.tv_sec
, boost::make_tuple(remoteIP
, qname
, qtype
.getCode()), 60, 3);
2124 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
)
2129 prefix
.append(depth
, ' ');
2133 for(auto& rec
: lwr
.d_records
) {
2134 rec
.d_ttl
= max(rec
.d_ttl
, s_minimumTTL
);
2138 bool needWildcardProof
= false;
2139 *rcode
= updateCacheFromRecords(depth
, lwr
, qname
, qtype
, auth
, wasForwarded
, ednsmask
, state
, needWildcardProof
);
2140 if (*rcode
!= RCode::NoError
) {
2144 LOG(prefix
<<qname
<<": determining status after receiving this packet"<<endl
);
2147 bool realreferral
=false, negindic
=false;
2151 bool done
= processRecords(prefix
, qname
, qtype
, auth
, lwr
, sendRDQuery
, ret
, nsset
, newtarget
, newauth
, realreferral
, negindic
, state
, needWildcardProof
);
2154 LOG(prefix
<<qname
<<": status=got results, this level of recursion done"<<endl
);
2155 *rcode
= RCode::NoError
;
2159 if(!newtarget
.empty()) {
2160 if(newtarget
== qname
) {
2161 LOG(prefix
<<qname
<<": status=got a CNAME referral to self, returning SERVFAIL"<<endl
);
2162 *rcode
= RCode::ServFail
;
2167 LOG(prefix
<<qname
<<": status=got a CNAME referral, but recursing too deep, returning SERVFAIL"<<endl
);
2168 *rcode
= RCode::ServFail
;
2172 LOG(prefix
<<qname
<<": status=got a CNAME referral, starting over with "<<newtarget
<<endl
);
2174 set
<GetBestNSAnswer
> beenthere2
;
2175 vState cnameState
= Indeterminate
;
2176 *rcode
= doResolve(newtarget
, qtype
, ret
, depth
+ 1, beenthere2
, cnameState
);
2177 LOG(prefix
<<qname
<<": updating validation state for response to "<<qname
<<" from "<<vStates
[state
]<<" with the state from the CNAME quest: "<<vStates
[cnameState
]<<endl
);
2178 updateValidationState(state
, cnameState
);
2182 if(lwr
.d_rcode
== RCode::NXDomain
) {
2183 LOG(prefix
<<qname
<<": status=NXDOMAIN, we are done "<<(negindic
? "(have negative SOA)" : "")<<endl
);
2186 addNXNSECS(ret
, lwr
.d_records
);
2188 *rcode
= RCode::NXDomain
;
2192 if(nsset
.empty() && !lwr
.d_rcode
&& (negindic
|| lwr
.d_aabit
|| sendRDQuery
)) {
2193 LOG(prefix
<<qname
<<": status=noerror, other types may exist, but we are done "<<(negindic
? "(have negative SOA) " : "")<<(lwr
.d_aabit
? "(have aa bit) " : "")<<endl
);
2196 addNXNSECS(ret
, lwr
.d_records
);
2198 *rcode
= RCode::NoError
;
2203 LOG(prefix
<<qname
<<": status=did not resolve, got "<<(unsigned int)nsset
.size()<<" NS, ");
2205 nameservers
.clear();
2206 for (auto const &nameserver
: nsset
) {
2208 d_appliedPolicy
= dfe
.getProcessingPolicy(nameserver
, d_discardedPolicies
);
2209 if (d_appliedPolicy
.d_kind
!= DNSFilterEngine::PolicyKind::NoAction
) { // client query needs an RPZ response
2210 LOG("however "<<nameserver
<<" was blocked by RPZ policy '"<<(d_appliedPolicy
.d_name
? *d_appliedPolicy
.d_name
: "")<<"'"<<endl
);
2215 nameservers
.insert({nameserver
, {{}, false}});
2217 LOG("looping to them"<<endl
);
2218 *gotNewServers
= true;
2228 * -1 in case of no results
2229 * -2 when a FilterEngine Policy was hit
2232 int SyncRes::doResolveAt(NsSet
&nameservers
, DNSName auth
, bool flawedNSSet
, const DNSName
&qname
, const QType
&qtype
,
2233 vector
<DNSRecord
>&ret
,
2234 unsigned int depth
, set
<GetBestNSAnswer
>&beenthere
, vState
& state
)
2236 auto luaconfsLocal
= g_luaconfs
.getLocal();
2240 prefix
.append(depth
, ' ');
2243 LOG(prefix
<<qname
<<": Cache consultations done, have "<<(unsigned int)nameservers
.size()<<" NS to contact");
2245 if (nameserversBlockedByRPZ(luaconfsLocal
->dfe
, nameservers
)) {
2251 for(;;) { // we may get more specific nameservers
2252 vector
<DNSName
> rnameservers
= shuffleInSpeedOrder(nameservers
, doLog() ? (prefix
+qname
.toString()+": ") : string() );
2254 for(auto tns
=rnameservers
.cbegin();;++tns
) {
2255 if(tns
==rnameservers
.cend()) {
2256 LOG(prefix
<<qname
<<": Failed to resolve via any of the "<<(unsigned int)rnameservers
.size()<<" offered NS at level '"<<auth
<<"'"<<endl
);
2257 if(!auth
.isRoot() && flawedNSSet
) {
2258 LOG(prefix
<<qname
<<": Ageing nameservers for level '"<<auth
<<"', next query might succeed"<<endl
);
2260 if(t_RC
->doAgeCache(d_now
.tv_sec
, auth
, QType::NS
, 10))
2261 g_stats
.nsSetInvalidations
++;
2266 // this line needs to identify the 'self-resolving' behaviour, but we get it wrong now
2267 if(qname
== *tns
&& qtype
.getCode()==QType::A
&& rnameservers
.size() > (size_t)(1+1*s_doIPv6
)) {
2268 LOG(prefix
<<qname
<<": Not using NS to resolve itself! ("<<(1+tns
-rnameservers
.cbegin())<<"/"<<rnameservers
.size()<<")"<<endl
);
2272 typedef vector
<ComboAddress
> remoteIPs_t
;
2273 remoteIPs_t remoteIPs
;
2274 remoteIPs_t::const_iterator remoteIP
;
2275 bool pierceDontQuery
=false;
2276 bool sendRDQuery
=false;
2277 boost::optional
<Netmask
> ednsmask
;
2279 const bool wasForwarded
= tns
->empty() && (!nameservers
[*tns
].first
.empty());
2280 int rcode
= RCode::NoError
;
2281 bool gotNewServers
= false;
2283 if(tns
->empty() && !wasForwarded
) {
2284 LOG(prefix
<<qname
<<": Domain is out-of-band"<<endl
);
2286 d_wasOutOfBand
= doOOBResolve(qname
, qtype
, lwr
.d_records
, depth
, lwr
.d_rcode
);
2290 /* we have received an answer, are we done ? */
2291 bool done
= processAnswer(depth
, lwr
, qname
, qtype
, auth
, false, ednsmask
, sendRDQuery
, nameservers
, ret
, luaconfsLocal
->dfe
, &gotNewServers
, &rcode
, state
);
2295 if (gotNewServers
) {
2300 /* if tns is empty, retrieveAddressesForNS() knows we have hardcoded servers (i.e. "forwards") */
2301 remoteIPs
= retrieveAddressesForNS(prefix
, qname
, tns
, depth
, beenthere
, rnameservers
, nameservers
, sendRDQuery
, pierceDontQuery
, flawedNSSet
);
2303 if(remoteIPs
.empty()) {
2304 LOG(prefix
<<qname
<<": Failed to get IP for NS "<<*tns
<<", trying next if available"<<endl
);
2309 bool hitPolicy
{false};
2310 LOG(prefix
<<qname
<<": Resolved '"<<auth
<<"' NS "<<*tns
<<" to: ");
2311 for(remoteIP
= remoteIPs
.cbegin(); remoteIP
!= remoteIPs
.cend(); ++remoteIP
) {
2312 if(remoteIP
!= remoteIPs
.cbegin()) {
2315 LOG(remoteIP
->toString());
2316 if(nameserverIPBlockedByRPZ(luaconfsLocal
->dfe
, *remoteIP
)) {
2321 if (hitPolicy
) //implies d_wantsRPZ
2325 for(remoteIP
= remoteIPs
.cbegin(); remoteIP
!= remoteIPs
.cend(); ++remoteIP
) {
2326 LOG(prefix
<<qname
<<": Trying IP "<< remoteIP
->toStringWithPort() <<", asking '"<<qname
<<"|"<<qtype
.getName()<<"'"<<endl
);
2328 if (throttledOrBlocked(prefix
, *remoteIP
, qname
, qtype
, pierceDontQuery
)) {
2332 bool truncated
= false;
2333 bool gotAnswer
= doResolveAtThisIP(prefix
, qname
, qtype
, lwr
, ednsmask
, auth
, sendRDQuery
,
2334 *tns
, *remoteIP
, false, &truncated
);
2335 if (gotAnswer
&& truncated
) {
2336 /* retry, over TCP this time */
2337 gotAnswer
= doResolveAtThisIP(prefix
, qname
, qtype
, lwr
, ednsmask
, auth
, sendRDQuery
,
2338 *tns
, *remoteIP
, true, &truncated
);
2345 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
);
2347 /* // for you IPv6 fanatics :-)
2348 if(remoteIP->sin4.sin_family==AF_INET6)
2351 // cout<<"msec: "<<lwr.d_usec/1000.0<<", "<<g_avgLatency/1000.0<<'\n';
2353 t_sstorage
.nsSpeeds
[*tns
].submit(*remoteIP
, lwr
.d_usec
, &d_now
);
2355 /* we have received an answer, are we done ? */
2356 bool done
= processAnswer(depth
, lwr
, qname
, qtype
, auth
, wasForwarded
, ednsmask
, sendRDQuery
, nameservers
, ret
, luaconfsLocal
->dfe
, &gotNewServers
, &rcode
, state
);
2360 if (gotNewServers
) {
2364 t_sstorage
.throttle
.throttle(d_now
.tv_sec
, boost::make_tuple(*remoteIP
, qname
, qtype
.getCode()), 60, 100);
2367 if (gotNewServers
) {
2371 if(remoteIP
== remoteIPs
.cend()) // we tried all IP addresses, none worked
2380 boost::optional
<Netmask
> SyncRes::getEDNSSubnetMask(const ComboAddress
& local
, const DNSName
&dn
, const ComboAddress
& rem
)
2382 boost::optional
<Netmask
> result
;
2385 if(d_incomingECSFound
) {
2386 if (d_incomingECS
->source
.getBits() == 0) {
2387 /* RFC7871 says we MUST NOT send any ECS if the source scope is 0 */
2390 trunc
= d_incomingECSNetwork
;
2391 bits
= d_incomingECS
->source
.getBits();
2393 else if(!local
.isIPv4() || local
.sin4
.sin_addr
.s_addr
) { // detect unset 'requestor'
2395 bits
= local
.isIPv4() ? 32 : 128;
2398 /* nothing usable */
2402 if(s_ednsdomains
.check(dn
) || s_ednssubnets
.match(rem
)) {
2403 bits
= std::min(bits
, (trunc
.isIPv4() ? s_ecsipv4limit
: s_ecsipv6limit
));
2404 trunc
.truncate(bits
);
2405 return boost::optional
<Netmask
>(Netmask(trunc
, bits
));
2411 void SyncRes::parseEDNSSubnetWhitelist(const std::string
& wlist
)
2413 vector
<string
> parts
;
2414 stringtok(parts
, wlist
, ",; ");
2415 for(const auto& a
: parts
) {
2417 s_ednssubnets
.addMask(Netmask(a
));
2420 s_ednsdomains
.add(DNSName(a
));
2425 // used by PowerDNSLua - note that this neglects to add the packet count & statistics back to pdns_ercursor.cc
2426 int directResolve(const DNSName
& qname
, const QType
& qtype
, int qclass
, vector
<DNSRecord
>& ret
)
2429 gettimeofday(&now
, 0);
2432 int res
= sr
.beginResolve(qname
, QType(qtype
), qclass
, ret
);
2437 int SyncRes::getRootNS(struct timeval now
, asyncresolve_t asyncCallback
) {
2439 sr
.setDoEDNS0(true);
2440 sr
.setUpdatingRootNS();
2441 sr
.setDoDNSSEC(g_dnssecmode
!= DNSSECMode::Off
);
2442 sr
.setAsyncCallback(asyncCallback
);
2444 vector
<DNSRecord
> ret
;
2447 res
=sr
.beginResolve(g_rootdnsname
, QType(QType::NS
), 1, ret
);
2448 if (g_dnssecmode
!= DNSSECMode::Off
&& g_dnssecmode
!= DNSSECMode::ProcessNoValidate
) {
2449 auto state
= sr
.getValidationState();
2451 throw PDNSException("Got Bogus validation result for .|NS");
2455 catch(const PDNSException
& e
) {
2456 L
<<Logger::Error
<<"Failed to update . records, got an exception: "<<e
.reason
<<endl
;
2458 catch(const ImmediateServFailException
& e
) {
2459 L
<<Logger::Error
<<"Failed to update . records, got an exception: "<<e
.reason
<<endl
;
2461 catch(const std::exception
& e
) {
2462 L
<<Logger::Error
<<"Failed to update . records, got an exception: "<<e
.what()<<endl
;
2465 L
<<Logger::Error
<<"Failed to update . records, got an exception"<<endl
;
2469 L
<<Logger::Notice
<<"Refreshed . records"<<endl
;
2472 L
<<Logger::Error
<<"Failed to update . records, RCODE="<<res
<<endl
;