]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/syncres.cc
Merge pull request #5374 from mind04/tools
[thirdparty/pdns.git] / pdns / syncres.cc
CommitLineData
86c152f2 1/*
6edbf68a
PL
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 */
870a0fe4
AT
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
fa8fd4d2 25
86c152f2 26#include "arguments.hh"
6dfff36f 27#include "cachecleaner.hh"
51e2144e 28#include "dns_random.hh"
6dfff36f
RG
29#include "dnsparser.hh"
30#include "dnsrecords.hh"
376effcf 31#include "ednssubnet.hh"
6dfff36f
RG
32#include "logger.hh"
33#include "lua-recursor4.hh"
ad42489c 34#include "rec-lua-conf.hh"
6dfff36f
RG
35#include "syncres.hh"
36
a712cb56 37thread_local SyncRes::ThreadLocalStorage SyncRes::t_sstorage;
bb4bdbaf 38
3337c2f7
RG
39std::unordered_set<DNSName> SyncRes::s_delegationOnly;
40std::unique_ptr<NetmaskGroup> SyncRes::s_dontQuery{nullptr};
41NetmaskGroup SyncRes::s_ednssubnets;
42SuffixMatchNode SyncRes::s_ednsdomains;
43string SyncRes::s_serverID;
44SyncRes::LogMode SyncRes::s_lm;
45
a9af3782 46unsigned int SyncRes::s_maxnegttl;
c3e753c7 47unsigned int SyncRes::s_maxcachettl;
3337c2f7
RG
48unsigned int SyncRes::s_maxqperq;
49unsigned int SyncRes::s_maxtotusec;
50unsigned int SyncRes::s_maxdepth;
51unsigned int SyncRes::s_minimumTTL;
1051f8a9
BH
52unsigned int SyncRes::s_packetcachettl;
53unsigned int SyncRes::s_packetcacheservfailttl;
628e2c7b
PA
54unsigned int SyncRes::s_serverdownmaxfails;
55unsigned int SyncRes::s_serverdownthrottletime;
aebb81e4 56std::atomic<uint64_t> SyncRes::s_queries;
57std::atomic<uint64_t> SyncRes::s_outgoingtimeouts;
58std::atomic<uint64_t> SyncRes::s_outgoing4timeouts;
59std::atomic<uint64_t> SyncRes::s_outgoing6timeouts;
60std::atomic<uint64_t> SyncRes::s_outqueries;
61std::atomic<uint64_t> SyncRes::s_tcpoutqueries;
62std::atomic<uint64_t> SyncRes::s_throttledqueries;
63std::atomic<uint64_t> SyncRes::s_dontqueries;
64std::atomic<uint64_t> SyncRes::s_nodelegated;
65std::atomic<uint64_t> SyncRes::s_unreachables;
e9f9b8ec
RG
66uint8_t SyncRes::s_ecsipv4limit;
67uint8_t SyncRes::s_ecsipv6limit;
996c89cc 68bool SyncRes::s_doIPv6;
1051f8a9 69bool SyncRes::s_nopacketcache;
01402d56 70bool SyncRes::s_rootNXTrust;
3337c2f7 71bool SyncRes::s_noEDNS;
c836dc19 72
77499b05 73#define LOG(x) if(d_lm == Log) { L <<Logger::Warning << x; } else if(d_lm == Store) { d_trace << x; }
728485ca 74
69cbdef9 75static void accountAuthLatency(int usec, int family)
11adfdd3 76{
7b75810e 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
11adfdd3 101}
102
4465e941 103
ac0e821b 104SyncRes::SyncRes(const struct timeval& now) : d_outqueries(0), d_tcpoutqueries(0), d_throttledqueries(0), d_timeouts(0), d_unreachables(0),
30ee601a 105 d_totUsec(0), d_now(now),
0b29b9c5 106 d_cacheonly(false), d_doDNSSEC(false), d_doEDNS0(false), d_lm(s_lm)
232f0877 107
ac0e821b 108{
ac0e821b
BH
109}
110
728485ca 111/** everything begins here - this is the entry point just after receiving a packet */
e325f20c 112int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSRecord>&ret)
728485ca 113{
c836dc19 114 s_queries++;
3762e821 115 d_wasVariable=false;
9fc36e90 116 d_wasOutOfBand=false;
710af846 117
db50a7f4
PL
118 if (doSpecialNamesResolve(qname, qtype, qclass, ret))
119 return 0;
120
fad4e1b2 121 if( (qtype.getCode() == QType::AXFR) || (qtype.getCode() == QType::IXFR))
693dbe65 122 return -1;
710af846 123
db50a7f4
PL
124 if(qclass==QClass::ANY)
125 qclass=QClass::IN;
126 else if(qclass!=QClass::IN)
127 return -1;
8171ab83 128
db50a7f4
PL
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 *
d03c1b70 137 * Handles the following queries (and their ANY variants):
db50a7f4
PL
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
db50a7f4 146 */
6dfff36f 147bool SyncRes::doSpecialNamesResolve(const DNSName &qname, const QType &qtype, const uint16_t qclass, vector<DNSRecord> &ret)
db50a7f4
PL
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;
d03c1b70 153 vector<pair<QType::typeenum, string> > answers;
db50a7f4 154
d03c1b70
PL
155 if ((qname == arpa || qname == ip6_arpa) &&
156 qclass == QClass::IN) {
db50a7f4 157 handled = true;
d03c1b70
PL
158 if (qtype == QType::PTR || qtype == QType::ANY)
159 answers.push_back({QType::PTR, "localhost."});
db50a7f4
PL
160 }
161
d03c1b70
PL
162 if (qname == localhost &&
163 qclass == QClass::IN) {
db50a7f4 164 handled = true;
d03c1b70
PL
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"});
db50a7f4
PL
169 }
170
d03c1b70
PL
171 if ((qname == versionbind || qname == idserver || qname == versionpdns) &&
172 qclass == QClass::CHAOS) {
db50a7f4 173 handled = true;
d03c1b70
PL
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 }
31ad43ab
BH
180 }
181
d03c1b70 182 if (handled && !answers.empty()) {
a9af3782 183 ret.clear();
db50a7f4
PL
184 d_wasOutOfBand=true;
185
e325f20c 186 DNSRecord dr;
db50a7f4 187 dr.d_name = qname;
e693ff5a 188 dr.d_place = DNSResourceRecord::ANSWER;
db50a7f4
PL
189 dr.d_class = qclass;
190 dr.d_ttl = 86400;
d03c1b70
PL
191 for (const auto& ans : answers) {
192 dr.d_type = ans.first;
193 dr.d_content = shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(ans.first, qclass, ans.second));
194 ret.push_back(dr);
195 }
a9af3782 196 }
710af846 197
db50a7f4 198 return handled;
728485ca 199}
afbe2787 200
db50a7f4 201
ab5c053d 202//! This is the 'out of band resolver', in other words, the authoritative server
3337c2f7 203void SyncRes::AuthDomain::addSOA(std::vector<DNSRecord>& records) const
e93c956b 204{
3337c2f7
RG
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);
5605c067 210 }
3337c2f7
RG
211 else {
212 // cerr<<qname<<": can't find SOA record '"<<getName()<<"' in our zone!"<<endl;
213 }
214}
5605c067 215
3337c2f7
RG
216int SyncRes::AuthDomain::getRecords(const DNSName& qname, uint16_t qtype, std::vector<DNSRecord>& records) const
217{
218 int result = RCode::NoError;
219 records.clear();
5605c067 220
3337c2f7
RG
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;
39eb8051 237 dr.d_place=DNSResourceRecord::AUTHORITY;
3337c2f7 238 records.push_back(dr);
39eb8051 239 }
5605c067 240 }
3337c2f7
RG
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;
5605c067 246 }
3337c2f7
RG
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;
9e9844e2 254 }
5605c067 255
3337c2f7 256 // cerr<<qname<<": nothing found so far in '"<<getName()<<"', trying wildcards"<<endl;
c5c066bf 257 DNSName wcarddomain(qname);
3337c2f7
RG
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)
0d1e259a
BH
262 continue;
263
3337c2f7
RG
264 for(ziter = range.first; ziter != range.second; ++ziter) {
265 DNSRecord dr = *ziter;
0f05b02b 266 // if we hit a CNAME, just answer that - rest of recursor will do the needful & follow
3337c2f7 267 if(dr.d_type == qtype || qtype == QType::ANY || dr.d_type == QType::CNAME) {
e325f20c 268 dr.d_name = qname;
3337c2f7
RG
269 dr.d_place = DNSResourceRecord::ANSWER;
270 records.push_back(dr);
0d1e259a
BH
271 }
272 }
3337c2f7
RG
273
274 if (records.empty()) {
275 addSOA(records);
276 }
277
278 // cerr<<qname<<": in '"<<getName()<<"', had wildcard match on '*."<<wcarddomain<<"'"<<endl;
279 return result;
0d1e259a
BH
280 }
281
3337c2f7 282 /* Nothing for this name, no wildcard, let's see if there is some NS */
c5c066bf 283 DNSName nsdomain(qname);
3337c2f7
RG
284 while (nsdomain.chopOff() && nsdomain != getName()) {
285 range = d_records.equal_range(boost::make_tuple(nsdomain,QType::NS));
286 if(range.first == range.second)
5605c067
BH
287 continue;
288
3337c2f7
RG
289 for(ziter = range.first; ziter != range.second; ++ziter) {
290 DNSRecord dr = *ziter;
291 dr.d_place = DNSResourceRecord::AUTHORITY;
292 records.push_back(dr);
5605c067
BH
293 }
294 }
3337c2f7
RG
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;
5605c067 300 }
5605c067 301
3337c2f7
RG
302 return result;
303}
304
305bool 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);
9e9844e2 308 return true;
e93c956b
BH
309}
310
3337c2f7
RG
311bool 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
ff1872cf
BH
330void SyncRes::doEDNSDumpAndClose(int fd)
331{
332 FILE* fp=fdopen(fd, "w");
a82f68f0
RG
333 if (!fp) {
334 return;
335 }
ff1872cf 336 fprintf(fp,"IP Address\tMode\tMode last updated at\n");
a712cb56 337 for(const auto& eds : t_sstorage.ednsstatus) {
57769f13 338 fprintf(fp, "%s\t%d\t%s", eds.first.toString().c_str(), (int)eds.second.mode, ctime(&eds.second.modeSetAt));
ff1872cf 339 }
bb4bdbaf 340
ff1872cf
BH
341 fclose(fp);
342}
343
9065eb05
RG
344uint64_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
a712cb56 352 for(const auto& i : t_sstorage.nsSpeeds)
9065eb05
RG
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
9d534f2a 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
69cbdef9 388int 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
81883dcc
BH
389{
390 /* what is your QUEST?
57769f13 391 the goal is to get as many remotes as possible on the highest level of EDNS support
81883dcc
BH
392 The levels are:
393
81883dcc 394 0) UNKNOWN Unknown state
57769f13 395 1) EDNS: Honors EDNS0
396 2) EDNSIGNORANT: Ignores EDNS0, gives replies without EDNS0
9d534f2a 397 3) NOEDNS: Generates FORMERR/NOTIMP on EDNS queries
81883dcc
BH
398
399 Everybody starts out assumed to be '0'.
57769f13 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
81883dcc 406 Same behaviour as 0
57769f13 407 If '3', send bare queries
81883dcc
BH
408 */
409
bb4bdbaf 410 SyncRes::EDNSStatus* ednsstatus;
a712cb56 411 ednsstatus = &t_sstorage.ednsstatus[ip]; // does this include port? YES
81883dcc 412
bb4bdbaf
BH
413 if(ednsstatus->modeSetAt && ednsstatus->modeSetAt + 3600 < d_now.tv_sec) {
414 *ednsstatus=SyncRes::EDNSStatus();
77499b05 415 // cerr<<"Resetting EDNS Status for "<<ip.toString()<<endl);
81883dcc
BH
416 }
417
bb4bdbaf 418 SyncRes::EDNSStatus::EDNSMode& mode=ednsstatus->mode;
81883dcc
BH
419 SyncRes::EDNSStatus::EDNSMode oldmode = mode;
420 int EDNSLevel=0;
4898a348
RG
421 auto luaconfsLocal = g_luaconfs.getLocal();
422 ResolveContext ctx;
423#ifdef HAVE_PROTOBUF
424 ctx.d_initialRequestId = d_initialRequestId;
425#endif
81883dcc
BH
426
427 int ret;
ff1872cf 428 for(int tries = 0; tries < 3; ++tries) {
e325f20c 429 // cerr<<"Remote '"<<ip.toString()<<"' currently in mode "<<mode<<endl;
57769f13 430
9d534f2a 431 if(mode==EDNSStatus::NOEDNS) {
81883dcc 432 g_stats.noEdnsOutQueries++;
9d534f2a 433 EDNSLevel = 0; // level != mode
81883dcc 434 }
9d534f2a 435 else if(ednsMANDATORY || mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSOK || mode==EDNSStatus::EDNSIGNORANT)
436 EDNSLevel = 1;
30ee601a
RG
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 }
9d534f2a 444 if(ret < 0) {
445 return ret; // transport error, nothing to learn here
446 }
57769f13 447
9d534f2a 448 if(ret == 0) { // timeout, not doing anything with it now
81883dcc
BH
449 return ret;
450 }
57769f13 451 else if(mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSOK || mode == EDNSStatus::EDNSIGNORANT ) {
452 if(res->d_rcode == RCode::FormErr || res->d_rcode == RCode::NotImp) {
2189085d 453 // cerr<<"Downgrading to NOEDNS because of "<<RCode::to_s(res->d_rcode)<<" for query to "<<ip.toString()<<" for '"<<domain<<"'"<<endl;
57769f13 454 mode = EDNSStatus::NOEDNS;
4957a608 455 continue;
81883dcc 456 }
81883dcc 457 else if(!res->d_haveEDNS) {
4957a608
BH
458 if(mode != EDNSStatus::EDNSIGNORANT) {
459 mode = EDNSStatus::EDNSIGNORANT;
2189085d 460 // cerr<<"We find that "<<ip.toString()<<" is an EDNS-ignorer for '"<<domain<<"', moving to mode 3"<<endl;
57769f13 461 }
81883dcc 462 }
57769f13 463 else {
464 mode = EDNSStatus::EDNSOK;
e325f20c 465 // cerr<<"We find that "<<ip.toString()<<" is EDNS OK!"<<endl;
81883dcc 466 }
57769f13 467
81883dcc 468 }
12ce523e 469 if(oldmode != mode || !ednsstatus->modeSetAt)
bb4bdbaf 470 ednsstatus->modeSetAt=d_now.tv_sec;
e325f20c 471 // cerr<<"Result: ret="<<ret<<", EDNS-level: "<<EDNSLevel<<", haveEDNS: "<<res->d_haveEDNS<<", new mode: "<<mode<<endl;
81883dcc
BH
472 return ret;
473 }
474 return ret;
475}
476
b88526ce
PL
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 */
7c3398aa 486int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, set<GetBestNSAnswer>& beenthere)
afbe2787 487{
ded77b10 488 string prefix;
77499b05 489 if(doLog()) {
ded77b10
BH
490 prefix=d_prefix;
491 prefix.append(depth, ' ');
492 }
b8470add 493
2189085d 494 LOG(prefix<<qname<<": Wants "<< (d_doDNSSEC ? "" : "NO ") << "DNSSEC processing in query for "<<qtype.getName()<<endl);
710af846 495
7c3398aa
RG
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
f4df5e89 499 int res=0;
b88526ce
PL
500
501 // This is a difficult way of expressing "this is a normal query", i.e. not getRootNS.
0b29b9c5 502 if(!(d_updatingRootNS && qtype.getCode()==QType::NS && qname.isRoot())) {
115d07ad 503 if(d_cacheonly) { // very limited OOB support
263f6a5a 504 LWResult lwr;
2189085d 505 LOG(prefix<<qname<<": Recursion not requested for '"<<qname<<"|"<<qtype.getName()<<"', peeking at auth/forward zones"<<endl);
c5c066bf 506 DNSName authname(qname);
115d07ad 507 domainmap_t::const_iterator iter=getBestAuthZone(&authname);
a712cb56 508 if(iter != t_sstorage.domainmap->end()) {
3337c2f7 509 if(iter->second.isAuth()) {
4957a608 510 ret.clear();
9fc36e90 511 d_wasOutOfBand = doOOBResolve(qname, qtype, ret, depth, res);
4957a608
BH
512 return res;
513 }
514 else {
3337c2f7 515 const vector<ComboAddress>& servers = iter->second.d_servers;
4957a608 516 const ComboAddress remoteIP = servers.front();
2189085d 517 LOG(prefix<<qname<<": forwarding query to hardcoded nameserver '"<< remoteIP.toStringWithPort()<<"' for zone '"<<authname<<"'"<<endl);
4957a608 518
6148fa97 519 boost::optional<Netmask> nm;
12ce523e 520 res=asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, qtype.getCode(), false, false, &d_now, nm, &lwr);
4957a608 521 // filter out the good stuff from lwr.result()
ab33a095
RG
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;
4957a608 531 }
4957a608 532 }
115d07ad
BH
533 }
534 }
535
a672e9de 536 if(!d_skipCNAMECheck && doCNAMECacheCheck(qname,qtype,ret,depth,res)) // will reroute us if needed
c836dc19 537 return res;
710af846 538
c836dc19
BH
539 if(doCacheCheck(qname,qtype,ret,depth,res)) // we done
540 return res;
541 }
afbe2787 542
115d07ad 543 if(d_cacheonly)
c836dc19 544 return 0;
728485ca 545
2189085d 546 LOG(prefix<<qname<<": No cache hit for '"<<qname<<"|"<<qtype.getName()<<"', trying to find an appropriate NS record"<<endl);
710af846 547
c5c066bf 548 DNSName subdomain(qname);
d8049162 549 if(qtype == QType::DS) subdomain.chopOff();
728485ca 550
fa1b87ff 551 NsSet nsset;
7305df82 552 bool flawedNSSet=false;
97df07f8
PD
553
554 // the two retries allow getBestNSNamesFromCache&co to reprime the root
555 // hints, in case they ever go missing
bdf40704 556 for(int tries=0;tries<2 && nsset.empty();++tries) {
891fbf88 557 subdomain=getBestNSNamesFromCache(subdomain, qtype, nsset, &flawedNSSet, depth, beenthere); // pass beenthere to both occasions
bdf40704
BH
558 }
559
7305df82 560 if(!(res=doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, ret, depth, beenthere)))
728485ca 561 return 0;
3ddb9247 562
2189085d 563 LOG(prefix<<qname<<": failed (res="<<res<<")"<<endl);
e325f20c 564 ;
b8470add
PL
565
566 if (res == -2)
567 return res;
568
20177d1d 569 return res<0 ? RCode::ServFail : res;
afbe2787
BH
570}
571
c2567ad1 572#if 0
a67dd0cf 573// for testing purposes
fdf05fd4
BH
574static bool ipv6First(const ComboAddress& a, const ComboAddress& b)
575{
576 return !(a.sin4.sin_family < a.sin4.sin_family);
577}
c2567ad1 578#endif
fdf05fd4 579
21f0f88b 580/** This function explicitly goes out for A or AAAA addresses
996c89cc 581*/
7c3398aa 582vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, unsigned int depth, set<GetBestNSAnswer>& beenthere)
75b49099 583{
e325f20c 584 typedef vector<DNSRecord> res_t;
bfea0d0b 585 res_t res;
75b49099 586
996c89cc
BH
587 typedef vector<ComboAddress> ret_t;
588 ret_t ret;
75b49099 589
d96e88da 590 QType type;
92011b8f 591
592 for(int j=1; j<2+s_doIPv6; j++)
d96e88da 593 {
76c01aec 594 bool done=false;
76c01aec
PD
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 }
d96e88da 606
891fbf88 607 if(!doResolve(qname, type, res,depth+1, beenthere) && !res.empty()) { // this consults cache, OR goes out
d96e88da 608 for(res_t::const_iterator i=res.begin(); i!= res.end(); ++i) {
e325f20c 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));
dd079764
RG
612 else if(auto aaaarec = std::dynamic_pointer_cast<AAAARecordContent>(i->d_content))
613 ret.push_back(aaaarec->getCA(53));
92011b8f 614 done=true;
d96e88da 615 }
42724edf 616 }
f4df5e89 617 }
710af846 618 if(done) {
60c9a54f 619 if(j==1 && s_doIPv6) { // we got an A record, see if we have some AAAA lying around
e325f20c 620 vector<DNSRecord> cset;
376effcf 621 if(t_RC->get(d_now.tv_sec, qname, QType(QType::AAAA), &cset, d_requestor) > 0) {
e325f20c 622 for(auto k=cset.cbegin();k!=cset.cend();++k) {
623 if(k->d_ttl > (unsigned int)d_now.tv_sec ) {
ba3c54cb
RG
624 if (auto drc = std::dynamic_pointer_cast<AAAARecordContent>(k->d_content)) {
625 ComboAddress ca=drc->getCA(53);
626 ret.push_back(ca);
627 }
60c9a54f 628 }
629 }
630 }
631 }
632 break;
633 }
bfea0d0b 634 }
710af846 635
996c89cc 636 if(ret.size() > 1) {
51e2144e 637 random_shuffle(ret.begin(), ret.end(), dns_random);
996c89cc 638
ae4d8cf1 639 // move 'best' address for this nameserver name up front
a712cb56 640 nsspeeds_t::iterator best = t_sstorage.nsSpeeds.find(qname);
996c89cc 641
a712cb56 642 if(best != t_sstorage.nsSpeeds.end())
710af846 643 for(ret_t::iterator i=ret.begin(); i != ret.end(); ++i) {
4957a608
BH
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 }
996c89cc
BH
651 }
652 }
fdf05fd4 653
728485ca 654 return ret;
75b49099
BH
655}
656
7c3398aa 657void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, vector<DNSRecord>& bestns, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>& beenthere)
86c152f2 658{
c5c066bf
PD
659 string prefix;
660 DNSName subdomain(qname);
77499b05 661 if(doLog()) {
ded77b10
BH
662 prefix=d_prefix;
663 prefix.append(depth, ' ');
664 }
75b49099 665 bestns.clear();
2b1b4054 666 bool brokeloop;
75b49099 667 do {
2b1b4054 668 brokeloop=false;
2189085d 669 LOG(prefix<<qname<<": Checking if we have NS in cache for '"<<subdomain<<"'"<<endl);
e325f20c 670 vector<DNSRecord> ns;
7305df82 671 *flawedNSSet = false;
376effcf 672 if(t_RC->get(d_now.tv_sec, subdomain, QType(QType::NS), &ns, d_requestor) > 0) {
e325f20c 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;
4957a608 676
e325f20c 677 const DNSRecord& dr=*k;
ba3c54cb
RG
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)) {
e325f20c 681 bestns.push_back(dr);
2189085d
PL
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));
4957a608 684 if(!aset.empty()) {
e325f20c 685 LOG(", in cache, ttl="<<(unsigned int)(((time_t)aset.begin()->d_ttl- d_now.tv_sec ))<<endl);
4957a608
BH
686 }
687 else {
77499b05 688 LOG(", not in cache / did not look at cache"<<endl);
4957a608
BH
689 }
690 }
691 else {
692 *flawedNSSet=true;
e325f20c 693 LOG(prefix<<qname<<": NS in cache for '"<<subdomain<<"', but needs glue ("<<nrr->getNS()<<") which we miss or is expired"<<endl);
4957a608
BH
694 }
695 }
afbe2787 696 }
75b49099 697 if(!bestns.empty()) {
4957a608 698 GetBestNSAnswer answer;
891fbf88 699 answer.qname=qname;
700 answer.qtype=qtype.getCode();
e325f20c 701 for(const auto& dr : bestns)
ba3c54cb 702 answer.bestns.insert(make_pair(dr.d_name, getRR<NSRecordContent>(dr)->getNS()));
891fbf88 703
4957a608 704 if(beenthere.count(answer)) {
2b1b4054 705 brokeloop=true;
2189085d 706 LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' but part of LOOP (already seen "<<answer.qname<<")! Trying less specific NS"<<endl);
e325f20c 707 ;
77499b05
BH
708 if(doLog())
709 for( set<GetBestNSAnswer>::const_iterator j=beenthere.begin();j!=beenthere.end();++j) {
2b1b4054 710 bool neo = !(*j< answer || answer<*j);
2189085d 711 LOG(prefix<<qname<<": beenthere"<<(neo?"*":"")<<": "<<j->qname<<"|"<<DNSRecordContent::NumberToType(j->qtype)<<" ("<<(unsigned int)j->bestns.size()<<")"<<endl);
77499b05 712 }
4957a608
BH
713 bestns.clear();
714 }
715 else {
6576051d 716 beenthere.insert(answer);
2189085d 717 LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' (flawedNSSet="<<*flawedNSSet<<")"<<endl);
4957a608
BH
718 return;
719 }
75b49099 720 }
afbe2787 721 }
2189085d 722 LOG(prefix<<qname<<": no valid/useful NS in cache for '"<<subdomain<<"'"<<endl);
e325f20c 723 ;
52683ca3 724 if(subdomain.isRoot() && !brokeloop) {
7836f7b4 725 // We lost the root NS records
3ddb9247 726 primeHints();
2189085d 727 LOG(prefix<<qname<<": reprimed the root"<<endl);
0b29b9c5
RG
728 /* let's prevent an infinite loop */
729 if (!d_updatingRootNS) {
730 getRootNS(d_now, d_asyncResolve);
731 }
6576051d 732 }
c5c066bf 733 }while(subdomain.chopOff());
75b49099
BH
734}
735
69cbdef9 736SyncRes::domainmap_t::const_iterator SyncRes::getBestAuthZone(DNSName* qname) const
5605c067
BH
737{
738 SyncRes::domainmap_t::const_iterator ret;
739 do {
a712cb56
RG
740 ret=t_sstorage.domainmap->find(*qname);
741 if(ret!=t_sstorage.domainmap->end())
5605c067 742 break;
c5c066bf 743 }while(qname->chopOff());
5605c067
BH
744 return ret;
745}
288f4aa9 746
7bf26383 747/** doesn't actually do the work, leaves that to getBestNSFromCache */
7c3398aa 748DNSName SyncRes::getBestNSNamesFromCache(const DNSName &qname, const QType& qtype, NsSet& nsset, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>&beenthere)
75b49099 749{
c5c066bf
PD
750 DNSName subdomain(qname);
751 DNSName authdomain(qname);
3ddb9247 752
5605c067 753 domainmap_t::const_iterator iter=getBestAuthZone(&authdomain);
a712cb56 754 if(iter!=t_sstorage.domainmap->end()) {
3337c2f7 755 if( iter->second.isAuth() )
fa1b87ff
PL
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}});
2e5ae2b2 759 else {
fa1b87ff
PL
760 // Again, picked up in doResolveAt. An empty DNSName, combined with a
761 // non-empty vector of ComboAddresses means 'this is a forwarded domain'
6dfff36f 762 // This is actually picked up in retrieveAddressesForNS called from doResolveAt.
3337c2f7 763 nsset.insert({DNSName(), {iter->second.d_servers, iter->second.shouldRecurse() }});
2e5ae2b2 764 }
5605c067
BH
765 return authdomain;
766 }
767
e325f20c 768 vector<DNSRecord> bestns;
891fbf88 769 getBestNSFromCache(subdomain, qtype, bestns, flawedNSSet, depth, beenthere);
75b49099 770
e325f20c 771 for(auto k=bestns.cbegin() ; k != bestns.cend(); ++k) {
fa1b87ff
PL
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}});
e325f20c 774 if(k==bestns.cbegin())
775 subdomain=k->d_name;
86c152f2 776 }
75b49099 777 return subdomain;
afbe2787
BH
778}
779
7c3398aa 780bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>& ret, unsigned int depth, int &res)
afbe2787 781{
ded77b10 782 string prefix;
77499b05 783 if(doLog()) {
710af846 784 prefix=d_prefix;
ded77b10
BH
785 prefix.append(depth, ' ');
786 }
36f5e3db 787
40de2910 788 if((depth>9 && d_outqueries>10 && d_throttledqueries>5) || depth > 15) {
2189085d 789 LOG(prefix<<qname<<": recursing (CNAME or other indirection) too deep, depth="<<depth<<endl);
c6644fc5
BH
790 res=RCode::ServFail;
791 return true;
792 }
3ddb9247 793
2189085d 794 LOG(prefix<<qname<<": Looking for CNAME cache hit of '"<<qname<<"|CNAME"<<"'"<<endl);
e325f20c 795 vector<DNSRecord> cset;
1f77f479 796 vector<std::shared_ptr<RRSIGRecordContent>> signatures;
376effcf 797 if(t_RC->get(d_now.tv_sec, qname,QType(QType::CNAME), &cset, d_requestor, &signatures) > 0) {
36c5ee42 798
e325f20c 799 for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
800 if(j->d_ttl>(unsigned int) d_now.tv_sec) {
2189085d 801 LOG(prefix<<qname<<": Found cache CNAME hit for '"<< qname << "|CNAME" <<"' to '"<<j->d_content->getZoneRepresentation()<<"'"<<endl);
e325f20c 802 DNSRecord dr=*j;
803 dr.d_ttl-=d_now.tv_sec;
804 ret.push_back(dr);
1f77f479 805
806 for(const auto& signature : signatures) {
dd079764
RG
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);
1f77f479 815 }
816
f8e7daf8 817 if(qtype != QType::CNAME) { // perhaps they really wanted a CNAME!
4957a608 818 set<GetBestNSAnswer>beenthere;
e325f20c 819 res=doResolve(std::dynamic_pointer_cast<CNAMERecordContent>(j->d_content)->getTarget(), qtype, ret, depth+1, beenthere);
4957a608
BH
820 }
821 else
822 res=0;
823 return true;
ac539791
BH
824 }
825 }
afbe2787 826 }
2189085d 827 LOG(prefix<<qname<<": No CNAME cache hit of '"<< qname << "|CNAME" <<"' found"<<endl);
75b49099
BH
828 return false;
829}
830
6909b8c5
PL
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 */
838static void addTTLModifiedRecords(const vector<DNSRecord>& records, const uint32_t ttl, vector<DNSRecord>& ret) {
39ce10b2
PL
839 for (const auto& rec : records) {
840 DNSRecord r(rec);
841 r.d_ttl = ttl;
842 ret.push_back(r);
843 }
844}
845
e325f20c 846
7c3398aa 847bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res)
75b49099 848{
fd8bc993 849 bool giveNegative=false;
710af846 850
be718669 851 string prefix;
77499b05 852 if(doLog()) {
ded77b10
BH
853 prefix=d_prefix;
854 prefix.append(depth, ' ');
855 }
afbe2787 856
30e9bd93 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)
c5c066bf 858 DNSName sqname(qname);
288f4aa9 859 QType sqt(qtype);
092f210a 860 uint32_t sttl=0;
2189085d 861 // cout<<"Lookup for '"<<qname<<"|"<<qtype.getName()<<"' -> "<<getLastLabel(qname)<<endl;
3ddb9247 862
64a8b6a1 863 DNSName authname(qname);
129bb0c3
RG
864 bool wasForwardedOrAuth = false;
865 bool wasAuth = false;
866 domainmap_t::const_iterator iter=getBestAuthZone(&authname);
a712cb56 867 if(iter != t_sstorage.domainmap->end()) {
129bb0c3
RG
868 wasForwardedOrAuth = true;
869 const vector<ComboAddress>& servers = iter->second.d_servers;
870 if(servers.empty()) {
871 wasAuth = true;
872 }
873 }
39ce10b2 874 NegCache::NegCacheEntry ne;
64a8b6a1 875
710af846 876 if(s_rootNXTrust &&
a712cb56 877 t_sstorage.negcache.getRootNXTrust(qname, d_now, ne) &&
39ce10b2
PL
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);
3ddb9247 882 res = RCode::NXDomain;
39ce10b2 883 giveNegative = true;
01402d56 884 }
a712cb56 885 else if (t_sstorage.negcache.get(qname, qtype, d_now, ne) &&
39ce10b2
PL
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;
fd8bc993 893 }
39ce10b2
PL
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;
fd8bc993 910 }
39ce10b2 911
e325f20c 912 vector<DNSRecord> cset;
75b49099 913 bool found=false, expired=false;
57769f13 914 vector<std::shared_ptr<RRSIGRecordContent>> signatures;
915 uint32_t ttl=0;
376effcf 916 if(t_RC->get(d_now.tv_sec, sqname, sqt, &cset, d_requestor, d_doDNSSEC ? &signatures : 0) > 0) {
2189085d 917 LOG(prefix<<sqname<<": Found cache hit for "<<sqt.getName()<<": ");
e325f20c 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);
e325f20c 923 ret.push_back(dr);
924 LOG("[ttl="<<dr.d_ttl<<"] ");
4957a608 925 found=true;
ac539791 926 }
75b49099 927 else {
77499b05 928 LOG("[expired] ");
4957a608 929 expired=true;
75b49099 930 }
afbe2787 931 }
57769f13 932
933 for(const auto& signature : signatures) {
e325f20c 934 DNSRecord dr;
935 dr.d_type=QType::RRSIG;
936 dr.d_name=sqname;
937 dr.d_ttl=ttl;
938 dr.d_content=signature;
39ce10b2 939 dr.d_place = DNSResourceRecord::ANSWER;
e325f20c 940 dr.d_class=1;
941 ret.push_back(dr);
57769f13 942 }
ac539791 943
77499b05 944 LOG(endl);
f4df5e89 945 if(found && !expired) {
f15a5b2a 946 if(!giveNegative)
4957a608 947 res=0;
129bb0c3 948 d_wasOutOfBand = wasAuth;
75b49099 949 return true;
f4df5e89 950 }
75b49099 951 else
2189085d 952 LOG(prefix<<qname<<": cache had only stale entries"<<endl);
afbe2787 953 }
f4df5e89 954
75b49099
BH
955 return false;
956}
afbe2787 957
69cbdef9 958bool SyncRes::moreSpecificThan(const DNSName& a, const DNSName &b) const
75b49099 959{
6a1010f7 960 return (a.isPartOf(b) && a.countLabels() > b.countLabels());
afbe2787
BH
961}
962
d8d0bb8f 963struct speedOrder
eefd15f9 964{
3ddb9247
PD
965 speedOrder(map<DNSName,double> &speeds) : d_speeds(speeds) {}
966 bool operator()(const DNSName &a, const DNSName &b) const
c3d9d009
BH
967 {
968 return d_speeds[a] < d_speeds[b];
c3d9d009 969 }
3ddb9247 970 map<DNSName, double>& d_speeds;
c3d9d009
BH
971};
972
fa1b87ff 973inline vector<DNSName> SyncRes::shuffleInSpeedOrder(NsSet &tnameservers, const string &prefix)
afbe2787 974{
e8b23f3b 975 vector<DNSName> rnameservers;
5ea6f7de 976 rnameservers.reserve(tnameservers.size());
e8b23f3b 977 for(const auto& tns:tnameservers) {
88490c03 978 rnameservers.push_back(tns.first);
21f0f88b 979 }
e8b23f3b 980 map<DNSName, double> speeds;
461df9d2 981
e8b23f3b 982 for(const auto& val: rnameservers) {
79b8cdcc 983 double speed;
a712cb56 984 speed=t_sstorage.nsSpeeds[val].get(&d_now);
21f0f88b 985 speeds[val]=speed;
eefd15f9 986 }
51e2144e 987 random_shuffle(rnameservers.begin(),rnameservers.end(), dns_random);
996c89cc
BH
988 speedOrder so(speeds);
989 stable_sort(rnameservers.begin(),rnameservers.end(), so);
710af846 990
77499b05
BH
991 if(doLog()) {
992 LOG(prefix<<"Nameservers: ");
e325f20c 993 for(vector<DNSName>::const_iterator i=rnameservers.begin();i!=rnameservers.end();++i) {
3ddb9247 994 if(i!=rnameservers.begin()) {
77499b05
BH
995 LOG(", ");
996 if(!((i-rnameservers.begin())%3)) {
997 LOG(endl<<prefix<<" ");
998 }
d8d0bb8f 999 }
34dcd30c 1000 LOG((i->empty() ? string("<empty>") : i->toString())<<"(" << (boost::format("%0.2f") % (speeds[*i]/1000.0)).str() <<"ms)");
d8d0bb8f 1001 }
77499b05 1002 LOG(endl);
d8d0bb8f 1003 }
728485ca 1004 return rnameservers;
afbe2787
BH
1005}
1006
bf7e4a70
BH
1007static 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}
7738a23f 1013
39ce10b2
PL
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 */
1019static void harvestNXRecords(const vector<DNSRecord>& records, NegCache::NegCacheEntry& ne) {
1020 static const set<uint16_t> nsecTypes = {QType::NSEC, QType::NSEC3};
620db2c8 1021 for(const auto& rec : records) {
39ce10b2
PL
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
620db2c8 1029 if(rec.d_type == QType::RRSIG) {
39ce10b2
PL
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;
620db2c8 1048 }
620db2c8 1049 }
620db2c8 1050}
1051
39ce10b2
PL
1052// TODO remove after processRecords is fixed!
1053// Adds the RRSIG for the SOA and the NSEC(3) + RRSIGs to ret
620db2c8 1054static void addNXNSECS(vector<DNSRecord>&ret, const vector<DNSRecord>& records)
1055{
39ce10b2
PL
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());
620db2c8 1061}
1062
69cbdef9 1063bool SyncRes::nameserversBlockedByRPZ(const DNSFilterEngine& dfe, const NsSet& nameservers)
26ca3513
RG
1064{
1065 if(d_wantsRPZ) {
1066 for (auto const &ns : nameservers) {
69cbdef9 1067 d_appliedPolicy = dfe.getProcessingPolicy(ns.first, d_discardedPolicies);
26ca3513
RG
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) {
69cbdef9 1075 d_appliedPolicy = dfe.getProcessingPolicy(address, d_discardedPolicies);
26ca3513
RG
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
69cbdef9 1086bool SyncRes::nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAddress& remoteIP)
26ca3513
RG
1087{
1088 if (d_wantsRPZ) {
69cbdef9 1089 d_appliedPolicy = dfe.getProcessingPolicy(remoteIP, d_discardedPolicies);
26ca3513
RG
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
1098vector<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
1122bool SyncRes::throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, const QType& qtype, bool pierceDontQuery)
1123{
a712cb56 1124 if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0))) {
26ca3513
RG
1125 LOG(prefix<<qname<<": server throttled "<<endl);
1126 s_throttledqueries++; d_throttledqueries++;
1127 return true;
1128 }
a712cb56 1129 else if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()))) {
6dfff36f 1130 LOG(prefix<<qname<<": query throttled "<<remoteIP.toString()<<", "<<qname<<"; "<<qtype.getName()<<endl);
26ca3513
RG
1131 s_throttledqueries++; d_throttledqueries++;
1132 return true;
1133 }
9065eb05 1134 else if(!pierceDontQuery && s_dontQuery && s_dontQuery->match(&remoteIP)) {
26ca3513
RG
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
6dfff36f 1142RCode::rcodes_ SyncRes::updateCacheFromRecords(const std::string& prefix, LWResult& lwr, const DNSName& qname, const DNSName& auth, bool wasForwarded, const boost::optional<Netmask> ednsmask)
26ca3513
RG
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 }
9065eb05 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)) {
26ca3513
RG
1188 LOG("NO! Is from delegation-only zone"<<endl);
1189 s_nodelegated++;
1190 return RCode::NXDomain;
1191 }
1192 else {
1193 bool haveLogged = false;
a712cb56 1194 if (!t_sstorage.domainmap->empty()) {
26ca3513
RG
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);
a712cb56 1198 if(auth_domain_iter!=t_sstorage.domainmap->end() &&
26ca3513
RG
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 ");
6dfff36f 1205 if (!wasForwarded) {
26ca3513
RG
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;
6dfff36f 1247
26ca3513 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::optional<Netmask>());
6dfff36f 1249
26ca3513
RG
1250 if(i->first.place == DNSResourceRecord::ANSWER && ednsmask)
1251 d_wasVariable=true;
1252 }
1253
1254 return RCode::NoError;
1255}
1256
6dfff36f 1257bool 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)
26ca3513
RG
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()) {
39ce10b2
PL
1273 NegCache::NegCacheEntry ne;
1274
39ce10b2
PL
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'
898856ca 1278 ne.d_auth = rec.d_name;
39ce10b2 1279 harvestNXRecords(lwr.d_records, ne);
a712cb56 1280 t_sstorage.negcache.add(ne);
07e3cfb6 1281 if(s_rootNXTrust && ne.d_auth.isRoot() && auth.isRoot()) {
9a1e060b 1282 ne.d_name = ne.d_name.getLastLabel();
a712cb56 1283 t_sstorage.negcache.add(ne);
26ca3513
RG
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);
26ca3513
RG
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()) {
39ce10b2
PL
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);
26ca3513 1344 if(qtype.getCode()) { // prevents us from blacking out a whole domain
a712cb56 1345 t_sstorage.negcache.add(ne);
26ca3513
RG
1346 }
1347 }
1348 negindic=true;
1349 }
1350 }
1351 }
1352
1353 return done;
1354}
1355
6dfff36f
RG
1356bool 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
1475bool 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
b8470add
PL
1573/** returns:
1574 * -1 in case of no results
1575 * -2 when a FilterEngine Policy was hit
1576 * rcode otherwise
1577 */
fa1b87ff 1578int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype,
e325f20c 1579 vector<DNSRecord>&ret,
7c3398aa 1580 unsigned int depth, set<GetBestNSAnswer>&beenthere)
86c152f2 1581{
69cbdef9 1582 auto luaconfsLocal = g_luaconfs.getLocal();
ded77b10 1583 string prefix;
77499b05 1584 if(doLog()) {
ded77b10
BH
1585 prefix=d_prefix;
1586 prefix.append(depth, ' ');
1587 }
3ddb9247 1588
b8470add
PL
1589 LOG(prefix<<qname<<": Cache consultations done, have "<<(unsigned int)nameservers.size()<<" NS to contact");
1590
69cbdef9 1591 if (nameserversBlockedByRPZ(luaconfsLocal->dfe, nameservers)) {
26ca3513 1592 return -2;
b8470add
PL
1593 }
1594
1595 LOG(endl);
afbe2787
BH
1596
1597 for(;;) { // we may get more specific nameservers
e8b23f3b 1598 vector<DNSName > rnameservers = shuffleInSpeedOrder(nameservers, doLog() ? (prefix+qname.toString()+": ") : string() );
3ddb9247 1599
26ca3513
RG
1600 for(auto tns=rnameservers.cbegin();;++tns) {
1601 if(tns==rnameservers.cend()) {
2189085d 1602 LOG(prefix<<qname<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth<<"'"<<endl);
03c09afe 1603 if(!auth.isRoot() && flawedNSSet) {
2189085d 1604 LOG(prefix<<qname<<": Ageing nameservers for level '"<<auth<<"', next query might succeed"<<endl);
88490c03 1605
49a699c4 1606 if(t_RC->doAgeCache(d_now.tv_sec, auth, QType::NS, 10))
4957a608
BH
1607 g_stats.nsSetInvalidations++;
1608 }
1609 return -1;
afbe2787 1610 }
6dfff36f 1611
21f0f88b 1612 // this line needs to identify the 'self-resolving' behaviour, but we get it wrong now
26ca3513
RG
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);
4957a608 1615 continue;
20177d1d 1616 }
5605c067 1617
996c89cc 1618 typedef vector<ComboAddress> remoteIPs_t;
5605c067 1619 remoteIPs_t remoteIPs;
bfea0d0b 1620 remoteIPs_t::const_iterator remoteIP;
1c21f389 1621 bool pierceDontQuery=false;
c1d73d94 1622 bool sendRDQuery=false;
376effcf 1623 boost::optional<Netmask> ednsmask;
263f6a5a 1624 LWResult lwr;
6dfff36f
RG
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) {
2189085d 1630 LOG(prefix<<qname<<": Domain is out-of-band"<<endl);
9fc36e90 1631 d_wasOutOfBand = doOOBResolve(qname, qtype, lwr.d_records, depth, lwr.d_rcode);
4957a608
BH
1632 lwr.d_tcbit=false;
1633 lwr.d_aabit=true;
6dfff36f
RG
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 }
5605c067
BH
1643 }
1644 else {
6dfff36f 1645 /* if tns is empty, retrieveAddressesForNS() knows we have hardcoded servers (i.e. "forwards") */
26ca3513 1646 remoteIPs = retrieveAddressesForNS(prefix, qname, tns, depth, beenthere, rnameservers, nameservers, sendRDQuery, pierceDontQuery, flawedNSSet);
4957a608
BH
1647
1648 if(remoteIPs.empty()) {
2189085d 1649 LOG(prefix<<qname<<": Failed to get IP for NS "<<*tns<<", trying next if available"<<endl);
4957a608
BH
1650 flawedNSSet=true;
1651 continue;
1652 }
1653 else {
b8470add 1654 bool hitPolicy{false};
2189085d 1655 LOG(prefix<<qname<<": Resolved '"<<auth<<"' NS "<<*tns<<" to: ");
26ca3513
RG
1656 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
1657 if(remoteIP != remoteIPs.cbegin()) {
77499b05
BH
1658 LOG(", ");
1659 }
1660 LOG(remoteIP->toString());
69cbdef9 1661 if(nameserverIPBlockedByRPZ(luaconfsLocal->dfe, *remoteIP)) {
26ca3513 1662 hitPolicy = true;
b8470add 1663 }
4957a608 1664 }
77499b05 1665 LOG(endl);
b8470add
PL
1666 if (hitPolicy) //implies d_wantsRPZ
1667 return -2;
4957a608
BH
1668 }
1669
26ca3513 1670 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
2189085d 1671 LOG(prefix<<qname<<": Trying IP "<< remoteIP->toStringWithPort() <<", asking '"<<qname<<"|"<<qtype.getName()<<"'"<<endl);
6dfff36f 1672
26ca3513 1673 if (throttledOrBlocked(prefix, *remoteIP, qname, qtype, pierceDontQuery)) {
4957a608
BH
1674 continue;
1675 }
9de3e034 1676
6dfff36f
RG
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 }
710af846 1685
6dfff36f
RG
1686 if (!gotAnswer) {
1687 continue;
1688 }
352b4183 1689
6dfff36f 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);
92011b8f 1691
6dfff36f
RG
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';
710af846 1697
6dfff36f 1698 t_sstorage.nsSpeeds[*tns].submit(*remoteIP, lwr.d_usec, &d_now);
628e2c7b 1699
6dfff36f
RG
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;
4957a608 1704 }
6dfff36f
RG
1705 if (gotNewServers) {
1706 break;
4957a608 1707 }
6dfff36f
RG
1708 /* was lame */
1709 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100);
4957a608 1710 }
aadceba8 1711
6dfff36f
RG
1712 if (gotNewServers) {
1713 break;
4957a608 1714 }
620db2c8 1715
6dfff36f
RG
1716 if(remoteIP == remoteIPs.cend()) // we tried all IP addresses, none worked
1717 continue;
620db2c8 1718
86c152f2
BH
1719 }
1720 }
86c152f2 1721 }
ac539791 1722 return -1;
86c152f2
BH
1723}
1724
e9f9b8ec
RG
1725boost::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
9065eb05 1747 if(s_ednsdomains.check(dn) || s_ednssubnets.match(rem)) {
e9f9b8ec
RG
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}
bd53ea9d 1755
9065eb05
RG
1756void 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
8ce79a22 1770// used by PowerDNSLua - note that this neglects to add the packet count & statistics back to pdns_ercursor.cc
a3e7b735 1771int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<DNSRecord>& ret)
bd53ea9d
PD
1772{
1773 struct timeval now;
1774 gettimeofday(&now, 0);
710af846 1775
bd53ea9d 1776 SyncRes sr(now);
a3e7b735 1777 int res = sr.beginResolve(qname, QType(qtype), qclass, ret);
e325f20c 1778
bd53ea9d
PD
1779 return res;
1780}
30ee601a
RG
1781
1782#include "validate-recursor.hh"
1783
1784int SyncRes::getRootNS(struct timeval now, asyncresolve_t asyncCallback) {
1785 SyncRes sr(now);
1786 sr.setDoEDNS0(true);
0b29b9c5 1787 sr.setUpdatingRootNS();
30ee601a
RG
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(PDNSException& e)
1804 {
1805 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
1806 }
1807
1808 catch(std::exception& e)
1809 {
1810 L<<Logger::Error<<"Failed to update . records, got an exception: "<<e.what()<<endl;
1811 }
1812
1813 catch(...)
1814 {
1815 L<<Logger::Error<<"Failed to update . records, got an exception"<<endl;
1816 }
1817 if(!res) {
1818 L<<Logger::Notice<<"Refreshed . records"<<endl;
1819 }
1820 else
1821 L<<Logger::Error<<"Failed to update . records, RCODE="<<res<<endl;
1822 return res;
1823}