]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/syncres.cc
Merge pull request #5437 from mind04/oops
[thirdparty/pdns.git] / pdns / syncres.cc
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
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.
8 *
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.
12 *
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.
17 *
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.
21 */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
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"
32 #include "logger.hh"
33 #include "lua-recursor4.hh"
34 #include "rec-lua-conf.hh"
35 #include "syncres.hh"
36
37 thread_local SyncRes::ThreadLocalStorage SyncRes::t_sstorage;
38
39 std::unordered_set<DNSName> SyncRes::s_delegationOnly;
40 std::unique_ptr<NetmaskGroup> SyncRes::s_dontQuery{nullptr};
41 NetmaskGroup SyncRes::s_ednssubnets;
42 SuffixMatchNode SyncRes::s_ednsdomains;
43 string SyncRes::s_serverID;
44 SyncRes::LogMode SyncRes::s_lm;
45
46 unsigned int SyncRes::s_maxnegttl;
47 unsigned int SyncRes::s_maxcachettl;
48 unsigned int SyncRes::s_maxqperq;
49 unsigned int SyncRes::s_maxtotusec;
50 unsigned int SyncRes::s_maxdepth;
51 unsigned int SyncRes::s_minimumTTL;
52 unsigned int SyncRes::s_packetcachettl;
53 unsigned int SyncRes::s_packetcacheservfailttl;
54 unsigned int SyncRes::s_serverdownmaxfails;
55 unsigned int SyncRes::s_serverdownthrottletime;
56 std::atomic<uint64_t> SyncRes::s_queries;
57 std::atomic<uint64_t> SyncRes::s_outgoingtimeouts;
58 std::atomic<uint64_t> SyncRes::s_outgoing4timeouts;
59 std::atomic<uint64_t> SyncRes::s_outgoing6timeouts;
60 std::atomic<uint64_t> SyncRes::s_outqueries;
61 std::atomic<uint64_t> SyncRes::s_tcpoutqueries;
62 std::atomic<uint64_t> SyncRes::s_throttledqueries;
63 std::atomic<uint64_t> SyncRes::s_dontqueries;
64 std::atomic<uint64_t> SyncRes::s_nodelegated;
65 std::atomic<uint64_t> SyncRes::s_unreachables;
66 uint8_t SyncRes::s_ecsipv4limit;
67 uint8_t SyncRes::s_ecsipv6limit;
68 bool SyncRes::s_doIPv6;
69 bool SyncRes::s_nopacketcache;
70 bool SyncRes::s_rootNXTrust;
71 bool SyncRes::s_noEDNS;
72
73 #define LOG(x) if(d_lm == Log) { L <<Logger::Warning << x; } else if(d_lm == Store) { d_trace << x; }
74
75 static void accountAuthLatency(int usec, int family)
76 {
77 if(family == AF_INET) {
78 if(usec < 1000)
79 g_stats.auth4Answers0_1++;
80 else if(usec < 10000)
81 g_stats.auth4Answers1_10++;
82 else if(usec < 100000)
83 g_stats.auth4Answers10_100++;
84 else if(usec < 1000000)
85 g_stats.auth4Answers100_1000++;
86 else
87 g_stats.auth4AnswersSlow++;
88 } else {
89 if(usec < 1000)
90 g_stats.auth6Answers0_1++;
91 else if(usec < 10000)
92 g_stats.auth6Answers1_10++;
93 else if(usec < 100000)
94 g_stats.auth6Answers10_100++;
95 else if(usec < 1000000)
96 g_stats.auth6Answers100_1000++;
97 else
98 g_stats.auth6AnswersSlow++;
99 }
100
101 }
102
103
104 SyncRes::SyncRes(const struct timeval& now) : d_outqueries(0), d_tcpoutqueries(0), d_throttledqueries(0), d_timeouts(0), d_unreachables(0),
105 d_totUsec(0), d_now(now),
106 d_cacheonly(false), d_doDNSSEC(false), d_doEDNS0(false), d_lm(s_lm)
107
108 {
109 }
110
111 /** everything begins here - this is the entry point just after receiving a packet */
112 int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSRecord>&ret)
113 {
114 s_queries++;
115 d_wasVariable=false;
116 d_wasOutOfBand=false;
117
118 if (doSpecialNamesResolve(qname, qtype, qclass, ret))
119 return 0;
120
121 if( (qtype.getCode() == QType::AXFR) || (qtype.getCode() == QType::IXFR))
122 return -1;
123
124 if(qclass==QClass::ANY)
125 qclass=QClass::IN;
126 else if(qclass!=QClass::IN)
127 return -1;
128
129 set<GetBestNSAnswer> beenthere;
130 int res=doResolve(qname, qtype, ret, 0, beenthere);
131 return res;
132 }
133
134 /*! Handles all special, built-in names
135 * Fills ret with an answer and returns true if it handled the query.
136 *
137 * Handles the following queries (and their ANY variants):
138 *
139 * - localhost. IN A
140 * - localhost. IN AAAA
141 * - 1.0.0.127.in-addr.arpa. IN PTR
142 * - 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
143 * - version.bind. CH TXT
144 * - version.pdns. CH TXT
145 * - id.server. CH TXT
146 */
147 bool SyncRes::doSpecialNamesResolve(const DNSName &qname, const QType &qtype, const uint16_t qclass, vector<DNSRecord> &ret)
148 {
149 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."),
150 localhost("localhost."), versionbind("version.bind."), idserver("id.server."), versionpdns("version.pdns.");
151
152 bool handled = false;
153 vector<pair<QType::typeenum, string> > answers;
154
155 if ((qname == arpa || qname == ip6_arpa) &&
156 qclass == QClass::IN) {
157 handled = true;
158 if (qtype == QType::PTR || qtype == QType::ANY)
159 answers.push_back({QType::PTR, "localhost."});
160 }
161
162 if (qname == localhost &&
163 qclass == QClass::IN) {
164 handled = true;
165 if (qtype == QType::A || qtype == QType::ANY)
166 answers.push_back({QType::A, "127.0.0.1"});
167 if (qtype == QType::AAAA || qtype == QType::ANY)
168 answers.push_back({QType::AAAA, "::1"});
169 }
170
171 if ((qname == versionbind || qname == idserver || qname == versionpdns) &&
172 qclass == QClass::CHAOS) {
173 handled = true;
174 if (qtype == QType::TXT || qtype == QType::ANY) {
175 if(qname == versionbind || qname == versionpdns)
176 answers.push_back({QType::TXT, "\""+::arg()["version-string"]+"\""});
177 else
178 answers.push_back({QType::TXT, "\""+s_serverID+"\""});
179 }
180 }
181
182 if (handled && !answers.empty()) {
183 ret.clear();
184 d_wasOutOfBand=true;
185
186 DNSRecord dr;
187 dr.d_name = qname;
188 dr.d_place = DNSResourceRecord::ANSWER;
189 dr.d_class = qclass;
190 dr.d_ttl = 86400;
191 for (const auto& ans : answers) {
192 dr.d_type = ans.first;
193 dr.d_content = DNSRecordContent::mastermake(ans.first, qclass, ans.second);
194 ret.push_back(dr);
195 }
196 }
197
198 return handled;
199 }
200
201
202 //! This is the 'out of band resolver', in other words, the authoritative server
203 void SyncRes::AuthDomain::addSOA(std::vector<DNSRecord>& records) const
204 {
205 SyncRes::AuthDomain::records_t::const_iterator ziter = d_records.find(boost::make_tuple(getName(), QType::SOA));
206 if (ziter != d_records.end()) {
207 DNSRecord dr = *ziter;
208 dr.d_place = DNSResourceRecord::AUTHORITY;
209 records.push_back(dr);
210 }
211 else {
212 // cerr<<qname<<": can't find SOA record '"<<getName()<<"' in our zone!"<<endl;
213 }
214 }
215
216 int SyncRes::AuthDomain::getRecords(const DNSName& qname, uint16_t qtype, std::vector<DNSRecord>& records) const
217 {
218 int result = RCode::NoError;
219 records.clear();
220
221 // partial lookup
222 std::pair<records_t::const_iterator,records_t::const_iterator> range = d_records.equal_range(tie(qname));
223
224 SyncRes::AuthDomain::records_t::const_iterator ziter;
225 bool somedata = false;
226
227 for(ziter = range.first; ziter != range.second; ++ziter) {
228 somedata = true;
229
230 if(qtype == QType::ANY || ziter->d_type == qtype || ziter->d_type == QType::CNAME) {
231 // let rest of nameserver do the legwork on this one
232 records.push_back(*ziter);
233 }
234 else if (ziter->d_type == QType::NS && ziter->d_name.countLabels() > getName().countLabels()) {
235 // we hit a delegation point!
236 DNSRecord dr = *ziter;
237 dr.d_place=DNSResourceRecord::AUTHORITY;
238 records.push_back(dr);
239 }
240 }
241
242 if (!records.empty()) {
243 /* We have found an exact match, we're done */
244 // cerr<<qname<<": exact match in zone '"<<getName()<<"'"<<endl;
245 return result;
246 }
247
248 if (somedata) {
249 /* We have records for that name, but not of the wanted qtype */
250 // cerr<<qname<<": found record in '"<<getName()<<"', but nothing of the right type, sending SOA"<<endl;
251 addSOA(records);
252
253 return result;
254 }
255
256 // cerr<<qname<<": nothing found so far in '"<<getName()<<"', trying wildcards"<<endl;
257 DNSName wcarddomain(qname);
258 while(wcarddomain != getName() && wcarddomain.chopOff()) {
259 // cerr<<qname<<": trying '*."<<wcarddomain<<"' in "<<getName()<<endl;
260 range = d_records.equal_range(boost::make_tuple(g_wildcarddnsname + wcarddomain));
261 if (range.first==range.second)
262 continue;
263
264 for(ziter = range.first; ziter != range.second; ++ziter) {
265 DNSRecord dr = *ziter;
266 // if we hit a CNAME, just answer that - rest of recursor will do the needful & follow
267 if(dr.d_type == qtype || qtype == QType::ANY || dr.d_type == QType::CNAME) {
268 dr.d_name = qname;
269 dr.d_place = DNSResourceRecord::ANSWER;
270 records.push_back(dr);
271 }
272 }
273
274 if (records.empty()) {
275 addSOA(records);
276 }
277
278 // cerr<<qname<<": in '"<<getName()<<"', had wildcard match on '*."<<wcarddomain<<"'"<<endl;
279 return result;
280 }
281
282 /* Nothing for this name, no wildcard, let's see if there is some NS */
283 DNSName nsdomain(qname);
284 while (nsdomain.chopOff() && nsdomain != getName()) {
285 range = d_records.equal_range(boost::make_tuple(nsdomain,QType::NS));
286 if(range.first == range.second)
287 continue;
288
289 for(ziter = range.first; ziter != range.second; ++ziter) {
290 DNSRecord dr = *ziter;
291 dr.d_place = DNSResourceRecord::AUTHORITY;
292 records.push_back(dr);
293 }
294 }
295
296 if(records.empty()) {
297 // cerr<<qname<<": no NS match in zone '"<<getName()<<"' either, handing out SOA"<<endl;
298 addSOA(records);
299 result = RCode::NXDomain;
300 }
301
302 return result;
303 }
304
305 bool SyncRes::doOOBResolve(const AuthDomain& domain, const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int& res) const
306 {
307 res = domain.getRecords(qname, qtype.getCode(), ret);
308 return true;
309 }
310
311 bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int& res)
312 {
313 string prefix;
314 if(doLog()) {
315 prefix=d_prefix;
316 prefix.append(depth, ' ');
317 }
318
319 DNSName authdomain(qname);
320 domainmap_t::const_iterator iter=getBestAuthZone(&authdomain);
321 if(iter==t_sstorage.domainmap->end() || !iter->second.isAuth()) {
322 LOG(prefix<<qname<<": auth storage has no zone for this query!"<<endl);
323 return false;
324 }
325
326 LOG(prefix<<qname<<": auth storage has data, zone='"<<authdomain<<"'"<<endl);
327 return doOOBResolve(iter->second, qname, qtype, ret, res);
328 }
329
330 void SyncRes::doEDNSDumpAndClose(int fd)
331 {
332 FILE* fp=fdopen(fd, "w");
333 if (!fp) {
334 return;
335 }
336 fprintf(fp,"IP Address\tMode\tMode last updated at\n");
337 for(const auto& eds : t_sstorage.ednsstatus) {
338 fprintf(fp, "%s\t%d\t%s", eds.first.toString().c_str(), (int)eds.second.mode, ctime(&eds.second.modeSetAt));
339 }
340
341 fclose(fp);
342 }
343
344 uint64_t SyncRes::doDumpNSSpeeds(int fd)
345 {
346 FILE* fp=fdopen(dup(fd), "w");
347 if(!fp)
348 return 0;
349 fprintf(fp, "; nsspeed dump from thread follows\n;\n");
350 uint64_t count=0;
351
352 for(const auto& i : t_sstorage.nsSpeeds)
353 {
354 count++;
355 fprintf(fp, "%s -> ", i.first.toString().c_str());
356 for(const auto& j : i.second.d_collection)
357 {
358 // typedef vector<pair<ComboAddress, DecayingEwma> > collection_t;
359 fprintf(fp, "%s/%f ", j.first.toString().c_str(), j.second.peek());
360 }
361 fprintf(fp, "\n");
362 }
363 fclose(fp);
364 return count;
365 }
366
367 /* so here is the story. First we complete the full resolution process for a domain name. And only THEN do we decide
368 to also do DNSSEC validation, which leads to new queries. To make this simple, we *always* ask for DNSSEC records
369 so that if there are RRSIGs for a name, we'll have them.
370
371 However, some hosts simply can't answer questions which ask for DNSSEC. This can manifest itself as:
372 * No answer
373 * FormErr
374 * Nonsense answer
375
376 The cause of "No answer" may be fragmentation, and it is tempting to probe if smaller answers would get through.
377 Another cause of "No answer" may simply be a network condition.
378 Nonsense answers are a clearer indication this host won't be able to do DNSSEC evah.
379
380 Previous implementations have suffered from turning off DNSSEC questions for an authoritative server based on timeouts.
381 A clever idea is to only turn off DNSSEC if we know a domain isn't signed anyhow. The problem with that really
382 clever idea however is that at this point in PowerDNS, we may simply not know that yet. All the DNSSEC thinking happens
383 elsewhere. It may not have happened yet.
384
385 For now this means we can't be clever, but will turn off DNSSEC if you reply with FormError or gibberish.
386 */
387
388 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
389 {
390 /* what is your QUEST?
391 the goal is to get as many remotes as possible on the highest level of EDNS support
392 The levels are:
393
394 0) UNKNOWN Unknown state
395 1) EDNS: Honors EDNS0
396 2) EDNSIGNORANT: Ignores EDNS0, gives replies without EDNS0
397 3) NOEDNS: Generates FORMERR/NOTIMP on EDNS queries
398
399 Everybody starts out assumed to be '0'.
400 If '0', send out EDNS0
401 If you FORMERR us, go to '3',
402 If no EDNS in response, go to '2'
403 If '1', send out EDNS0
404 If FORMERR, downgrade to 3
405 If '2', keep on including EDNS0, see what happens
406 Same behaviour as 0
407 If '3', send bare queries
408 */
409
410 SyncRes::EDNSStatus* ednsstatus;
411 ednsstatus = &t_sstorage.ednsstatus[ip]; // does this include port? YES
412
413 if(ednsstatus->modeSetAt && ednsstatus->modeSetAt + 3600 < d_now.tv_sec) {
414 *ednsstatus=SyncRes::EDNSStatus();
415 // cerr<<"Resetting EDNS Status for "<<ip.toString()<<endl);
416 }
417
418 SyncRes::EDNSStatus::EDNSMode& mode=ednsstatus->mode;
419 SyncRes::EDNSStatus::EDNSMode oldmode = mode;
420 int EDNSLevel = 0;
421 auto luaconfsLocal = g_luaconfs.getLocal();
422 ResolveContext ctx;
423 #ifdef HAVE_PROTOBUF
424 ctx.d_initialRequestId = d_initialRequestId;
425 #endif
426
427 int ret;
428 for(int tries = 0; tries < 3; ++tries) {
429 // cerr<<"Remote '"<<ip.toString()<<"' currently in mode "<<mode<<endl;
430
431 if(mode==EDNSStatus::NOEDNS) {
432 g_stats.noEdnsOutQueries++;
433 EDNSLevel = 0; // level != mode
434 }
435 else if(ednsMANDATORY || mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSOK || mode==EDNSStatus::EDNSIGNORANT)
436 EDNSLevel = 1;
437
438 if (d_asyncResolve) {
439 ret = d_asyncResolve(ip, domain, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, luaconfsLocal->outgoingProtobufServer, res);
440 }
441 else {
442 ret=asyncresolve(ip, domain, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, luaconfsLocal->outgoingProtobufServer, res);
443 }
444 if(ret < 0) {
445 return ret; // transport error, nothing to learn here
446 }
447
448 if(ret == 0) { // timeout, not doing anything with it now
449 return ret;
450 }
451 else if(mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSOK || mode == EDNSStatus::EDNSIGNORANT ) {
452 if(res->d_rcode == RCode::FormErr || res->d_rcode == RCode::NotImp) {
453 // cerr<<"Downgrading to NOEDNS because of "<<RCode::to_s(res->d_rcode)<<" for query to "<<ip.toString()<<" for '"<<domain<<"'"<<endl;
454 mode = EDNSStatus::NOEDNS;
455 continue;
456 }
457 else if(!res->d_haveEDNS) {
458 if(mode != EDNSStatus::EDNSIGNORANT) {
459 mode = EDNSStatus::EDNSIGNORANT;
460 // cerr<<"We find that "<<ip.toString()<<" is an EDNS-ignorer for '"<<domain<<"', moving to mode 3"<<endl;
461 }
462 }
463 else {
464 mode = EDNSStatus::EDNSOK;
465 // cerr<<"We find that "<<ip.toString()<<" is EDNS OK!"<<endl;
466 }
467
468 }
469 if(oldmode != mode || !ednsstatus->modeSetAt)
470 ednsstatus->modeSetAt=d_now.tv_sec;
471 // cerr<<"Result: ret="<<ret<<", EDNS-level: "<<EDNSLevel<<", haveEDNS: "<<res->d_haveEDNS<<", new mode: "<<mode<<endl;
472 return ret;
473 }
474 return ret;
475 }
476
477 /*! This function will check the cache and go out to the internet if the answer is not in cache
478 *
479 * \param qname The name we need an answer for
480 * \param qtype
481 * \param ret The vector of DNSRecords we need to fill with the answers
482 * \param depth The recursion depth we are in
483 * \param beenthere
484 * \return DNS RCODE or -1 (Error) or -2 (RPZ hit)
485 */
486 int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, set<GetBestNSAnswer>& beenthere)
487 {
488 string prefix;
489 if(doLog()) {
490 prefix=d_prefix;
491 prefix.append(depth, ' ');
492 }
493
494 LOG(prefix<<qname<<": Wants "<< (d_doDNSSEC ? "" : "NO ") << "DNSSEC processing in query for "<<qtype.getName()<<endl);
495
496 if(s_maxdepth && depth > s_maxdepth)
497 throw ImmediateServFailException("More than "+std::to_string(s_maxdepth)+" (max-recursion-depth) levels of recursion needed while resolving "+qname.toLogString());
498
499 int res=0;
500
501 // This is a difficult way of expressing "this is a normal query", i.e. not getRootNS.
502 if(!(d_updatingRootNS && qtype.getCode()==QType::NS && qname.isRoot())) {
503 if(d_cacheonly) { // very limited OOB support
504 LWResult lwr;
505 LOG(prefix<<qname<<": Recursion not requested for '"<<qname<<"|"<<qtype.getName()<<"', peeking at auth/forward zones"<<endl);
506 DNSName authname(qname);
507 domainmap_t::const_iterator iter=getBestAuthZone(&authname);
508 if(iter != t_sstorage.domainmap->end()) {
509 if(iter->second.isAuth()) {
510 ret.clear();
511 d_wasOutOfBand = doOOBResolve(qname, qtype, ret, depth, res);
512 return res;
513 }
514 else {
515 const vector<ComboAddress>& servers = iter->second.d_servers;
516 const ComboAddress remoteIP = servers.front();
517 LOG(prefix<<qname<<": forwarding query to hardcoded nameserver '"<< remoteIP.toStringWithPort()<<"' for zone '"<<authname<<"'"<<endl);
518
519 boost::optional<Netmask> nm;
520 res=asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, qtype.getCode(), false, false, &d_now, nm, &lwr);
521 // filter out the good stuff from lwr.result()
522 if (res == 1) {
523 for(const auto& rec : lwr.d_records) {
524 if(rec.d_place == DNSResourceRecord::ANSWER)
525 ret.push_back(rec);
526 }
527 return 0;
528 }
529 else {
530 return RCode::ServFail;
531 }
532 }
533 }
534 }
535
536 if(!d_skipCNAMECheck && doCNAMECacheCheck(qname,qtype,ret,depth,res)) // will reroute us if needed
537 return res;
538
539 if(doCacheCheck(qname,qtype,ret,depth,res)) // we done
540 return res;
541 }
542
543 if(d_cacheonly)
544 return 0;
545
546 LOG(prefix<<qname<<": No cache hit for '"<<qname<<"|"<<qtype.getName()<<"', trying to find an appropriate NS record"<<endl);
547
548 DNSName subdomain(qname);
549 if(qtype == QType::DS) subdomain.chopOff();
550
551 NsSet nsset;
552 bool flawedNSSet=false;
553
554 // the two retries allow getBestNSNamesFromCache&co to reprime the root
555 // hints, in case they ever go missing
556 for(int tries=0;tries<2 && nsset.empty();++tries) {
557 subdomain=getBestNSNamesFromCache(subdomain, qtype, nsset, &flawedNSSet, depth, beenthere); // pass beenthere to both occasions
558 }
559
560 if(!(res=doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, ret, depth, beenthere)))
561 return 0;
562
563 LOG(prefix<<qname<<": failed (res="<<res<<")"<<endl);
564 ;
565
566 if (res == -2)
567 return res;
568
569 return res<0 ? RCode::ServFail : res;
570 }
571
572 #if 0
573 // for testing purposes
574 static bool ipv6First(const ComboAddress& a, const ComboAddress& b)
575 {
576 return !(a.sin4.sin_family < a.sin4.sin_family);
577 }
578 #endif
579
580 /** This function explicitly goes out for A or AAAA addresses
581 */
582 vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, unsigned int depth, set<GetBestNSAnswer>& beenthere)
583 {
584 typedef vector<DNSRecord> res_t;
585 res_t res;
586
587 typedef vector<ComboAddress> ret_t;
588 ret_t ret;
589
590 QType type;
591
592 for(int j=1; j<2+s_doIPv6; j++)
593 {
594 bool done=false;
595 switch(j) {
596 case 0:
597 type = QType::ANY;
598 break;
599 case 1:
600 type = QType::A;
601 break;
602 case 2:
603 type = QType::AAAA;
604 break;
605 }
606
607 if(!doResolve(qname, type, res,depth+1, beenthere) && !res.empty()) { // this consults cache, OR goes out
608 for(res_t::const_iterator i=res.begin(); i!= res.end(); ++i) {
609 if(i->d_type == QType::A || i->d_type == QType::AAAA) {
610 if(auto rec = std::dynamic_pointer_cast<ARecordContent>(i->d_content))
611 ret.push_back(rec->getCA(53));
612 else if(auto aaaarec = std::dynamic_pointer_cast<AAAARecordContent>(i->d_content))
613 ret.push_back(aaaarec->getCA(53));
614 done=true;
615 }
616 }
617 }
618 if(done) {
619 if(j==1 && s_doIPv6) { // we got an A record, see if we have some AAAA lying around
620 vector<DNSRecord> cset;
621 if(t_RC->get(d_now.tv_sec, qname, QType(QType::AAAA), &cset, d_requestor) > 0) {
622 for(auto k=cset.cbegin();k!=cset.cend();++k) {
623 if(k->d_ttl > (unsigned int)d_now.tv_sec ) {
624 if (auto drc = std::dynamic_pointer_cast<AAAARecordContent>(k->d_content)) {
625 ComboAddress ca=drc->getCA(53);
626 ret.push_back(ca);
627 }
628 }
629 }
630 }
631 }
632 break;
633 }
634 }
635
636 if(ret.size() > 1) {
637 random_shuffle(ret.begin(), ret.end(), dns_random);
638
639 // move 'best' address for this nameserver name up front
640 nsspeeds_t::iterator best = t_sstorage.nsSpeeds.find(qname);
641
642 if(best != t_sstorage.nsSpeeds.end())
643 for(ret_t::iterator i=ret.begin(); i != ret.end(); ++i) {
644 if(*i==best->second.d_best) { // got the fastest one
645 if(i!=ret.begin()) {
646 *i=*ret.begin();
647 *ret.begin()=best->second.d_best;
648 }
649 break;
650 }
651 }
652 }
653
654 return ret;
655 }
656
657 void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, vector<DNSRecord>& bestns, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>& beenthere)
658 {
659 string prefix;
660 DNSName subdomain(qname);
661 if(doLog()) {
662 prefix=d_prefix;
663 prefix.append(depth, ' ');
664 }
665 bestns.clear();
666 bool brokeloop;
667 do {
668 brokeloop=false;
669 LOG(prefix<<qname<<": Checking if we have NS in cache for '"<<subdomain<<"'"<<endl);
670 vector<DNSRecord> ns;
671 *flawedNSSet = false;
672 if(t_RC->get(d_now.tv_sec, subdomain, QType(QType::NS), &ns, d_requestor) > 0) {
673 for(auto k=ns.cbegin();k!=ns.cend(); ++k) {
674 if(k->d_ttl > (unsigned int)d_now.tv_sec ) {
675 vector<DNSRecord> aset;
676
677 const DNSRecord& dr=*k;
678 auto nrr = getRR<NSRecordContent>(dr);
679 if(nrr && (!nrr->getNS().isPartOf(subdomain) || t_RC->get(d_now.tv_sec, nrr->getNS(), s_doIPv6 ? QType(QType::ADDR) : QType(QType::A),
680 doLog() ? &aset : 0, d_requestor) > 5)) {
681 bestns.push_back(dr);
682 LOG(prefix<<qname<<": NS (with ip, or non-glue) in cache for '"<<subdomain<<"' -> '"<<nrr->getNS()<<"'"<<endl);
683 LOG(prefix<<qname<<": within bailiwick: "<< nrr->getNS().isPartOf(subdomain));
684 if(!aset.empty()) {
685 LOG(", in cache, ttl="<<(unsigned int)(((time_t)aset.begin()->d_ttl- d_now.tv_sec ))<<endl);
686 }
687 else {
688 LOG(", not in cache / did not look at cache"<<endl);
689 }
690 }
691 else {
692 *flawedNSSet=true;
693 LOG(prefix<<qname<<": NS in cache for '"<<subdomain<<"', but needs glue ("<<nrr->getNS()<<") which we miss or is expired"<<endl);
694 }
695 }
696 }
697 if(!bestns.empty()) {
698 GetBestNSAnswer answer;
699 answer.qname=qname;
700 answer.qtype=qtype.getCode();
701 for(const auto& dr : bestns)
702 answer.bestns.insert(make_pair(dr.d_name, getRR<NSRecordContent>(dr)->getNS()));
703
704 if(beenthere.count(answer)) {
705 brokeloop=true;
706 LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' but part of LOOP (already seen "<<answer.qname<<")! Trying less specific NS"<<endl);
707 ;
708 if(doLog())
709 for( set<GetBestNSAnswer>::const_iterator j=beenthere.begin();j!=beenthere.end();++j) {
710 bool neo = !(*j< answer || answer<*j);
711 LOG(prefix<<qname<<": beenthere"<<(neo?"*":"")<<": "<<j->qname<<"|"<<DNSRecordContent::NumberToType(j->qtype)<<" ("<<(unsigned int)j->bestns.size()<<")"<<endl);
712 }
713 bestns.clear();
714 }
715 else {
716 beenthere.insert(answer);
717 LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' (flawedNSSet="<<*flawedNSSet<<")"<<endl);
718 return;
719 }
720 }
721 }
722 LOG(prefix<<qname<<": no valid/useful NS in cache for '"<<subdomain<<"'"<<endl);
723 ;
724 if(subdomain.isRoot() && !brokeloop) {
725 // We lost the root NS records
726 primeHints();
727 LOG(prefix<<qname<<": reprimed the root"<<endl);
728 /* let's prevent an infinite loop */
729 if (!d_updatingRootNS) {
730 getRootNS(d_now, d_asyncResolve);
731 }
732 }
733 }while(subdomain.chopOff());
734 }
735
736 SyncRes::domainmap_t::const_iterator SyncRes::getBestAuthZone(DNSName* qname) const
737 {
738 SyncRes::domainmap_t::const_iterator ret;
739 do {
740 ret=t_sstorage.domainmap->find(*qname);
741 if(ret!=t_sstorage.domainmap->end())
742 break;
743 }while(qname->chopOff());
744 return ret;
745 }
746
747 /** doesn't actually do the work, leaves that to getBestNSFromCache */
748 DNSName SyncRes::getBestNSNamesFromCache(const DNSName &qname, const QType& qtype, NsSet& nsset, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>&beenthere)
749 {
750 DNSName subdomain(qname);
751 DNSName authdomain(qname);
752
753 domainmap_t::const_iterator iter=getBestAuthZone(&authdomain);
754 if(iter!=t_sstorage.domainmap->end()) {
755 if( iter->second.isAuth() )
756 // this gets picked up in doResolveAt, the empty DNSName, combined with the
757 // empty vector means 'we are auth for this zone'
758 nsset.insert({DNSName(), {{}, false}});
759 else {
760 // Again, picked up in doResolveAt. An empty DNSName, combined with a
761 // non-empty vector of ComboAddresses means 'this is a forwarded domain'
762 // This is actually picked up in retrieveAddressesForNS called from doResolveAt.
763 nsset.insert({DNSName(), {iter->second.d_servers, iter->second.shouldRecurse() }});
764 }
765 return authdomain;
766 }
767
768 vector<DNSRecord> bestns;
769 getBestNSFromCache(subdomain, qtype, bestns, flawedNSSet, depth, beenthere);
770
771 for(auto k=bestns.cbegin() ; k != bestns.cend(); ++k) {
772 // The actual resolver code will not even look at the ComboAddress or bool
773 nsset.insert({std::dynamic_pointer_cast<NSRecordContent>(k->d_content)->getNS(), {{}, false}});
774 if(k==bestns.cbegin())
775 subdomain=k->d_name;
776 }
777 return subdomain;
778 }
779
780 bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>& ret, unsigned int depth, int &res)
781 {
782 string prefix;
783 if(doLog()) {
784 prefix=d_prefix;
785 prefix.append(depth, ' ');
786 }
787
788 if((depth>9 && d_outqueries>10 && d_throttledqueries>5) || depth > 15) {
789 LOG(prefix<<qname<<": recursing (CNAME or other indirection) too deep, depth="<<depth<<endl);
790 res=RCode::ServFail;
791 return true;
792 }
793
794 LOG(prefix<<qname<<": Looking for CNAME cache hit of '"<<qname<<"|CNAME"<<"'"<<endl);
795 vector<DNSRecord> cset;
796 vector<std::shared_ptr<RRSIGRecordContent>> signatures;
797 if(t_RC->get(d_now.tv_sec, qname,QType(QType::CNAME), &cset, d_requestor, &signatures, &d_wasVariable) > 0) {
798
799 for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
800 if(j->d_ttl>(unsigned int) d_now.tv_sec) {
801 LOG(prefix<<qname<<": Found cache CNAME hit for '"<< qname << "|CNAME" <<"' to '"<<j->d_content->getZoneRepresentation()<<"'"<<endl);
802 DNSRecord dr=*j;
803 dr.d_ttl-=d_now.tv_sec;
804 ret.push_back(dr);
805
806 for(const auto& signature : signatures) {
807 DNSRecord sigdr;
808 sigdr.d_type=QType::RRSIG;
809 sigdr.d_name=qname;
810 sigdr.d_ttl=j->d_ttl - d_now.tv_sec;
811 sigdr.d_content=signature;
812 sigdr.d_place=DNSResourceRecord::ANSWER;
813 sigdr.d_class=1;
814 ret.push_back(sigdr);
815 }
816
817 if(qtype != QType::CNAME) { // perhaps they really wanted a CNAME!
818 set<GetBestNSAnswer>beenthere;
819 res=doResolve(std::dynamic_pointer_cast<CNAMERecordContent>(j->d_content)->getTarget(), qtype, ret, depth+1, beenthere);
820 }
821 else
822 res=0;
823 return true;
824 }
825 }
826 }
827 LOG(prefix<<qname<<": No CNAME cache hit of '"<< qname << "|CNAME" <<"' found"<<endl);
828 return false;
829 }
830
831 /*!
832 * Convience function to push the records from records into ret with a new TTL
833 *
834 * \param records DNSRecords that need to go into ret
835 * \param ttl The new TTL for these records
836 * \param ret The vector of DNSRecords that should contian the records with the modified TTL
837 */
838 static void addTTLModifiedRecords(const vector<DNSRecord>& records, const uint32_t ttl, vector<DNSRecord>& ret) {
839 for (const auto& rec : records) {
840 DNSRecord r(rec);
841 r.d_ttl = ttl;
842 ret.push_back(r);
843 }
844 }
845
846
847 bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res)
848 {
849 bool giveNegative=false;
850
851 string prefix;
852 if(doLog()) {
853 prefix=d_prefix;
854 prefix.append(depth, ' ');
855 }
856
857 // 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)
858 DNSName sqname(qname);
859 QType sqt(qtype);
860 uint32_t sttl=0;
861 // cout<<"Lookup for '"<<qname<<"|"<<qtype.getName()<<"' -> "<<getLastLabel(qname)<<endl;
862
863 DNSName authname(qname);
864 bool wasForwardedOrAuth = false;
865 bool wasAuth = false;
866 domainmap_t::const_iterator iter=getBestAuthZone(&authname);
867 if(iter != t_sstorage.domainmap->end()) {
868 wasForwardedOrAuth = true;
869 const vector<ComboAddress>& servers = iter->second.d_servers;
870 if(servers.empty()) {
871 wasAuth = true;
872 }
873 }
874 NegCache::NegCacheEntry ne;
875
876 if(s_rootNXTrust &&
877 t_sstorage.negcache.getRootNXTrust(qname, d_now, ne) &&
878 ne.d_auth.isRoot() &&
879 !(wasForwardedOrAuth && !authname.isRoot())) { // when forwarding, the root may only neg-cache if it was forwarded to.
880 sttl = ne.d_ttd - d_now.tv_sec;
881 LOG(prefix<<qname<<": Entire name '"<<qname<<"', is negatively cached via '"<<ne.d_auth<<"' & '"<<ne.d_name<<"' for another "<<sttl<<" seconds"<<endl);
882 res = RCode::NXDomain;
883 giveNegative = true;
884 }
885 else if (t_sstorage.negcache.get(qname, qtype, d_now, ne) &&
886 !(wasForwardedOrAuth && ne.d_auth != authname)) { // Only the authname nameserver can neg cache entries
887 res = 0;
888 sttl = ne.d_ttd - d_now.tv_sec;
889 giveNegative = true;
890 if(ne.d_qtype.getCode()) {
891 LOG(prefix<<qname<<": "<<qtype.getName()<<" is negatively cached via '"<<ne.d_auth<<"' for another "<<sttl<<" seconds"<<endl);
892 res = RCode::NoError;
893 }
894 else {
895 LOG(prefix<<qname<<": Entire name '"<<qname<<"', is negatively cached via '"<<ne.d_auth<<"' for another "<<sttl<<" seconds"<<endl);
896 res = RCode::NXDomain;
897 }
898 if(d_doDNSSEC) {
899 addTTLModifiedRecords(ne.DNSSECRecords.records, sttl, ret);
900 addTTLModifiedRecords(ne.DNSSECRecords.signatures, sttl, ret);
901 }
902 }
903
904 if (giveNegative) {
905 // Transplant SOA to the returned packet
906 addTTLModifiedRecords(ne.authoritySOA.records, sttl, ret);
907 if(d_doDNSSEC)
908 addTTLModifiedRecords(ne.authoritySOA.signatures, sttl, ret);
909 return true;
910 }
911
912 vector<DNSRecord> cset;
913 bool found=false, expired=false;
914 vector<std::shared_ptr<RRSIGRecordContent>> signatures;
915 uint32_t ttl=0;
916 if(t_RC->get(d_now.tv_sec, sqname, sqt, &cset, d_requestor, d_doDNSSEC ? &signatures : 0, &d_wasVariable) > 0) {
917 LOG(prefix<<sqname<<": Found cache hit for "<<sqt.getName()<<": ");
918 for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
919 LOG(j->d_content->getZoneRepresentation());
920 if(j->d_ttl>(unsigned int) d_now.tv_sec) {
921 DNSRecord dr=*j;
922 ttl = (dr.d_ttl-=d_now.tv_sec);
923 ret.push_back(dr);
924 LOG("[ttl="<<dr.d_ttl<<"] ");
925 found=true;
926 }
927 else {
928 LOG("[expired] ");
929 expired=true;
930 }
931 }
932
933 for(const auto& signature : signatures) {
934 DNSRecord dr;
935 dr.d_type=QType::RRSIG;
936 dr.d_name=sqname;
937 dr.d_ttl=ttl;
938 dr.d_content=signature;
939 dr.d_place = DNSResourceRecord::ANSWER;
940 dr.d_class=1;
941 ret.push_back(dr);
942 }
943
944 LOG(endl);
945 if(found && !expired) {
946 if(!giveNegative)
947 res=0;
948 d_wasOutOfBand = wasAuth;
949 return true;
950 }
951 else
952 LOG(prefix<<qname<<": cache had only stale entries"<<endl);
953 }
954
955 return false;
956 }
957
958 bool SyncRes::moreSpecificThan(const DNSName& a, const DNSName &b) const
959 {
960 return (a.isPartOf(b) && a.countLabels() > b.countLabels());
961 }
962
963 struct speedOrder
964 {
965 speedOrder(map<DNSName,double> &speeds) : d_speeds(speeds) {}
966 bool operator()(const DNSName &a, const DNSName &b) const
967 {
968 return d_speeds[a] < d_speeds[b];
969 }
970 map<DNSName, double>& d_speeds;
971 };
972
973 inline vector<DNSName> SyncRes::shuffleInSpeedOrder(NsSet &tnameservers, const string &prefix)
974 {
975 vector<DNSName> rnameservers;
976 rnameservers.reserve(tnameservers.size());
977 for(const auto& tns:tnameservers) {
978 rnameservers.push_back(tns.first);
979 }
980 map<DNSName, double> speeds;
981
982 for(const auto& val: rnameservers) {
983 double speed;
984 speed=t_sstorage.nsSpeeds[val].get(&d_now);
985 speeds[val]=speed;
986 }
987 random_shuffle(rnameservers.begin(),rnameservers.end(), dns_random);
988 speedOrder so(speeds);
989 stable_sort(rnameservers.begin(),rnameservers.end(), so);
990
991 if(doLog()) {
992 LOG(prefix<<"Nameservers: ");
993 for(vector<DNSName>::const_iterator i=rnameservers.begin();i!=rnameservers.end();++i) {
994 if(i!=rnameservers.begin()) {
995 LOG(", ");
996 if(!((i-rnameservers.begin())%3)) {
997 LOG(endl<<prefix<<" ");
998 }
999 }
1000 LOG((i->empty() ? string("<empty>") : i->toString())<<"(" << (boost::format("%0.2f") % (speeds[*i]/1000.0)).str() <<"ms)");
1001 }
1002 LOG(endl);
1003 }
1004 return rnameservers;
1005 }
1006
1007 static bool magicAddrMatch(const QType& query, const QType& answer)
1008 {
1009 if(query.getCode() != QType::ADDR)
1010 return false;
1011 return answer.getCode() == QType::A || answer.getCode() == QType::AAAA;
1012 }
1013
1014 /* Fills the authoritySOA and DNSSECRecords fields from ne with those found in the records
1015 *
1016 * \param records The records to parse for the authority SOA and NSEC(3) records
1017 * \param ne The NegCacheEntry to be filled out (will not be cleared, only appended to
1018 */
1019 static void harvestNXRecords(const vector<DNSRecord>& records, NegCache::NegCacheEntry& ne) {
1020 static const set<uint16_t> nsecTypes = {QType::NSEC, QType::NSEC3};
1021 for(const auto& rec : records) {
1022 if(rec.d_place != DNSResourceRecord::AUTHORITY)
1023 // RFC 4035 section 3.1.3. indicates that NSEC records MUST be placed in
1024 // the AUTHORITY section. Section 3.1.1 indicates that that RRSIGs for
1025 // records MUST be in the same section as the records they cover.
1026 // Hence, we ignore all records outside of the AUTHORITY section.
1027 continue;
1028
1029 if(rec.d_type == QType::RRSIG) {
1030 auto rrsig = getRR<RRSIGRecordContent>(rec);
1031 if(rrsig) {
1032 if(rrsig->d_type == QType::SOA) {
1033 ne.authoritySOA.signatures.push_back(rec);
1034 }
1035 if(nsecTypes.count(rrsig->d_type)) {
1036 ne.DNSSECRecords.signatures.push_back(rec);
1037 }
1038 }
1039 continue;
1040 }
1041 if(rec.d_type == QType::SOA) {
1042 ne.authoritySOA.records.push_back(rec);
1043 continue;
1044 }
1045 if(nsecTypes.count(rec.d_type)) {
1046 ne.DNSSECRecords.records.push_back(rec);
1047 continue;
1048 }
1049 }
1050 }
1051
1052 // TODO remove after processRecords is fixed!
1053 // Adds the RRSIG for the SOA and the NSEC(3) + RRSIGs to ret
1054 static void addNXNSECS(vector<DNSRecord>&ret, const vector<DNSRecord>& records)
1055 {
1056 NegCache::NegCacheEntry ne;
1057 harvestNXRecords(records, ne);
1058 ret.insert(ret.end(), ne.authoritySOA.signatures.begin(), ne.authoritySOA.signatures.end());
1059 ret.insert(ret.end(), ne.DNSSECRecords.records.begin(), ne.DNSSECRecords.records.end());
1060 ret.insert(ret.end(), ne.DNSSECRecords.signatures.begin(), ne.DNSSECRecords.signatures.end());
1061 }
1062
1063 bool SyncRes::nameserversBlockedByRPZ(const DNSFilterEngine& dfe, const NsSet& nameservers)
1064 {
1065 if(d_wantsRPZ) {
1066 for (auto const &ns : nameservers) {
1067 d_appliedPolicy = dfe.getProcessingPolicy(ns.first, d_discardedPolicies);
1068 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
1069 LOG(", however nameserver "<<ns.first<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
1070 return true;
1071 }
1072
1073 // Traverse all IP addresses for this NS to see if they have an RPN NSIP policy
1074 for (auto const &address : ns.second.first) {
1075 d_appliedPolicy = dfe.getProcessingPolicy(address, d_discardedPolicies);
1076 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
1077 LOG(", however nameserver "<<ns.first<<" IP address "<<address.toString()<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
1078 return true;
1079 }
1080 }
1081 }
1082 }
1083 return false;
1084 }
1085
1086 bool SyncRes::nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAddress& remoteIP)
1087 {
1088 if (d_wantsRPZ) {
1089 d_appliedPolicy = dfe.getProcessingPolicy(remoteIP, d_discardedPolicies);
1090 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) {
1091 LOG(" (blocked by RPZ policy '"+(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")+"')");
1092 return true;
1093 }
1094 }
1095 return false;
1096 }
1097
1098 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)
1099 {
1100 vector<ComboAddress> result;
1101
1102 if(!tns->empty()) {
1103 LOG(prefix<<qname<<": Trying to resolve NS '"<<*tns<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<<endl);
1104 result = getAddrs(*tns, depth+2, beenthere);
1105 pierceDontQuery=false;
1106 }
1107 else {
1108 LOG(prefix<<qname<<": Domain has hardcoded nameserver");
1109
1110 result = nameservers[*tns].first;
1111 if(result.size() > 1) {
1112 LOG("s");
1113 }
1114 LOG(endl);
1115
1116 sendRDQuery = nameservers[*tns].second;
1117 pierceDontQuery=true;
1118 }
1119 return result;
1120 }
1121
1122 bool SyncRes::throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, const QType& qtype, bool pierceDontQuery)
1123 {
1124 if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0))) {
1125 LOG(prefix<<qname<<": server throttled "<<endl);
1126 s_throttledqueries++; d_throttledqueries++;
1127 return true;
1128 }
1129 else if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()))) {
1130 LOG(prefix<<qname<<": query throttled "<<remoteIP.toString()<<", "<<qname<<"; "<<qtype.getName()<<endl);
1131 s_throttledqueries++; d_throttledqueries++;
1132 return true;
1133 }
1134 else if(!pierceDontQuery && s_dontQuery && s_dontQuery->match(&remoteIP)) {
1135 LOG(prefix<<qname<<": not sending query to " << remoteIP.toString() << ", blocked by 'dont-query' setting" << endl);
1136 s_dontqueries++;
1137 return true;
1138 }
1139 return false;
1140 }
1141
1142 RCode::rcodes_ SyncRes::updateCacheFromRecords(const std::string& prefix, LWResult& lwr, const DNSName& qname, const DNSName& auth, bool wasForwarded, const boost::optional<Netmask> ednsmask)
1143 {
1144 struct CachePair
1145 {
1146 vector<DNSRecord> records;
1147 vector<shared_ptr<RRSIGRecordContent>> signatures;
1148 };
1149 struct CacheKey
1150 {
1151 DNSName name;
1152 uint16_t type;
1153 DNSResourceRecord::Place place;
1154 bool operator<(const CacheKey& rhs) const {
1155 return tie(name, type) < tie(rhs.name, rhs.type);
1156 }
1157 };
1158 typedef map<CacheKey, CachePair> tcache_t;
1159 tcache_t tcache;
1160
1161 for(const auto& rec : lwr.d_records) {
1162 if(rec.d_type == QType::RRSIG) {
1163 auto rrsig = getRR<RRSIGRecordContent>(rec);
1164 if (rrsig) {
1165 // cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.d_name<<"'"<<endl;
1166 tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signatures.push_back(rrsig);
1167 }
1168 }
1169 }
1170
1171 // reap all answers from this packet that are acceptable
1172 for(auto& rec : lwr.d_records) {
1173 if(rec.d_type == QType::OPT) {
1174 LOG(prefix<<qname<<": OPT answer '"<<rec.d_name<<"' from '"<<auth<<"' nameservers" <<endl);
1175 continue;
1176 }
1177 LOG(prefix<<qname<<": accept answer '"<<rec.d_name<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<"|"<<rec.d_content->getZoneRepresentation()<<"' from '"<<auth<<"' nameservers? "<<(int)rec.d_place<<" ");
1178 if(rec.d_type == QType::ANY) {
1179 LOG("NO! - we don't accept 'ANY' data"<<endl);
1180 continue;
1181 }
1182
1183 if(rec.d_name.isPartOf(auth)) {
1184 if(rec.d_type == QType::RRSIG) {
1185 LOG("RRSIG - separate"<<endl);
1186 }
1187 else if(lwr.d_aabit && lwr.d_rcode==RCode::NoError && rec.d_place==DNSResourceRecord::ANSWER && (rec.d_type != QType::DNSKEY || rec.d_name != auth) && s_delegationOnly.count(auth)) {
1188 LOG("NO! Is from delegation-only zone"<<endl);
1189 s_nodelegated++;
1190 return RCode::NXDomain;
1191 }
1192 else {
1193 bool haveLogged = false;
1194 if (!t_sstorage.domainmap->empty()) {
1195 // Check if we are authoritative for a zone in this answer
1196 DNSName tmp_qname(rec.d_name);
1197 auto auth_domain_iter=getBestAuthZone(&tmp_qname);
1198 if(auth_domain_iter!=t_sstorage.domainmap->end() &&
1199 auth.countLabels() <= auth_domain_iter->first.countLabels()) {
1200 if (auth_domain_iter->first != auth) {
1201 LOG("NO! - we are authoritative for the zone "<<auth_domain_iter->first<<endl);
1202 continue;
1203 } else {
1204 LOG("YES! - This answer was ");
1205 if (!wasForwarded) {
1206 LOG("retrieved from the local auth store.");
1207 } else {
1208 LOG("received from a server we forward to.");
1209 }
1210 haveLogged = true;
1211 LOG(endl);
1212 }
1213 }
1214 }
1215 if (!haveLogged) {
1216 LOG("YES!"<<endl);
1217 }
1218
1219 rec.d_ttl=min(s_maxcachettl, rec.d_ttl);
1220
1221 DNSRecord dr(rec);
1222 dr.d_place=DNSResourceRecord::ANSWER;
1223
1224 dr.d_ttl += d_now.tv_sec;
1225 tcache[{rec.d_name,rec.d_type,rec.d_place}].records.push_back(dr);
1226 }
1227 }
1228 else
1229 LOG("NO!"<<endl);
1230 }
1231
1232 // supplant
1233 for(tcache_t::iterator i=tcache.begin();i!=tcache.end();++i) {
1234 if(i->second.records.size() > 1) { // need to group the ttl to be the minimum of the RRSET (RFC 2181, 5.2)
1235 uint32_t lowestTTL=std::numeric_limits<uint32_t>::max();
1236 for(const auto& record : i->second.records)
1237 lowestTTL=min(lowestTTL, record.d_ttl);
1238
1239 for(auto& record : i->second.records)
1240 *const_cast<uint32_t*>(&record.d_ttl)=lowestTTL; // boom
1241 }
1242
1243 // cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.name;
1244 // cout<<'|'<<DNSRecordContent::NumberToType(i->first.type)<<endl;
1245 if(i->second.records.empty()) // this happens when we did store signatures, but passed on the records themselves
1246 continue;
1247
1248 t_RC->replace(d_now.tv_sec, i->first.name, QType(i->first.type), i->second.records, i->second.signatures, lwr.d_aabit, i->first.place == DNSResourceRecord::ANSWER ? ednsmask : boost::none);
1249
1250 if(i->first.place == DNSResourceRecord::ANSWER && ednsmask)
1251 d_wasVariable=true;
1252 }
1253
1254 return RCode::NoError;
1255 }
1256
1257 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)
1258 {
1259 bool done = false;
1260
1261 for(auto& rec : lwr.d_records) {
1262 if (rec.d_type!=QType::OPT && rec.d_class!=QClass::IN)
1263 continue;
1264
1265 if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::SOA &&
1266 lwr.d_rcode==RCode::NXDomain && qname.isPartOf(rec.d_name) && rec.d_name.isPartOf(auth)) {
1267 LOG(prefix<<qname<<": got negative caching indication for name '"<<qname<<"' (accept="<<rec.d_name.isPartOf(auth)<<"), newtarget='"<<newtarget<<"'"<<endl);
1268
1269 rec.d_ttl = min(rec.d_ttl, s_maxnegttl);
1270 if(newtarget.empty()) // only add a SOA if we're not going anywhere after this
1271 ret.push_back(rec);
1272 if(!wasVariable()) {
1273 NegCache::NegCacheEntry ne;
1274
1275 ne.d_ttd = d_now.tv_sec + rec.d_ttl;
1276 ne.d_name = qname;
1277 ne.d_qtype = QType(0); // this encodes 'whole record'
1278 ne.d_auth = rec.d_name;
1279 harvestNXRecords(lwr.d_records, ne);
1280 t_sstorage.negcache.add(ne);
1281 if(s_rootNXTrust && ne.d_auth.isRoot() && auth.isRoot()) {
1282 ne.d_name = ne.d_name.getLastLabel();
1283 t_sstorage.negcache.add(ne);
1284 }
1285 }
1286
1287 negindic=true;
1288 }
1289 else if(rec.d_place==DNSResourceRecord::ANSWER && rec.d_name == qname && rec.d_type==QType::CNAME && (!(qtype==QType(QType::CNAME)))) {
1290 ret.push_back(rec);
1291 if (auto content = getRR<CNAMERecordContent>(rec)) {
1292 newtarget=content->getTarget();
1293 }
1294 }
1295 else if((rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSResourceRecord::ANSWER){
1296 if(rec.d_type != QType::RRSIG || rec.d_name == qname)
1297 ret.push_back(rec); // enjoy your DNSSEC
1298 }
1299 // for ANY answers we *must* have an authoritative answer, unless we are forwarding recursively
1300 else if(rec.d_place==DNSResourceRecord::ANSWER && rec.d_name == qname &&
1301 (
1302 rec.d_type==qtype.getCode() || (lwr.d_aabit && (qtype==QType(QType::ANY) || magicAddrMatch(qtype, QType(rec.d_type)) ) ) || sendRDQuery
1303 )
1304 )
1305 {
1306 LOG(prefix<<qname<<": answer is in: resolved to '"<< rec.d_content->getZoneRepresentation()<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<"'"<<endl);
1307
1308 done=true;
1309 ret.push_back(rec);
1310 }
1311 else if(rec.d_place==DNSResourceRecord::AUTHORITY && qname.isPartOf(rec.d_name) && rec.d_type==QType::NS) {
1312 if(moreSpecificThan(rec.d_name,auth)) {
1313 newauth=rec.d_name;
1314 LOG(prefix<<qname<<": got NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
1315 realreferral=true;
1316 }
1317 else {
1318 LOG(prefix<<qname<<": got upwards/level NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"', had '"<<auth<<"'"<<endl);
1319 }
1320 if (auto content = getRR<NSRecordContent>(rec)) {
1321 nsset.insert(content->getNS());
1322 }
1323 }
1324 else if(rec.d_place==DNSResourceRecord::AUTHORITY && qname.isPartOf(rec.d_name) && rec.d_type==QType::DS) {
1325 LOG(prefix<<qname<<": got DS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
1326 }
1327 else if(!done && rec.d_place==DNSResourceRecord::AUTHORITY && qname.isPartOf(rec.d_name) && rec.d_type==QType::SOA &&
1328 lwr.d_rcode==RCode::NoError) {
1329 LOG(prefix<<qname<<": got negative caching indication for '"<< qname<<"|"<<qtype.getName()<<"'"<<endl);
1330
1331 if(!newtarget.empty()) {
1332 LOG(prefix<<qname<<": Hang on! Got a redirect to '"<<newtarget<<"' already"<<endl);
1333 }
1334 else {
1335 rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
1336 ret.push_back(rec);
1337 if(!wasVariable()) {
1338 NegCache::NegCacheEntry ne;
1339 ne.d_auth = rec.d_name;
1340 ne.d_ttd = d_now.tv_sec + rec.d_ttl;
1341 ne.d_name = qname;
1342 ne.d_qtype = qtype;
1343 harvestNXRecords(lwr.d_records, ne);
1344 if(qtype.getCode()) { // prevents us from blacking out a whole domain
1345 t_sstorage.negcache.add(ne);
1346 }
1347 }
1348 negindic=true;
1349 }
1350 }
1351 }
1352
1353 return done;
1354 }
1355
1356 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)
1357 {
1358 int resolveret;
1359 s_outqueries++;
1360 d_outqueries++;
1361
1362 if(d_outqueries + d_throttledqueries > s_maxqperq) {
1363 throw ImmediateServFailException("more than "+std::to_string(s_maxqperq)+" (max-qperq) queries sent while resolving "+qname.toLogString());
1364 }
1365
1366 if(s_maxtotusec && d_totUsec > s_maxtotusec) {
1367 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");
1368 }
1369
1370 if(doTCP) {
1371 LOG(prefix<<qname<<": using TCP with "<< remoteIP.toStringWithPort() <<endl);
1372 s_tcpoutqueries++;
1373 d_tcpoutqueries++;
1374 }
1375
1376 if(d_pdl && d_pdl->preoutquery(remoteIP, d_requestor, qname, qtype, doTCP, lwr.d_records, resolveret)) {
1377 LOG(prefix<<qname<<": query handled by Lua"<<endl);
1378 }
1379 else {
1380 ednsmask=getEDNSSubnetMask(d_requestor, qname, remoteIP);
1381 if(ednsmask) {
1382 LOG(prefix<<qname<<": Adding EDNS Client Subnet Mask "<<ednsmask->toString()<<" to query"<<endl);
1383 }
1384 resolveret = asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, qtype.getCode(),
1385 doTCP, sendRDQuery, &d_now, ednsmask, &lwr); // <- we go out on the wire!
1386 if(ednsmask) {
1387 LOG(prefix<<qname<<": Received EDNS Client Subnet Mask "<<ednsmask->toString()<<" on response"<<endl);
1388 }
1389 }
1390
1391 /* preoutquery killed the query by setting dq.rcode to -3 */
1392 if(resolveret==-3) {
1393 throw ImmediateServFailException("Query killed by policy");
1394 }
1395
1396 d_totUsec += lwr.d_usec;
1397 accountAuthLatency(lwr.d_usec, remoteIP.sin4.sin_family);
1398
1399 if(resolveret != 1) {
1400 /* Error while resolving */
1401 if(resolveret == 0) {
1402 /* Time out */
1403
1404 LOG(prefix<<qname<<": timeout resolving after "<<lwr.d_usec/1000.0<<"msec "<< (doTCP ? "over TCP" : "")<<endl);
1405 d_timeouts++;
1406 s_outgoingtimeouts++;
1407
1408 if(remoteIP.sin4.sin_family == AF_INET)
1409 s_outgoing4timeouts++;
1410 else
1411 s_outgoing6timeouts++;
1412 }
1413 else if(resolveret == -2) {
1414 /* OS resource limit reached */
1415 LOG(prefix<<qname<<": hit a local resource limit resolving"<< (doTCP ? " over TCP" : "")<<", probable error: "<<stringerror()<<endl);
1416 g_stats.resourceLimits++;
1417 }
1418 else {
1419 /* -1 means server unreachable */
1420 s_unreachables++;
1421 d_unreachables++;
1422 LOG(prefix<<qname<<": error resolving from "<<remoteIP.toString()<< (doTCP ? " over TCP" : "") <<", possible error: "<<strerror(errno)<< endl);
1423 }
1424
1425 if(resolveret != -2) { // don't account for resource limits, they are our own fault
1426 t_sstorage.nsSpeeds[nsName].submit(remoteIP, 1000000, &d_now); // 1 sec
1427
1428 // code below makes sure we don't filter COM or the root
1429 if (s_serverdownmaxfails > 0 && (auth != g_rootdnsname) && t_sstorage.fails.incr(remoteIP) >= s_serverdownmaxfails) {
1430 LOG(prefix<<qname<<": Max fails reached resolving on "<< remoteIP.toString() <<". Going full throttle for "<< s_serverdownthrottletime <<" seconds" <<endl);
1431 // mark server as down
1432 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0), s_serverdownthrottletime, 10000);
1433 }
1434 else if (resolveret == -1) {
1435 // unreachable, 1 minute or 100 queries
1436 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 100);
1437 }
1438 else {
1439 // timeout
1440 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 10, 5);
1441 }
1442 }
1443
1444 return false;
1445 }
1446
1447 /* we got an answer */
1448 if(lwr.d_rcode==RCode::ServFail || lwr.d_rcode==RCode::Refused) {
1449 LOG(prefix<<qname<<": "<<nsName<<" ("<<remoteIP.toString()<<") returned a "<< (lwr.d_rcode==RCode::ServFail ? "ServFail" : "Refused") << ", trying sibling IP or NS"<<endl);
1450 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
1451 return false;
1452 }
1453
1454 /* this server sent a valid answer, mark it backup up if it was down */
1455 if(s_serverdownmaxfails > 0) {
1456 t_sstorage.fails.clear(remoteIP);
1457 }
1458
1459 if(lwr.d_tcbit) {
1460 *truncated = true;
1461
1462 if (doTCP) {
1463 LOG(prefix<<qname<<": truncated bit set, over TCP?"<<endl);
1464 /* let's treat that as a ServFail answer from this server */
1465 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
1466 return false;
1467 }
1468
1469 return true;
1470 }
1471
1472 return true;
1473 }
1474
1475 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)
1476 {
1477 string prefix;
1478 if(doLog()) {
1479 prefix=d_prefix;
1480 prefix.append(depth, ' ');
1481 }
1482
1483 if(s_minimumTTL) {
1484 for(auto& rec : lwr.d_records) {
1485 rec.d_ttl = max(rec.d_ttl, s_minimumTTL);
1486 }
1487 }
1488
1489 *rcode = updateCacheFromRecords(prefix, lwr, qname, auth, wasForwarded, ednsmask);
1490 if (*rcode != RCode::NoError) {
1491 return true;
1492 }
1493
1494 LOG(prefix<<qname<<": determining status after receiving this packet"<<endl);
1495
1496 set<DNSName> nsset;
1497 bool realreferral=false, negindic=false;
1498 DNSName newauth;
1499 DNSName newtarget;
1500
1501 bool done = processRecords(prefix, qname, qtype, auth, lwr, sendRDQuery, ret, nsset, newtarget, newauth, realreferral, negindic);
1502
1503 if(done){
1504 LOG(prefix<<qname<<": status=got results, this level of recursion done"<<endl);
1505 *rcode = RCode::NoError;
1506 return true;
1507 }
1508
1509 if(!newtarget.empty()) {
1510 if(newtarget == qname) {
1511 LOG(prefix<<qname<<": status=got a CNAME referral to self, returning SERVFAIL"<<endl);
1512 *rcode = RCode::ServFail;
1513 return true;
1514 }
1515
1516 if(depth > 10) {
1517 LOG(prefix<<qname<<": status=got a CNAME referral, but recursing too deep, returning SERVFAIL"<<endl);
1518 *rcode = RCode::ServFail;
1519 return true;
1520 }
1521
1522 LOG(prefix<<qname<<": status=got a CNAME referral, starting over with "<<newtarget<<endl);
1523
1524 set<GetBestNSAnswer> beenthere2;
1525 *rcode = doResolve(newtarget, qtype, ret, depth + 1, beenthere2);
1526 return true;
1527 }
1528
1529 if(lwr.d_rcode == RCode::NXDomain) {
1530 LOG(prefix<<qname<<": status=NXDOMAIN, we are done "<<(negindic ? "(have negative SOA)" : "")<<endl);
1531
1532 if(d_doDNSSEC)
1533 addNXNSECS(ret, lwr.d_records);
1534
1535 *rcode = RCode::NXDomain;
1536 return true;
1537 }
1538
1539 if(nsset.empty() && !lwr.d_rcode && (negindic || lwr.d_aabit || sendRDQuery)) {
1540 LOG(prefix<<qname<<": status=noerror, other types may exist, but we are done "<<(negindic ? "(have negative SOA) " : "")<<(lwr.d_aabit ? "(have aa bit) " : "")<<endl);
1541
1542 if(d_doDNSSEC)
1543 addNXNSECS(ret, lwr.d_records);
1544
1545 *rcode = RCode::NoError;
1546 return true;
1547 }
1548
1549 if(realreferral) {
1550 LOG(prefix<<qname<<": status=did not resolve, got "<<(unsigned int)nsset.size()<<" NS, ");
1551 auth=newauth;
1552
1553 nameservers.clear();
1554 for (auto const &nameserver : nsset) {
1555 if (d_wantsRPZ) {
1556 d_appliedPolicy = dfe.getProcessingPolicy(nameserver, d_discardedPolicies);
1557 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
1558 LOG("however "<<nameserver<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
1559 *rcode = -2;
1560 return true;
1561 }
1562 }
1563 nameservers.insert({nameserver, {{}, false}});
1564 }
1565 LOG("looping to them"<<endl);
1566 *gotNewServers = true;
1567 return false;
1568 }
1569
1570 return false;
1571 }
1572
1573 /** returns:
1574 * -1 in case of no results
1575 * -2 when a FilterEngine Policy was hit
1576 * rcode otherwise
1577 */
1578 int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype,
1579 vector<DNSRecord>&ret,
1580 unsigned int depth, set<GetBestNSAnswer>&beenthere)
1581 {
1582 auto luaconfsLocal = g_luaconfs.getLocal();
1583 string prefix;
1584 if(doLog()) {
1585 prefix=d_prefix;
1586 prefix.append(depth, ' ');
1587 }
1588
1589 LOG(prefix<<qname<<": Cache consultations done, have "<<(unsigned int)nameservers.size()<<" NS to contact");
1590
1591 if (nameserversBlockedByRPZ(luaconfsLocal->dfe, nameservers)) {
1592 return -2;
1593 }
1594
1595 LOG(endl);
1596
1597 for(;;) { // we may get more specific nameservers
1598 vector<DNSName > rnameservers = shuffleInSpeedOrder(nameservers, doLog() ? (prefix+qname.toString()+": ") : string() );
1599
1600 for(auto tns=rnameservers.cbegin();;++tns) {
1601 if(tns==rnameservers.cend()) {
1602 LOG(prefix<<qname<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth<<"'"<<endl);
1603 if(!auth.isRoot() && flawedNSSet) {
1604 LOG(prefix<<qname<<": Ageing nameservers for level '"<<auth<<"', next query might succeed"<<endl);
1605
1606 if(t_RC->doAgeCache(d_now.tv_sec, auth, QType::NS, 10))
1607 g_stats.nsSetInvalidations++;
1608 }
1609 return -1;
1610 }
1611
1612 // this line needs to identify the 'self-resolving' behaviour, but we get it wrong now
1613 if(qname == *tns && qtype.getCode()==QType::A && rnameservers.size() > (size_t)(1+1*s_doIPv6)) {
1614 LOG(prefix<<qname<<": Not using NS to resolve itself! ("<<(1+tns-rnameservers.cbegin())<<"/"<<rnameservers.size()<<")"<<endl);
1615 continue;
1616 }
1617
1618 typedef vector<ComboAddress> remoteIPs_t;
1619 remoteIPs_t remoteIPs;
1620 remoteIPs_t::const_iterator remoteIP;
1621 bool pierceDontQuery=false;
1622 bool sendRDQuery=false;
1623 boost::optional<Netmask> ednsmask;
1624 LWResult lwr;
1625 const bool wasForwarded = tns->empty() && (!nameservers[*tns].first.empty());
1626 int rcode = RCode::NoError;
1627 bool gotNewServers = false;
1628
1629 if(tns->empty() && !wasForwarded) {
1630 LOG(prefix<<qname<<": Domain is out-of-band"<<endl);
1631 d_wasOutOfBand = doOOBResolve(qname, qtype, lwr.d_records, depth, lwr.d_rcode);
1632 lwr.d_tcbit=false;
1633 lwr.d_aabit=true;
1634
1635 /* we have received an answer, are we done ? */
1636 bool done = processAnswer(depth, lwr, qname, qtype, auth, false, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode);
1637 if (done) {
1638 return rcode;
1639 }
1640 if (gotNewServers) {
1641 break;
1642 }
1643 }
1644 else {
1645 /* if tns is empty, retrieveAddressesForNS() knows we have hardcoded servers (i.e. "forwards") */
1646 remoteIPs = retrieveAddressesForNS(prefix, qname, tns, depth, beenthere, rnameservers, nameservers, sendRDQuery, pierceDontQuery, flawedNSSet);
1647
1648 if(remoteIPs.empty()) {
1649 LOG(prefix<<qname<<": Failed to get IP for NS "<<*tns<<", trying next if available"<<endl);
1650 flawedNSSet=true;
1651 continue;
1652 }
1653 else {
1654 bool hitPolicy{false};
1655 LOG(prefix<<qname<<": Resolved '"<<auth<<"' NS "<<*tns<<" to: ");
1656 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
1657 if(remoteIP != remoteIPs.cbegin()) {
1658 LOG(", ");
1659 }
1660 LOG(remoteIP->toString());
1661 if(nameserverIPBlockedByRPZ(luaconfsLocal->dfe, *remoteIP)) {
1662 hitPolicy = true;
1663 }
1664 }
1665 LOG(endl);
1666 if (hitPolicy) //implies d_wantsRPZ
1667 return -2;
1668 }
1669
1670 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
1671 LOG(prefix<<qname<<": Trying IP "<< remoteIP->toStringWithPort() <<", asking '"<<qname<<"|"<<qtype.getName()<<"'"<<endl);
1672
1673 if (throttledOrBlocked(prefix, *remoteIP, qname, qtype, pierceDontQuery)) {
1674 continue;
1675 }
1676
1677 bool truncated = false;
1678 bool gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery,
1679 *tns, *remoteIP, false, &truncated);
1680 if (gotAnswer && truncated ) {
1681 /* retry, over TCP this time */
1682 gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery,
1683 *tns, *remoteIP, true, &truncated);
1684 }
1685
1686 if (!gotAnswer) {
1687 continue;
1688 }
1689
1690 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);
1691
1692 /* // for you IPv6 fanatics :-)
1693 if(remoteIP->sin4.sin_family==AF_INET6)
1694 lwr.d_usec/=3;
1695 */
1696 // cout<<"msec: "<<lwr.d_usec/1000.0<<", "<<g_avgLatency/1000.0<<'\n';
1697
1698 t_sstorage.nsSpeeds[*tns].submit(*remoteIP, lwr.d_usec, &d_now);
1699
1700 /* we have received an answer, are we done ? */
1701 bool done = processAnswer(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode);
1702 if (done) {
1703 return rcode;
1704 }
1705 if (gotNewServers) {
1706 break;
1707 }
1708 /* was lame */
1709 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100);
1710 }
1711
1712 if (gotNewServers) {
1713 break;
1714 }
1715
1716 if(remoteIP == remoteIPs.cend()) // we tried all IP addresses, none worked
1717 continue;
1718
1719 }
1720 }
1721 }
1722 return -1;
1723 }
1724
1725 boost::optional<Netmask> SyncRes::getEDNSSubnetMask(const ComboAddress& local, const DNSName&dn, const ComboAddress& rem)
1726 {
1727 boost::optional<Netmask> result;
1728 ComboAddress trunc;
1729 uint8_t bits;
1730 if(d_incomingECSFound) {
1731 if (d_incomingECS->source.getBits() == 0) {
1732 /* RFC7871 says we MUST NOT send any ECS if the source scope is 0 */
1733 return result;
1734 }
1735 trunc = d_incomingECS->source.getMaskedNetwork();
1736 bits = d_incomingECS->source.getBits();
1737 }
1738 else if(!local.isIPv4() || local.sin4.sin_addr.s_addr) { // detect unset 'requestor'
1739 trunc = local;
1740 bits = local.isIPv4() ? 32 : 128;
1741 }
1742 else {
1743 /* nothing usable */
1744 return result;
1745 }
1746
1747 if(s_ednsdomains.check(dn) || s_ednssubnets.match(rem)) {
1748 bits = std::min(bits, (trunc.isIPv4() ? s_ecsipv4limit : s_ecsipv6limit));
1749 trunc.truncate(bits);
1750 return boost::optional<Netmask>(Netmask(trunc, bits));
1751 }
1752
1753 return result;
1754 }
1755
1756 void SyncRes::parseEDNSSubnetWhitelist(const std::string& wlist)
1757 {
1758 vector<string> parts;
1759 stringtok(parts, wlist, ",; ");
1760 for(const auto& a : parts) {
1761 try {
1762 s_ednssubnets.addMask(Netmask(a));
1763 }
1764 catch(...) {
1765 s_ednsdomains.add(DNSName(a));
1766 }
1767 }
1768 }
1769
1770 // used by PowerDNSLua - note that this neglects to add the packet count & statistics back to pdns_ercursor.cc
1771 int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<DNSRecord>& ret)
1772 {
1773 struct timeval now;
1774 gettimeofday(&now, 0);
1775
1776 SyncRes sr(now);
1777 int res = sr.beginResolve(qname, QType(qtype), qclass, ret);
1778
1779 return res;
1780 }
1781
1782 #include "validate-recursor.hh"
1783
1784 int SyncRes::getRootNS(struct timeval now, asyncresolve_t asyncCallback) {
1785 SyncRes sr(now);
1786 sr.setDoEDNS0(true);
1787 sr.setUpdatingRootNS();
1788 sr.setDoDNSSEC(g_dnssecmode != DNSSECMode::Off);
1789 sr.setAsyncCallback(asyncCallback);
1790
1791 vector<DNSRecord> ret;
1792 int res=-1;
1793 try {
1794 res=sr.beginResolve(g_rootdnsname, QType(QType::NS), 1, ret);
1795 if (g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate) {
1796 ResolveContext ctx;
1797 auto state = validateRecords(ctx, ret);
1798 if (state == Bogus)
1799 throw PDNSException("Got Bogus validation result for .|NS");
1800 }
1801 return res;
1802 }
1803 catch(const PDNSException& e) {
1804 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
1805 }
1806 catch(const ImmediateServFailException& e) {
1807 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
1808 }
1809 catch(const std::exception& e) {
1810 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.what()<<endl;
1811 }
1812 catch(...) {
1813 L<<Logger::Error<<"Failed to update . records, got an exception"<<endl;
1814 }
1815
1816 if(!res) {
1817 L<<Logger::Notice<<"Refreshed . records"<<endl;
1818 }
1819 else
1820 L<<Logger::Error<<"Failed to update . records, RCODE="<<res<<endl;
1821
1822 return res;
1823 }