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