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