]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/syncres.cc
Merge pull request #7064 from rgacogne/dnsdist-tls-accept-leak-smart
[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 35#include "syncres.hh"
1e332f68 36#include "dnsseckeeper.hh"
4d2be65d 37#include "validate-recursor.hh"
6dfff36f 38
a712cb56 39thread_local SyncRes::ThreadLocalStorage SyncRes::t_sstorage;
be9078b3 40thread_local std::unique_ptr<addrringbuf_t> t_timeouts;
bb4bdbaf 41
3337c2f7
RG
42std::unordered_set<DNSName> SyncRes::s_delegationOnly;
43std::unique_ptr<NetmaskGroup> SyncRes::s_dontQuery{nullptr};
2fe3354d
CH
44NetmaskGroup SyncRes::s_ednslocalsubnets;
45NetmaskGroup SyncRes::s_ednsremotesubnets;
3337c2f7 46SuffixMatchNode SyncRes::s_ednsdomains;
8a3a3822 47EDNSSubnetOpts SyncRes::s_ecsScopeZero;
3337c2f7
RG
48string SyncRes::s_serverID;
49SyncRes::LogMode SyncRes::s_lm;
50
a9af3782 51unsigned int SyncRes::s_maxnegttl;
c3e753c7 52unsigned int SyncRes::s_maxcachettl;
3337c2f7
RG
53unsigned int SyncRes::s_maxqperq;
54unsigned int SyncRes::s_maxtotusec;
55unsigned int SyncRes::s_maxdepth;
56unsigned int SyncRes::s_minimumTTL;
1051f8a9
BH
57unsigned int SyncRes::s_packetcachettl;
58unsigned int SyncRes::s_packetcacheservfailttl;
628e2c7b
PA
59unsigned int SyncRes::s_serverdownmaxfails;
60unsigned int SyncRes::s_serverdownthrottletime;
e9a628a2 61std::atomic<uint64_t> SyncRes::s_authzonequeries;
aebb81e4 62std::atomic<uint64_t> SyncRes::s_queries;
63std::atomic<uint64_t> SyncRes::s_outgoingtimeouts;
64std::atomic<uint64_t> SyncRes::s_outgoing4timeouts;
65std::atomic<uint64_t> SyncRes::s_outgoing6timeouts;
66std::atomic<uint64_t> SyncRes::s_outqueries;
67std::atomic<uint64_t> SyncRes::s_tcpoutqueries;
68std::atomic<uint64_t> SyncRes::s_throttledqueries;
69std::atomic<uint64_t> SyncRes::s_dontqueries;
70std::atomic<uint64_t> SyncRes::s_nodelegated;
71std::atomic<uint64_t> SyncRes::s_unreachables;
d6923beb 72std::atomic<uint64_t> SyncRes::s_ecsqueries;
73std::atomic<uint64_t> SyncRes::s_ecsresponses;
e9f9b8ec
RG
74uint8_t SyncRes::s_ecsipv4limit;
75uint8_t SyncRes::s_ecsipv6limit;
996c89cc 76bool SyncRes::s_doIPv6;
1051f8a9 77bool SyncRes::s_nopacketcache;
01402d56 78bool SyncRes::s_rootNXTrust;
3337c2f7 79bool SyncRes::s_noEDNS;
c836dc19 80
e6a9dde5 81#define LOG(x) if(d_lm == Log) { g_log <<Logger::Warning << x; } else if(d_lm == Store) { d_trace << x; }
728485ca 82
69cbdef9 83static void accountAuthLatency(int usec, int family)
11adfdd3 84{
7b75810e 85 if(family == AF_INET) {
86 if(usec < 1000)
87 g_stats.auth4Answers0_1++;
88 else if(usec < 10000)
89 g_stats.auth4Answers1_10++;
90 else if(usec < 100000)
91 g_stats.auth4Answers10_100++;
92 else if(usec < 1000000)
93 g_stats.auth4Answers100_1000++;
94 else
95 g_stats.auth4AnswersSlow++;
96 } else {
97 if(usec < 1000)
98 g_stats.auth6Answers0_1++;
99 else if(usec < 10000)
100 g_stats.auth6Answers1_10++;
101 else if(usec < 100000)
102 g_stats.auth6Answers10_100++;
103 else if(usec < 1000000)
104 g_stats.auth6Answers100_1000++;
105 else
106 g_stats.auth6AnswersSlow++;
107 }
108
11adfdd3 109}
110
4465e941 111
14d9aade 112SyncRes::SyncRes(const struct timeval& now) : d_authzonequeries(0), d_outqueries(0), d_tcpoutqueries(0), d_throttledqueries(0), d_timeouts(0), d_unreachables(0),
30ee601a 113 d_totUsec(0), d_now(now),
0b29b9c5 114 d_cacheonly(false), d_doDNSSEC(false), d_doEDNS0(false), d_lm(s_lm)
232f0877 115
ac0e821b 116{
ac0e821b
BH
117}
118
728485ca 119/** everything begins here - this is the entry point just after receiving a packet */
e325f20c 120int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSRecord>&ret)
728485ca 121{
4d2be65d 122 vState state = Indeterminate;
c836dc19 123 s_queries++;
3762e821 124 d_wasVariable=false;
9fc36e90 125 d_wasOutOfBand=false;
710af846 126
4d2be65d 127 if (doSpecialNamesResolve(qname, qtype, qclass, ret)) {
d04ac108 128 d_queryValidationState = Insecure; // this could fool our stats into thinking a validation took place
129 return 0; // so do check before updating counters (we do now)
4d2be65d 130 }
db50a7f4 131
1f03b691 132 if( (qtype.getCode() == QType::AXFR) || (qtype.getCode() == QType::IXFR) || (qtype.getCode() == QType::RRSIG) || (qtype.getCode() == QType::NSEC3))
693dbe65 133 return -1;
710af846 134
db50a7f4
PL
135 if(qclass==QClass::ANY)
136 qclass=QClass::IN;
137 else if(qclass!=QClass::IN)
138 return -1;
8171ab83 139
db50a7f4 140 set<GetBestNSAnswer> beenthere;
51b6b728 141 int res=doResolve(qname, qtype, ret, 0, beenthere, state);
4d2be65d 142 d_queryValidationState = state;
0c43f455 143
e1636f82 144 if (shouldValidate()) {
3b54c577 145 if (d_queryValidationState != Indeterminate) {
146 g_stats.dnssecValidations++;
147 }
0c43f455
RG
148 increaseDNSSECStateCounter(d_queryValidationState);
149 }
150
db50a7f4
PL
151 return res;
152}
153
154/*! Handles all special, built-in names
155 * Fills ret with an answer and returns true if it handled the query.
156 *
d03c1b70 157 * Handles the following queries (and their ANY variants):
db50a7f4
PL
158 *
159 * - localhost. IN A
160 * - localhost. IN AAAA
161 * - 1.0.0.127.in-addr.arpa. IN PTR
162 * - 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
163 * - version.bind. CH TXT
164 * - version.pdns. CH TXT
165 * - id.server. CH TXT
db50a7f4 166 */
6dfff36f 167bool SyncRes::doSpecialNamesResolve(const DNSName &qname, const QType &qtype, const uint16_t qclass, vector<DNSRecord> &ret)
db50a7f4
PL
168{
169 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."),
170 localhost("localhost."), versionbind("version.bind."), idserver("id.server."), versionpdns("version.pdns.");
171
172 bool handled = false;
d03c1b70 173 vector<pair<QType::typeenum, string> > answers;
db50a7f4 174
d03c1b70
PL
175 if ((qname == arpa || qname == ip6_arpa) &&
176 qclass == QClass::IN) {
db50a7f4 177 handled = true;
d03c1b70
PL
178 if (qtype == QType::PTR || qtype == QType::ANY)
179 answers.push_back({QType::PTR, "localhost."});
db50a7f4
PL
180 }
181
d03c1b70
PL
182 if (qname == localhost &&
183 qclass == QClass::IN) {
db50a7f4 184 handled = true;
d03c1b70
PL
185 if (qtype == QType::A || qtype == QType::ANY)
186 answers.push_back({QType::A, "127.0.0.1"});
187 if (qtype == QType::AAAA || qtype == QType::ANY)
188 answers.push_back({QType::AAAA, "::1"});
db50a7f4
PL
189 }
190
d03c1b70
PL
191 if ((qname == versionbind || qname == idserver || qname == versionpdns) &&
192 qclass == QClass::CHAOS) {
db50a7f4 193 handled = true;
d03c1b70
PL
194 if (qtype == QType::TXT || qtype == QType::ANY) {
195 if(qname == versionbind || qname == versionpdns)
196 answers.push_back({QType::TXT, "\""+::arg()["version-string"]+"\""});
950626be 197 else if (s_serverID != "disabled")
d03c1b70
PL
198 answers.push_back({QType::TXT, "\""+s_serverID+"\""});
199 }
31ad43ab
BH
200 }
201
d03c1b70 202 if (handled && !answers.empty()) {
a9af3782 203 ret.clear();
db50a7f4
PL
204 d_wasOutOfBand=true;
205
e325f20c 206 DNSRecord dr;
db50a7f4 207 dr.d_name = qname;
e693ff5a 208 dr.d_place = DNSResourceRecord::ANSWER;
db50a7f4
PL
209 dr.d_class = qclass;
210 dr.d_ttl = 86400;
d03c1b70
PL
211 for (const auto& ans : answers) {
212 dr.d_type = ans.first;
6177a176 213 dr.d_content = DNSRecordContent::mastermake(ans.first, qclass, ans.second);
d03c1b70
PL
214 ret.push_back(dr);
215 }
a9af3782 216 }
710af846 217
db50a7f4 218 return handled;
728485ca 219}
afbe2787 220
db50a7f4 221
ab5c053d 222//! This is the 'out of band resolver', in other words, the authoritative server
3337c2f7 223void SyncRes::AuthDomain::addSOA(std::vector<DNSRecord>& records) const
e93c956b 224{
3337c2f7
RG
225 SyncRes::AuthDomain::records_t::const_iterator ziter = d_records.find(boost::make_tuple(getName(), QType::SOA));
226 if (ziter != d_records.end()) {
227 DNSRecord dr = *ziter;
228 dr.d_place = DNSResourceRecord::AUTHORITY;
229 records.push_back(dr);
5605c067 230 }
3337c2f7
RG
231 else {
232 // cerr<<qname<<": can't find SOA record '"<<getName()<<"' in our zone!"<<endl;
233 }
234}
5605c067 235
3337c2f7
RG
236int SyncRes::AuthDomain::getRecords(const DNSName& qname, uint16_t qtype, std::vector<DNSRecord>& records) const
237{
238 int result = RCode::NoError;
239 records.clear();
5605c067 240
3337c2f7
RG
241 // partial lookup
242 std::pair<records_t::const_iterator,records_t::const_iterator> range = d_records.equal_range(tie(qname));
243
244 SyncRes::AuthDomain::records_t::const_iterator ziter;
245 bool somedata = false;
246
247 for(ziter = range.first; ziter != range.second; ++ziter) {
248 somedata = true;
249
250 if(qtype == QType::ANY || ziter->d_type == qtype || ziter->d_type == QType::CNAME) {
251 // let rest of nameserver do the legwork on this one
252 records.push_back(*ziter);
253 }
254 else if (ziter->d_type == QType::NS && ziter->d_name.countLabels() > getName().countLabels()) {
255 // we hit a delegation point!
256 DNSRecord dr = *ziter;
39eb8051 257 dr.d_place=DNSResourceRecord::AUTHORITY;
3337c2f7 258 records.push_back(dr);
39eb8051 259 }
5605c067 260 }
3337c2f7
RG
261
262 if (!records.empty()) {
263 /* We have found an exact match, we're done */
264 // cerr<<qname<<": exact match in zone '"<<getName()<<"'"<<endl;
265 return result;
5605c067 266 }
3337c2f7
RG
267
268 if (somedata) {
269 /* We have records for that name, but not of the wanted qtype */
270 // cerr<<qname<<": found record in '"<<getName()<<"', but nothing of the right type, sending SOA"<<endl;
271 addSOA(records);
272
273 return result;
9e9844e2 274 }
5605c067 275
3337c2f7 276 // cerr<<qname<<": nothing found so far in '"<<getName()<<"', trying wildcards"<<endl;
c5c066bf 277 DNSName wcarddomain(qname);
3337c2f7
RG
278 while(wcarddomain != getName() && wcarddomain.chopOff()) {
279 // cerr<<qname<<": trying '*."<<wcarddomain<<"' in "<<getName()<<endl;
280 range = d_records.equal_range(boost::make_tuple(g_wildcarddnsname + wcarddomain));
281 if (range.first==range.second)
0d1e259a
BH
282 continue;
283
3337c2f7
RG
284 for(ziter = range.first; ziter != range.second; ++ziter) {
285 DNSRecord dr = *ziter;
0f05b02b 286 // if we hit a CNAME, just answer that - rest of recursor will do the needful & follow
3337c2f7 287 if(dr.d_type == qtype || qtype == QType::ANY || dr.d_type == QType::CNAME) {
e325f20c 288 dr.d_name = qname;
3337c2f7
RG
289 dr.d_place = DNSResourceRecord::ANSWER;
290 records.push_back(dr);
0d1e259a
BH
291 }
292 }
3337c2f7
RG
293
294 if (records.empty()) {
295 addSOA(records);
296 }
297
298 // cerr<<qname<<": in '"<<getName()<<"', had wildcard match on '*."<<wcarddomain<<"'"<<endl;
299 return result;
0d1e259a
BH
300 }
301
3337c2f7 302 /* Nothing for this name, no wildcard, let's see if there is some NS */
c5c066bf 303 DNSName nsdomain(qname);
3337c2f7
RG
304 while (nsdomain.chopOff() && nsdomain != getName()) {
305 range = d_records.equal_range(boost::make_tuple(nsdomain,QType::NS));
306 if(range.first == range.second)
5605c067
BH
307 continue;
308
3337c2f7
RG
309 for(ziter = range.first; ziter != range.second; ++ziter) {
310 DNSRecord dr = *ziter;
311 dr.d_place = DNSResourceRecord::AUTHORITY;
312 records.push_back(dr);
5605c067
BH
313 }
314 }
3337c2f7
RG
315
316 if(records.empty()) {
317 // cerr<<qname<<": no NS match in zone '"<<getName()<<"' either, handing out SOA"<<endl;
318 addSOA(records);
319 result = RCode::NXDomain;
5605c067 320 }
5605c067 321
3337c2f7
RG
322 return result;
323}
324
f7b8cffa 325bool SyncRes::doOOBResolve(const AuthDomain& domain, const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int& res)
3337c2f7 326{
f7b8cffa 327 d_authzonequeries++;
e9a628a2 328 s_authzonequeries++;
f7b8cffa 329
3337c2f7 330 res = domain.getRecords(qname, qtype.getCode(), ret);
9e9844e2 331 return true;
e93c956b
BH
332}
333
3337c2f7
RG
334bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int& res)
335{
336 string prefix;
337 if(doLog()) {
338 prefix=d_prefix;
339 prefix.append(depth, ' ');
340 }
341
342 DNSName authdomain(qname);
343 domainmap_t::const_iterator iter=getBestAuthZone(&authdomain);
344 if(iter==t_sstorage.domainmap->end() || !iter->second.isAuth()) {
345 LOG(prefix<<qname<<": auth storage has no zone for this query!"<<endl);
346 return false;
347 }
348
349 LOG(prefix<<qname<<": auth storage has data, zone='"<<authdomain<<"'"<<endl);
350 return doOOBResolve(iter->second, qname, qtype, ret, res);
351}
352
ff1872cf
BH
353void SyncRes::doEDNSDumpAndClose(int fd)
354{
355 FILE* fp=fdopen(fd, "w");
a82f68f0
RG
356 if (!fp) {
357 return;
358 }
ff1872cf 359 fprintf(fp,"IP Address\tMode\tMode last updated at\n");
a712cb56 360 for(const auto& eds : t_sstorage.ednsstatus) {
57769f13 361 fprintf(fp, "%s\t%d\t%s", eds.first.toString().c_str(), (int)eds.second.mode, ctime(&eds.second.modeSetAt));
ff1872cf 362 }
bb4bdbaf 363
ff1872cf
BH
364 fclose(fp);
365}
366
9065eb05
RG
367uint64_t SyncRes::doDumpNSSpeeds(int fd)
368{
369 FILE* fp=fdopen(dup(fd), "w");
370 if(!fp)
371 return 0;
372 fprintf(fp, "; nsspeed dump from thread follows\n;\n");
373 uint64_t count=0;
374
a712cb56 375 for(const auto& i : t_sstorage.nsSpeeds)
9065eb05
RG
376 {
377 count++;
a2d65f83 378
379 // an <empty> can appear hear in case of authoritative (hosted) zones
380 fprintf(fp, "%s -> ", i.first.toLogString().c_str());
9065eb05
RG
381 for(const auto& j : i.second.d_collection)
382 {
383 // typedef vector<pair<ComboAddress, DecayingEwma> > collection_t;
384 fprintf(fp, "%s/%f ", j.first.toString().c_str(), j.second.peek());
385 }
386 fprintf(fp, "\n");
387 }
388 fclose(fp);
389 return count;
390}
391
c1e20fba 392uint64_t SyncRes::doDumpThrottleMap(int fd)
393{
394 FILE* fp=fdopen(dup(fd), "w");
395 if(!fp)
396 return 0;
397 fprintf(fp, "; throttle map dump follows\n");
96e2f64f 398 fprintf(fp, "; remote IP\tqname\tqtype\tcount\tttd\n");
c1e20fba 399 uint64_t count=0;
400
96e2f64f 401 const auto& throttleMap = t_sstorage.throttle.getThrottleMap();
402 for(const auto& i : throttleMap)
c1e20fba 403 {
404 count++;
96e2f64f 405 // remote IP, dns name, qtype, count, ttd
bca7b789 406 fprintf(fp, "%s\t%s\t%d\t%u\t%s", i.first.get<0>().toString().c_str(), i.first.get<1>().toLogString().c_str(), i.first.get<2>(), i.second.count, ctime(&i.second.ttd));
c1e20fba 407 }
408 fclose(fp);
409 return count;
410}
411
9d534f2a 412/* so here is the story. First we complete the full resolution process for a domain name. And only THEN do we decide
413 to also do DNSSEC validation, which leads to new queries. To make this simple, we *always* ask for DNSSEC records
414 so that if there are RRSIGs for a name, we'll have them.
415
416 However, some hosts simply can't answer questions which ask for DNSSEC. This can manifest itself as:
417 * No answer
418 * FormErr
419 * Nonsense answer
420
421 The cause of "No answer" may be fragmentation, and it is tempting to probe if smaller answers would get through.
422 Another cause of "No answer" may simply be a network condition.
423 Nonsense answers are a clearer indication this host won't be able to do DNSSEC evah.
424
425 Previous implementations have suffered from turning off DNSSEC questions for an authoritative server based on timeouts.
426 A clever idea is to only turn off DNSSEC if we know a domain isn't signed anyhow. The problem with that really
427 clever idea however is that at this point in PowerDNS, we may simply not know that yet. All the DNSSEC thinking happens
428 elsewhere. It may not have happened yet.
429
430 For now this means we can't be clever, but will turn off DNSSEC if you reply with FormError or gibberish.
431*/
432
deca7d8f 433int 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, bool* chained) const
81883dcc
BH
434{
435 /* what is your QUEST?
57769f13 436 the goal is to get as many remotes as possible on the highest level of EDNS support
81883dcc
BH
437 The levels are:
438
81883dcc 439 0) UNKNOWN Unknown state
57769f13 440 1) EDNS: Honors EDNS0
441 2) EDNSIGNORANT: Ignores EDNS0, gives replies without EDNS0
269ac73d 442 3) NOEDNS: Generates FORMERR on EDNS queries
81883dcc
BH
443
444 Everybody starts out assumed to be '0'.
57769f13 445 If '0', send out EDNS0
446 If you FORMERR us, go to '3',
447 If no EDNS in response, go to '2'
448 If '1', send out EDNS0
449 If FORMERR, downgrade to 3
450 If '2', keep on including EDNS0, see what happens
81883dcc 451 Same behaviour as 0
57769f13 452 If '3', send bare queries
81883dcc
BH
453 */
454
bb4bdbaf 455 SyncRes::EDNSStatus* ednsstatus;
a712cb56 456 ednsstatus = &t_sstorage.ednsstatus[ip]; // does this include port? YES
81883dcc 457
bb4bdbaf
BH
458 if(ednsstatus->modeSetAt && ednsstatus->modeSetAt + 3600 < d_now.tv_sec) {
459 *ednsstatus=SyncRes::EDNSStatus();
77499b05 460 // cerr<<"Resetting EDNS Status for "<<ip.toString()<<endl);
81883dcc
BH
461 }
462
bb4bdbaf 463 SyncRes::EDNSStatus::EDNSMode& mode=ednsstatus->mode;
81883dcc 464 SyncRes::EDNSStatus::EDNSMode oldmode = mode;
fe61f5d8 465 int EDNSLevel = 0;
4898a348
RG
466 auto luaconfsLocal = g_luaconfs.getLocal();
467 ResolveContext ctx;
468#ifdef HAVE_PROTOBUF
469 ctx.d_initialRequestId = d_initialRequestId;
470#endif
81883dcc
BH
471
472 int ret;
ff1872cf 473 for(int tries = 0; tries < 3; ++tries) {
e325f20c 474 // cerr<<"Remote '"<<ip.toString()<<"' currently in mode "<<mode<<endl;
57769f13 475
9d534f2a 476 if(mode==EDNSStatus::NOEDNS) {
81883dcc 477 g_stats.noEdnsOutQueries++;
9d534f2a 478 EDNSLevel = 0; // level != mode
81883dcc 479 }
9d534f2a 480 else if(ednsMANDATORY || mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSOK || mode==EDNSStatus::EDNSIGNORANT)
481 EDNSLevel = 1;
30ee601a 482
c1c29961
PL
483 DNSName sendQname(domain);
484 if (g_lowercaseOutgoing)
485 sendQname.makeUsLowerCase();
486
30ee601a 487 if (d_asyncResolve) {
0bd2e252 488 ret = d_asyncResolve(ip, sendQname, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, res, chained);
30ee601a
RG
489 }
490 else {
0bd2e252 491 ret=asyncresolve(ip, sendQname, type, doTCP, sendRDQuery, EDNSLevel, now, srcmask, ctx, d_outgoingProtobufServer, luaconfsLocal->outgoingProtobufExportConfig.exportTypes, res, chained);
30ee601a 492 }
9d534f2a 493 if(ret < 0) {
494 return ret; // transport error, nothing to learn here
495 }
57769f13 496
9d534f2a 497 if(ret == 0) { // timeout, not doing anything with it now
81883dcc
BH
498 return ret;
499 }
57769f13 500 else if(mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSOK || mode == EDNSStatus::EDNSIGNORANT ) {
269ac73d 501 if(res->d_validpacket && res->d_rcode == RCode::FormErr) {
2189085d 502 // cerr<<"Downgrading to NOEDNS because of "<<RCode::to_s(res->d_rcode)<<" for query to "<<ip.toString()<<" for '"<<domain<<"'"<<endl;
57769f13 503 mode = EDNSStatus::NOEDNS;
4957a608 504 continue;
81883dcc 505 }
81883dcc 506 else if(!res->d_haveEDNS) {
4957a608
BH
507 if(mode != EDNSStatus::EDNSIGNORANT) {
508 mode = EDNSStatus::EDNSIGNORANT;
269ac73d 509 // cerr<<"We find that "<<ip.toString()<<" is an EDNS-ignorer for '"<<domain<<"', moving to mode 2"<<endl;
57769f13 510 }
81883dcc 511 }
57769f13 512 else {
513 mode = EDNSStatus::EDNSOK;
e325f20c 514 // cerr<<"We find that "<<ip.toString()<<" is EDNS OK!"<<endl;
81883dcc 515 }
57769f13 516
81883dcc 517 }
12ce523e 518 if(oldmode != mode || !ednsstatus->modeSetAt)
bb4bdbaf 519 ednsstatus->modeSetAt=d_now.tv_sec;
e325f20c 520 // cerr<<"Result: ret="<<ret<<", EDNS-level: "<<EDNSLevel<<", haveEDNS: "<<res->d_haveEDNS<<", new mode: "<<mode<<endl;
81883dcc
BH
521 return ret;
522 }
523 return ret;
524}
525
b88526ce
PL
526/*! This function will check the cache and go out to the internet if the answer is not in cache
527 *
528 * \param qname The name we need an answer for
529 * \param qtype
530 * \param ret The vector of DNSRecords we need to fill with the answers
531 * \param depth The recursion depth we are in
532 * \param beenthere
533 * \return DNS RCODE or -1 (Error) or -2 (RPZ hit)
534 */
51b6b728 535int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, set<GetBestNSAnswer>& beenthere, vState& state)
afbe2787 536{
ded77b10 537 string prefix;
77499b05 538 if(doLog()) {
ded77b10
BH
539 prefix=d_prefix;
540 prefix.append(depth, ' ');
541 }
b8470add 542
4d2be65d
RG
543 LOG(prefix<<qname<<": Wants "<< (d_doDNSSEC ? "" : "NO ") << "DNSSEC processing, "<<(d_requireAuthData ? "" : "NO ")<<"auth data in query for "<<qtype.getName()<<endl);
544
545 state = Indeterminate;
710af846 546
7c3398aa
RG
547 if(s_maxdepth && depth > s_maxdepth)
548 throw ImmediateServFailException("More than "+std::to_string(s_maxdepth)+" (max-recursion-depth) levels of recursion needed while resolving "+qname.toLogString());
549
f4df5e89 550 int res=0;
b88526ce
PL
551
552 // This is a difficult way of expressing "this is a normal query", i.e. not getRootNS.
0b29b9c5 553 if(!(d_updatingRootNS && qtype.getCode()==QType::NS && qname.isRoot())) {
115d07ad 554 if(d_cacheonly) { // very limited OOB support
263f6a5a 555 LWResult lwr;
2189085d 556 LOG(prefix<<qname<<": Recursion not requested for '"<<qname<<"|"<<qtype.getName()<<"', peeking at auth/forward zones"<<endl);
c5c066bf 557 DNSName authname(qname);
115d07ad 558 domainmap_t::const_iterator iter=getBestAuthZone(&authname);
a712cb56 559 if(iter != t_sstorage.domainmap->end()) {
3337c2f7 560 if(iter->second.isAuth()) {
4957a608 561 ret.clear();
9fc36e90 562 d_wasOutOfBand = doOOBResolve(qname, qtype, ret, depth, res);
4957a608
BH
563 return res;
564 }
565 else {
3337c2f7 566 const vector<ComboAddress>& servers = iter->second.d_servers;
4957a608 567 const ComboAddress remoteIP = servers.front();
2189085d 568 LOG(prefix<<qname<<": forwarding query to hardcoded nameserver '"<< remoteIP.toStringWithPort()<<"' for zone '"<<authname<<"'"<<endl);
4957a608 569
6148fa97 570 boost::optional<Netmask> nm;
deca7d8f
RG
571 bool chained = false;
572 res=asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, qtype.getCode(), false, false, &d_now, nm, &lwr, &chained);
fabef7e0 573
574 d_totUsec += lwr.d_usec;
575 accountAuthLatency(lwr.d_usec, remoteIP.sin4.sin_family);
576
4957a608 577 // filter out the good stuff from lwr.result()
ab33a095
RG
578 if (res == 1) {
579 for(const auto& rec : lwr.d_records) {
580 if(rec.d_place == DNSResourceRecord::ANSWER)
581 ret.push_back(rec);
582 }
583 return 0;
584 }
585 else {
586 return RCode::ServFail;
4957a608 587 }
4957a608 588 }
115d07ad
BH
589 }
590 }
591
e1636f82
RG
592 DNSName authname(qname);
593 bool wasForwardedOrAuthZone = false;
594 bool wasAuthZone = false;
ad797d94 595 bool wasForwardRecurse = false;
e1636f82
RG
596 domainmap_t::const_iterator iter = getBestAuthZone(&authname);
597 if(iter != t_sstorage.domainmap->end()) {
ad797d94 598 const auto& domain = iter->second;
e1636f82 599 wasForwardedOrAuthZone = true;
ad797d94
RG
600
601 if (domain.isAuth()) {
e1636f82 602 wasAuthZone = true;
ad797d94
RG
603 } else if (domain.shouldRecurse()) {
604 wasForwardRecurse = true;
e1636f82
RG
605 }
606 }
607
ad797d94 608 if(!d_skipCNAMECheck && doCNAMECacheCheck(qname, qtype, ret, depth, res, state, wasAuthZone, wasForwardRecurse)) { // will reroute us if needed
e1636f82 609 d_wasOutOfBand = wasAuthZone;
c836dc19 610 return res;
e1636f82 611 }
710af846 612
ad797d94 613 if(doCacheCheck(qname, authname, wasForwardedOrAuthZone, wasAuthZone, wasForwardRecurse, qtype, ret, depth, res, state)) {
e1636f82
RG
614 // we done
615 d_wasOutOfBand = wasAuthZone;
c836dc19 616 return res;
e1636f82 617 }
c836dc19 618 }
afbe2787 619
115d07ad 620 if(d_cacheonly)
c836dc19 621 return 0;
728485ca 622
2189085d 623 LOG(prefix<<qname<<": No cache hit for '"<<qname<<"|"<<qtype.getName()<<"', trying to find an appropriate NS record"<<endl);
710af846 624
c5c066bf 625 DNSName subdomain(qname);
d8049162 626 if(qtype == QType::DS) subdomain.chopOff();
728485ca 627
fa1b87ff 628 NsSet nsset;
7305df82 629 bool flawedNSSet=false;
97df07f8 630
3cef03e9
RG
631 /* we use subdomain here instead of qname because for DS queries we only care about the state of the parent zone */
632 computeZoneCuts(subdomain, g_rootdnsname, depth);
70b3fe7a 633
97df07f8
PD
634 // the two retries allow getBestNSNamesFromCache&co to reprime the root
635 // hints, in case they ever go missing
bdf40704 636 for(int tries=0;tries<2 && nsset.empty();++tries) {
891fbf88 637 subdomain=getBestNSNamesFromCache(subdomain, qtype, nsset, &flawedNSSet, depth, beenthere); // pass beenthere to both occasions
bdf40704
BH
638 }
639
5374b03b 640 state = getValidationStatus(qname, false);
70b3fe7a 641
5374b03b 642 LOG(prefix<<qname<<": initial validation status for "<<qname<<" is "<<vStates[state]<<endl);
4d2be65d 643
51b6b728 644 if(!(res=doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, ret, depth, beenthere, state)))
728485ca 645 return 0;
3ddb9247 646
2189085d 647 LOG(prefix<<qname<<": failed (res="<<res<<")"<<endl);
b8470add
PL
648
649 if (res == -2)
650 return res;
651
20177d1d 652 return res<0 ? RCode::ServFail : res;
afbe2787
BH
653}
654
c2567ad1 655#if 0
a67dd0cf 656// for testing purposes
fdf05fd4
BH
657static bool ipv6First(const ComboAddress& a, const ComboAddress& b)
658{
659 return !(a.sin4.sin_family < a.sin4.sin_family);
660}
c2567ad1 661#endif
fdf05fd4 662
0e4675a9
RG
663struct speedOrderCA
664{
665 speedOrderCA(std::map<ComboAddress,double>& speeds): d_speeds(speeds) {}
666 bool operator()(const ComboAddress& a, const ComboAddress& b) const
667 {
668 return d_speeds[a] < d_speeds[b];
669 }
670 std::map<ComboAddress, double>& d_speeds;
671};
672
21f0f88b 673/** This function explicitly goes out for A or AAAA addresses
996c89cc 674*/
b4c8789a 675vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, unsigned int depth, set<GetBestNSAnswer>& beenthere, bool cacheOnly)
75b49099 676{
e325f20c 677 typedef vector<DNSRecord> res_t;
bfea0d0b 678 res_t res;
75b49099 679
996c89cc
BH
680 typedef vector<ComboAddress> ret_t;
681 ret_t ret;
75b49099 682
d96e88da 683 QType type;
b4c8789a 684 bool oldCacheOnly = d_cacheonly;
24bb9b58 685 bool oldRequireAuthData = d_requireAuthData;
5597f804 686 bool oldValidationRequested = d_DNSSECValidationRequested;
24bb9b58 687 d_requireAuthData = false;
5597f804 688 d_DNSSECValidationRequested = false;
b4c8789a 689 d_cacheonly = cacheOnly;
92011b8f 690
691 for(int j=1; j<2+s_doIPv6; j++)
d96e88da 692 {
76c01aec 693 bool done=false;
76c01aec
PD
694 switch(j) {
695 case 0:
696 type = QType::ANY;
697 break;
698 case 1:
699 type = QType::A;
700 break;
701 case 2:
702 type = QType::AAAA;
703 break;
704 }
d96e88da 705
4d2be65d 706 vState newState = Indeterminate;
51b6b728 707 if(!doResolve(qname, type, res,depth+1, beenthere, newState) && !res.empty()) { // this consults cache, OR goes out
d96e88da 708 for(res_t::const_iterator i=res.begin(); i!= res.end(); ++i) {
e325f20c 709 if(i->d_type == QType::A || i->d_type == QType::AAAA) {
38c2ba02 710 if(auto rec = getRR<ARecordContent>(*i))
e325f20c 711 ret.push_back(rec->getCA(53));
38c2ba02 712 else if(auto aaaarec = getRR<AAAARecordContent>(*i))
dd079764 713 ret.push_back(aaaarec->getCA(53));
92011b8f 714 done=true;
d96e88da 715 }
42724edf 716 }
f4df5e89 717 }
710af846 718 if(done) {
60c9a54f 719 if(j==1 && s_doIPv6) { // we got an A record, see if we have some AAAA lying around
e325f20c 720 vector<DNSRecord> cset;
2fe3354d 721 if(t_RC->get(d_now.tv_sec, qname, QType(QType::AAAA), false, &cset, d_cacheRemote) > 0) {
e325f20c 722 for(auto k=cset.cbegin();k!=cset.cend();++k) {
723 if(k->d_ttl > (unsigned int)d_now.tv_sec ) {
38c2ba02 724 if (auto drc = getRR<AAAARecordContent>(*k)) {
ba3c54cb
RG
725 ComboAddress ca=drc->getCA(53);
726 ret.push_back(ca);
727 }
60c9a54f 728 }
729 }
730 }
731 }
732 break;
733 }
bfea0d0b 734 }
710af846 735
24bb9b58 736 d_requireAuthData = oldRequireAuthData;
5597f804 737 d_DNSSECValidationRequested = oldValidationRequested;
b4c8789a 738 d_cacheonly = oldCacheOnly;
24bb9b58 739
c767798a
RG
740 /* we need to remove from the nsSpeeds collection the existing IPs
741 for this nameserver that are no longer in the set, even if there
742 is only one or none at all in the current set.
743 */
744 map<ComboAddress, double> speeds;
745 auto& collection = t_sstorage.nsSpeeds[qname].d_collection;
746 for(const auto& val: ret) {
7881a640 747 speeds[val] = collection[val].get(&d_now);
c767798a 748 }
996c89cc 749
c767798a 750 t_sstorage.nsSpeeds[qname].purge(speeds);
996c89cc 751
c767798a 752 if(ret.size() > 1) {
0e4675a9
RG
753 random_shuffle(ret.begin(), ret.end(), dns_random);
754 speedOrderCA so(speeds);
755 stable_sort(ret.begin(), ret.end(), so);
756
757 if(doLog()) {
758 string prefix=d_prefix;
759 prefix.append(depth, ' ');
760 LOG(prefix<<"Nameserver "<<qname<<" IPs: ");
761 bool first = true;
762 for(const auto& addr : ret) {
763 if (first) {
764 first = false;
4957a608 765 }
0e4675a9
RG
766 else {
767 LOG(", ");
768 }
769 LOG((addr.toString())<<"(" << (boost::format("%0.2f") % (speeds[addr]/1000.0)).str() <<"ms)");
996c89cc 770 }
0e4675a9
RG
771 LOG(endl);
772 }
996c89cc 773 }
fdf05fd4 774
728485ca 775 return ret;
75b49099
BH
776}
777
7c3398aa 778void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, vector<DNSRecord>& bestns, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>& beenthere)
86c152f2 779{
c5c066bf
PD
780 string prefix;
781 DNSName subdomain(qname);
77499b05 782 if(doLog()) {
ded77b10
BH
783 prefix=d_prefix;
784 prefix.append(depth, ' ');
785 }
75b49099 786 bestns.clear();
2b1b4054 787 bool brokeloop;
75b49099 788 do {
2b1b4054 789 brokeloop=false;
2189085d 790 LOG(prefix<<qname<<": Checking if we have NS in cache for '"<<subdomain<<"'"<<endl);
e325f20c 791 vector<DNSRecord> ns;
7305df82 792 *flawedNSSet = false;
4d2be65d 793
2fe3354d 794 if(t_RC->get(d_now.tv_sec, subdomain, QType(QType::NS), false, &ns, d_cacheRemote) > 0) {
e325f20c 795 for(auto k=ns.cbegin();k!=ns.cend(); ++k) {
796 if(k->d_ttl > (unsigned int)d_now.tv_sec ) {
797 vector<DNSRecord> aset;
4957a608 798
e325f20c 799 const DNSRecord& dr=*k;
ba3c54cb
RG
800 auto nrr = getRR<NSRecordContent>(dr);
801 if(nrr && (!nrr->getNS().isPartOf(subdomain) || t_RC->get(d_now.tv_sec, nrr->getNS(), s_doIPv6 ? QType(QType::ADDR) : QType(QType::A),
2fe3354d 802 false, doLog() ? &aset : 0, d_cacheRemote) > 5)) {
e325f20c 803 bestns.push_back(dr);
2189085d
PL
804 LOG(prefix<<qname<<": NS (with ip, or non-glue) in cache for '"<<subdomain<<"' -> '"<<nrr->getNS()<<"'"<<endl);
805 LOG(prefix<<qname<<": within bailiwick: "<< nrr->getNS().isPartOf(subdomain));
4957a608 806 if(!aset.empty()) {
e325f20c 807 LOG(", in cache, ttl="<<(unsigned int)(((time_t)aset.begin()->d_ttl- d_now.tv_sec ))<<endl);
4957a608
BH
808 }
809 else {
77499b05 810 LOG(", not in cache / did not look at cache"<<endl);
4957a608
BH
811 }
812 }
813 else {
814 *flawedNSSet=true;
e325f20c 815 LOG(prefix<<qname<<": NS in cache for '"<<subdomain<<"', but needs glue ("<<nrr->getNS()<<") which we miss or is expired"<<endl);
4957a608
BH
816 }
817 }
afbe2787 818 }
4d2be65d 819
75b49099 820 if(!bestns.empty()) {
4957a608 821 GetBestNSAnswer answer;
891fbf88 822 answer.qname=qname;
823 answer.qtype=qtype.getCode();
38c2ba02
RG
824 for(const auto& dr : bestns) {
825 if (auto nsContent = getRR<NSRecordContent>(dr)) {
826 answer.bestns.insert(make_pair(dr.d_name, nsContent->getNS()));
827 }
828 }
891fbf88 829
4957a608 830 if(beenthere.count(answer)) {
2b1b4054 831 brokeloop=true;
2189085d 832 LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' but part of LOOP (already seen "<<answer.qname<<")! Trying less specific NS"<<endl);
e325f20c 833 ;
77499b05
BH
834 if(doLog())
835 for( set<GetBestNSAnswer>::const_iterator j=beenthere.begin();j!=beenthere.end();++j) {
2b1b4054 836 bool neo = !(*j< answer || answer<*j);
2189085d 837 LOG(prefix<<qname<<": beenthere"<<(neo?"*":"")<<": "<<j->qname<<"|"<<DNSRecordContent::NumberToType(j->qtype)<<" ("<<(unsigned int)j->bestns.size()<<")"<<endl);
77499b05 838 }
4957a608
BH
839 bestns.clear();
840 }
841 else {
6576051d 842 beenthere.insert(answer);
2189085d 843 LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' (flawedNSSet="<<*flawedNSSet<<")"<<endl);
4957a608
BH
844 return;
845 }
75b49099 846 }
afbe2787 847 }
2189085d 848 LOG(prefix<<qname<<": no valid/useful NS in cache for '"<<subdomain<<"'"<<endl);
4d2be65d 849
52683ca3 850 if(subdomain.isRoot() && !brokeloop) {
7836f7b4 851 // We lost the root NS records
3ddb9247 852 primeHints();
2189085d 853 LOG(prefix<<qname<<": reprimed the root"<<endl);
0b29b9c5
RG
854 /* let's prevent an infinite loop */
855 if (!d_updatingRootNS) {
856 getRootNS(d_now, d_asyncResolve);
857 }
6576051d 858 }
4d2be65d 859 } while(subdomain.chopOff());
75b49099
BH
860}
861
69cbdef9 862SyncRes::domainmap_t::const_iterator SyncRes::getBestAuthZone(DNSName* qname) const
5605c067
BH
863{
864 SyncRes::domainmap_t::const_iterator ret;
865 do {
a712cb56
RG
866 ret=t_sstorage.domainmap->find(*qname);
867 if(ret!=t_sstorage.domainmap->end())
5605c067 868 break;
c5c066bf 869 }while(qname->chopOff());
5605c067
BH
870 return ret;
871}
288f4aa9 872
7bf26383 873/** doesn't actually do the work, leaves that to getBestNSFromCache */
7c3398aa 874DNSName SyncRes::getBestNSNamesFromCache(const DNSName &qname, const QType& qtype, NsSet& nsset, bool* flawedNSSet, unsigned int depth, set<GetBestNSAnswer>&beenthere)
75b49099 875{
c5c066bf
PD
876 DNSName subdomain(qname);
877 DNSName authdomain(qname);
3ddb9247 878
5605c067 879 domainmap_t::const_iterator iter=getBestAuthZone(&authdomain);
a712cb56 880 if(iter!=t_sstorage.domainmap->end()) {
3337c2f7 881 if( iter->second.isAuth() )
fa1b87ff
PL
882 // this gets picked up in doResolveAt, the empty DNSName, combined with the
883 // empty vector means 'we are auth for this zone'
884 nsset.insert({DNSName(), {{}, false}});
2e5ae2b2 885 else {
fa1b87ff
PL
886 // Again, picked up in doResolveAt. An empty DNSName, combined with a
887 // non-empty vector of ComboAddresses means 'this is a forwarded domain'
6dfff36f 888 // This is actually picked up in retrieveAddressesForNS called from doResolveAt.
3337c2f7 889 nsset.insert({DNSName(), {iter->second.d_servers, iter->second.shouldRecurse() }});
2e5ae2b2 890 }
5605c067
BH
891 return authdomain;
892 }
893
e325f20c 894 vector<DNSRecord> bestns;
891fbf88 895 getBestNSFromCache(subdomain, qtype, bestns, flawedNSSet, depth, beenthere);
75b49099 896
e325f20c 897 for(auto k=bestns.cbegin() ; k != bestns.cend(); ++k) {
fa1b87ff 898 // The actual resolver code will not even look at the ComboAddress or bool
38c2ba02
RG
899 const auto nsContent = getRR<NSRecordContent>(*k);
900 if (nsContent) {
901 nsset.insert({nsContent->getNS(), {{}, false}});
902 if(k==bestns.cbegin())
903 subdomain=k->d_name;
904 }
86c152f2 905 }
75b49099 906 return subdomain;
afbe2787
BH
907}
908
ad797d94 909bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>& ret, unsigned int depth, int &res, vState& state, bool wasAuthZone, bool wasForwardRecurse)
afbe2787 910{
ded77b10 911 string prefix;
77499b05 912 if(doLog()) {
710af846 913 prefix=d_prefix;
ded77b10
BH
914 prefix.append(depth, ' ');
915 }
36f5e3db 916
40de2910 917 if((depth>9 && d_outqueries>10 && d_throttledqueries>5) || depth > 15) {
2189085d 918 LOG(prefix<<qname<<": recursing (CNAME or other indirection) too deep, depth="<<depth<<endl);
c6644fc5
BH
919 res=RCode::ServFail;
920 return true;
921 }
3ddb9247 922
2189085d 923 LOG(prefix<<qname<<": Looking for CNAME cache hit of '"<<qname<<"|CNAME"<<"'"<<endl);
e325f20c 924 vector<DNSRecord> cset;
1f77f479 925 vector<std::shared_ptr<RRSIGRecordContent>> signatures;
2b984251 926 vector<std::shared_ptr<DNSRecord>> authorityRecs;
428f41b7 927 bool wasAuth;
ad797d94
RG
928 /* we don't require auth data for forward-recurse lookups */
929 if(t_RC->get(d_now.tv_sec, qname, QType(QType::CNAME), !wasForwardRecurse && d_requireAuthData, &cset, d_cacheRemote, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &state, &wasAuth) > 0) {
36c5ee42 930
e325f20c 931 for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
c5310862
RG
932 if (j->d_class != QClass::IN) {
933 continue;
934 }
935
e325f20c 936 if(j->d_ttl>(unsigned int) d_now.tv_sec) {
428f41b7 937
e1636f82 938 if (!wasAuthZone && shouldValidate() && wasAuth && state == Indeterminate && d_requireAuthData) {
428f41b7
RG
939 /* This means we couldn't figure out the state when this entry was cached,
940 most likely because we hadn't computed the zone cuts yet. */
aa30ad7e 941 /* make sure they are computed before validating */
f4de85a3
RG
942 DNSName subdomain(qname);
943 /* if we are retrieving a DS, we only care about the state of the parent zone */
944 if(qtype == QType::DS)
945 subdomain.chopOff();
946
947 computeZoneCuts(subdomain, g_rootdnsname, depth);
aa30ad7e 948
142ab370 949 vState recordState = getValidationStatus(qname, false);
787737ae
RG
950 if (recordState == Secure) {
951 LOG(prefix<<qname<<": got Indeterminate state from the CNAME cache, validating.."<<endl);
952 state = SyncRes::validateRecordsWithSigs(depth, qname, QType(QType::CNAME), qname, cset, signatures);
953 if (state != Indeterminate) {
954 LOG(prefix<<qname<<": got Indeterminate state from the CNAME cache, new validation result is "<<vStates[state]<<endl);
2fe3354d 955 t_RC->updateValidationStatus(d_now.tv_sec, qname, QType(QType::CNAME), d_cacheRemote, d_requireAuthData, state);
787737ae
RG
956 }
957 }
428f41b7
RG
958 }
959
4d2be65d 960 LOG(prefix<<qname<<": Found cache CNAME hit for '"<< qname << "|CNAME" <<"' to '"<<j->d_content->getZoneRepresentation()<<"', validation state is "<<vStates[state]<<endl);
428f41b7 961
e325f20c 962 DNSRecord dr=*j;
963 dr.d_ttl-=d_now.tv_sec;
f128d20d 964 ret.reserve(ret.size() + 1 + signatures.size() + authorityRecs.size());
e325f20c 965 ret.push_back(dr);
1f77f479 966
4d2be65d
RG
967 for(const auto& signature : signatures) {
968 DNSRecord sigdr;
969 sigdr.d_type=QType::RRSIG;
970 sigdr.d_name=qname;
971 sigdr.d_ttl=j->d_ttl - d_now.tv_sec;
972 sigdr.d_content=signature;
973 sigdr.d_place=DNSResourceRecord::ANSWER;
974 sigdr.d_class=QClass::IN;
975 ret.push_back(sigdr);
976 }
1f77f479 977
2b984251 978 for(const auto& rec : authorityRecs) {
2010ac95
RG
979 DNSRecord authDR(*rec);
980 authDR.d_ttl=j->d_ttl - d_now.tv_sec;
981 ret.push_back(authDR);
2b984251
RG
982 }
983
f8e7daf8 984 if(qtype != QType::CNAME) { // perhaps they really wanted a CNAME!
4957a608 985 set<GetBestNSAnswer>beenthere;
4d2be65d
RG
986
987 vState cnameState = Indeterminate;
38c2ba02
RG
988 const auto cnameContent = getRR<CNAMERecordContent>(*j);
989 if (cnameContent) {
990 res=doResolve(cnameContent->getTarget(), qtype, ret, depth+1, beenthere, cnameState);
991 LOG(prefix<<qname<<": updating validation state for response to "<<qname<<" from "<<vStates[state]<<" with the state from the CNAME quest: "<<vStates[cnameState]<<endl);
992 updateValidationState(state, cnameState);
993 }
4957a608
BH
994 }
995 else
996 res=0;
4d2be65d 997
4957a608 998 return true;
ac539791
BH
999 }
1000 }
afbe2787 1001 }
2189085d 1002 LOG(prefix<<qname<<": No CNAME cache hit of '"<< qname << "|CNAME" <<"' found"<<endl);
75b49099
BH
1003 return false;
1004}
1005
f984e703 1006namespace {
142ab370
RG
1007struct CacheEntry
1008{
1009 vector<DNSRecord> records;
1010 vector<shared_ptr<RRSIGRecordContent>> signatures;
1011 uint32_t signaturesTTL{std::numeric_limits<uint32_t>::max()};
1012};
1013struct CacheKey
1014{
1015 DNSName name;
1016 uint16_t type;
1017 DNSResourceRecord::Place place;
1018 bool operator<(const CacheKey& rhs) const {
129e658f 1019 return tie(name, type, place) < tie(rhs.name, rhs.type, rhs.place);
142ab370
RG
1020 }
1021};
1022typedef map<CacheKey, CacheEntry> tcache_t;
f984e703 1023}
142ab370
RG
1024
1025static void reapRecordsFromNegCacheEntryForValidation(tcache_t& tcache, const vector<DNSRecord>& records)
1026{
1027 for (const auto& rec : records) {
1028 if (rec.d_type == QType::RRSIG) {
1029 auto rrsig = getRR<RRSIGRecordContent>(rec);
1030 if (rrsig) {
1031 tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signatures.push_back(rrsig);
1032 }
1033 } else {
1034 tcache[{rec.d_name,rec.d_type,rec.d_place}].records.push_back(rec);
1035 }
1036 }
1037}
1038
6909b8c5
PL
1039/*!
1040 * Convience function to push the records from records into ret with a new TTL
1041 *
1042 * \param records DNSRecords that need to go into ret
1043 * \param ttl The new TTL for these records
1044 * \param ret The vector of DNSRecords that should contian the records with the modified TTL
1045 */
1046static void addTTLModifiedRecords(const vector<DNSRecord>& records, const uint32_t ttl, vector<DNSRecord>& ret) {
39ce10b2
PL
1047 for (const auto& rec : records) {
1048 DNSRecord r(rec);
1049 r.d_ttl = ttl;
1050 ret.push_back(r);
1051 }
1052}
1053
28364e4b 1054void SyncRes::computeNegCacheValidationStatus(const NegCache::NegCacheEntry* ne, const DNSName& qname, const QType& qtype, const int res, vState& state, unsigned int depth)
142ab370 1055{
f4de85a3
RG
1056 DNSName subdomain(qname);
1057 /* if we are retrieving a DS, we only care about the state of the parent zone */
1058 if(qtype == QType::DS)
1059 subdomain.chopOff();
1060
1061 computeZoneCuts(subdomain, g_rootdnsname, depth);
142ab370
RG
1062
1063 tcache_t tcache;
28364e4b
RG
1064 reapRecordsFromNegCacheEntryForValidation(tcache, ne->authoritySOA.records);
1065 reapRecordsFromNegCacheEntryForValidation(tcache, ne->authoritySOA.signatures);
1066 reapRecordsFromNegCacheEntryForValidation(tcache, ne->DNSSECRecords.records);
1067 reapRecordsFromNegCacheEntryForValidation(tcache, ne->DNSSECRecords.signatures);
142ab370
RG
1068
1069 for (const auto& entry : tcache) {
1070 // this happens when we did store signatures, but passed on the records themselves
1071 if (entry.second.records.empty()) {
1072 continue;
1073 }
1074
1075 const DNSName& owner = entry.first.name;
1076
1077 vState recordState = getValidationStatus(owner, false);
1078 if (state == Indeterminate) {
1079 state = recordState;
1080 }
1081
1082 if (recordState == Secure) {
f4de85a3
RG
1083 recordState = SyncRes::validateRecordsWithSigs(depth, qname, qtype, owner, entry.second.records, entry.second.signatures);
1084 }
142ab370 1085
f4de85a3
RG
1086 if (recordState != Indeterminate && recordState != state) {
1087 updateValidationState(state, recordState);
1088 if (state != Secure) {
1089 break;
142ab370
RG
1090 }
1091 }
1092 }
1093
1094 if (state == Secure) {
28364e4b 1095 vState neValidationState = ne->d_validationState;
142ab370 1096 dState expectedState = res == RCode::NXDomain ? NXDOMAIN : NXQTYPE;
28364e4b
RG
1097 dState denialState = getDenialValidationState(*ne, state, expectedState, false);
1098 updateDenialValidationState(neValidationState, ne->d_name, state, denialState, expectedState, qtype == QType::DS);
142ab370
RG
1099 }
1100 if (state != Indeterminate) {
1101 /* validation succeeded, let's update the cache entry so we don't have to validate again */
28364e4b 1102 t_sstorage.negcache.updateValidationStatus(ne->d_name, ne->d_qtype, state);
142ab370
RG
1103 }
1104}
e325f20c 1105
ad797d94 1106bool SyncRes::doCacheCheck(const DNSName &qname, const DNSName& authname, bool wasForwardedOrAuthZone, bool wasAuthZone, bool wasForwardRecurse, const QType &qtype, vector<DNSRecord>&ret, unsigned int depth, int &res, vState& state)
75b49099 1107{
fd8bc993 1108 bool giveNegative=false;
710af846 1109
be718669 1110 string prefix;
77499b05 1111 if(doLog()) {
ded77b10
BH
1112 prefix=d_prefix;
1113 prefix.append(depth, ' ');
1114 }
afbe2787 1115
30e9bd93 1116 // 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 1117 DNSName sqname(qname);
288f4aa9 1118 QType sqt(qtype);
092f210a 1119 uint32_t sttl=0;
2189085d 1120 // cout<<"Lookup for '"<<qname<<"|"<<qtype.getName()<<"' -> "<<getLastLabel(qname)<<endl;
4d2be65d 1121 vState cachedState;
28364e4b 1122 const NegCache::NegCacheEntry* ne = nullptr;
64a8b6a1 1123
710af846 1124 if(s_rootNXTrust &&
28364e4b
RG
1125 t_sstorage.negcache.getRootNXTrust(qname, d_now, &ne) &&
1126 ne->d_auth.isRoot() &&
e1636f82 1127 !(wasForwardedOrAuthZone && !authname.isRoot())) { // when forwarding, the root may only neg-cache if it was forwarded to.
28364e4b
RG
1128 sttl = ne->d_ttd - d_now.tv_sec;
1129 LOG(prefix<<qname<<": Entire name '"<<qname<<"', is negatively cached via '"<<ne->d_auth<<"' & '"<<ne->d_name<<"' for another "<<sttl<<" seconds"<<endl);
3ddb9247 1130 res = RCode::NXDomain;
39ce10b2 1131 giveNegative = true;
28364e4b 1132 cachedState = ne->d_validationState;
01402d56 1133 }
28364e4b
RG
1134 else if (t_sstorage.negcache.get(qname, qtype, d_now, &ne) &&
1135 !(wasForwardedOrAuthZone && ne->d_auth != authname)) { // Only the authname nameserver can neg cache entries
b0c164a2
RG
1136
1137 /* If we are looking for a DS, discard NXD if auth == qname
1138 and ask for a specific denial instead */
28364e4b
RG
1139 if (qtype != QType::DS || ne->d_qtype.getCode() || ne->d_auth != qname ||
1140 t_sstorage.negcache.get(qname, qtype, d_now, &ne, true))
b0c164a2
RG
1141 {
1142 res = 0;
28364e4b 1143 sttl = ne->d_ttd - d_now.tv_sec;
b0c164a2 1144 giveNegative = true;
28364e4b
RG
1145 cachedState = ne->d_validationState;
1146 if(ne->d_qtype.getCode()) {
1147 LOG(prefix<<qname<<": "<<qtype.getName()<<" is negatively cached via '"<<ne->d_auth<<"' for another "<<sttl<<" seconds"<<endl);
b0c164a2
RG
1148 res = RCode::NoError;
1149 }
1150 else {
28364e4b 1151 LOG(prefix<<qname<<": Entire name '"<<qname<<"', is negatively cached via '"<<ne->d_auth<<"' for another "<<sttl<<" seconds"<<endl);
b0c164a2
RG
1152 res = RCode::NXDomain;
1153 }
39ce10b2 1154 }
39ce10b2
PL
1155 }
1156
1157 if (giveNegative) {
142ab370
RG
1158
1159 state = cachedState;
1160
e1636f82 1161 if (!wasAuthZone && shouldValidate() && state == Indeterminate) {
142ab370
RG
1162 LOG(prefix<<qname<<": got Indeterminate state for records retrieved from the negative cache, validating.."<<endl);
1163 computeNegCacheValidationStatus(ne, qname, qtype, res, state, depth);
1164 }
1165
39ce10b2 1166 // Transplant SOA to the returned packet
28364e4b 1167 addTTLModifiedRecords(ne->authoritySOA.records, sttl, ret);
4d00b38b 1168 if(d_doDNSSEC) {
28364e4b
RG
1169 addTTLModifiedRecords(ne->authoritySOA.signatures, sttl, ret);
1170 addTTLModifiedRecords(ne->DNSSECRecords.records, sttl, ret);
1171 addTTLModifiedRecords(ne->DNSSECRecords.signatures, sttl, ret);
4d00b38b 1172 }
4d2be65d 1173
142ab370 1174 LOG(prefix<<qname<<": updating validation state with negative cache content for "<<qname<<" to "<<vStates[state]<<endl);
39ce10b2 1175 return true;
fd8bc993 1176 }
39ce10b2 1177
e325f20c 1178 vector<DNSRecord> cset;
75b49099 1179 bool found=false, expired=false;
57769f13 1180 vector<std::shared_ptr<RRSIGRecordContent>> signatures;
2b984251 1181 vector<std::shared_ptr<DNSRecord>> authorityRecs;
57769f13 1182 uint32_t ttl=0;
428f41b7 1183 bool wasCachedAuth;
ad797d94 1184 if(t_RC->get(d_now.tv_sec, sqname, sqt, !wasForwardRecurse && d_requireAuthData, &cset, d_cacheRemote, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &cachedState, &wasCachedAuth) > 0) {
428f41b7 1185
2189085d 1186 LOG(prefix<<sqname<<": Found cache hit for "<<sqt.getName()<<": ");
428f41b7 1187
e1636f82 1188 if (!wasAuthZone && shouldValidate() && wasCachedAuth && cachedState == Indeterminate && d_requireAuthData) {
428f41b7
RG
1189
1190 /* This means we couldn't figure out the state when this entry was cached,
1191 most likely because we hadn't computed the zone cuts yet. */
aa30ad7e 1192 /* make sure they are computed before validating */
f4de85a3
RG
1193 DNSName subdomain(sqname);
1194 /* if we are retrieving a DS, we only care about the state of the parent zone */
1195 if(qtype == QType::DS)
1196 subdomain.chopOff();
1197
1198 computeZoneCuts(subdomain, g_rootdnsname, depth);
aa30ad7e 1199
142ab370 1200 vState recordState = getValidationStatus(qname, false);
787737ae
RG
1201 if (recordState == Secure) {
1202 LOG(prefix<<sqname<<": got Indeterminate state from the cache, validating.."<<endl);
1203 cachedState = SyncRes::validateRecordsWithSigs(depth, sqname, sqt, sqname, cset, signatures);
f4de85a3
RG
1204 }
1205 else {
1206 cachedState = recordState;
1207 }
787737ae 1208
f4de85a3
RG
1209 if (cachedState != Indeterminate) {
1210 LOG(prefix<<qname<<": got Indeterminate state from the cache, validation result is "<<vStates[cachedState]<<endl);
2fe3354d 1211 t_RC->updateValidationStatus(d_now.tv_sec, sqname, sqt, d_cacheRemote, d_requireAuthData, cachedState);
787737ae 1212 }
428f41b7
RG
1213 }
1214
e325f20c 1215 for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
c5310862 1216
e325f20c 1217 LOG(j->d_content->getZoneRepresentation());
c5310862
RG
1218
1219 if (j->d_class != QClass::IN) {
1220 continue;
1221 }
1222
e325f20c 1223 if(j->d_ttl>(unsigned int) d_now.tv_sec) {
1224 DNSRecord dr=*j;
1225 ttl = (dr.d_ttl-=d_now.tv_sec);
e325f20c 1226 ret.push_back(dr);
1227 LOG("[ttl="<<dr.d_ttl<<"] ");
4957a608 1228 found=true;
ac539791 1229 }
75b49099 1230 else {
77499b05 1231 LOG("[expired] ");
4957a608 1232 expired=true;
75b49099 1233 }
afbe2787 1234 }
57769f13 1235
f128d20d
RG
1236 ret.reserve(ret.size() + signatures.size() + authorityRecs.size());
1237
57769f13 1238 for(const auto& signature : signatures) {
e325f20c 1239 DNSRecord dr;
1240 dr.d_type=QType::RRSIG;
1241 dr.d_name=sqname;
1242 dr.d_ttl=ttl;
1243 dr.d_content=signature;
39ce10b2 1244 dr.d_place = DNSResourceRecord::ANSWER;
4d2be65d 1245 dr.d_class=QClass::IN;
e325f20c 1246 ret.push_back(dr);
57769f13 1247 }
2b984251
RG
1248
1249 for(const auto& rec : authorityRecs) {
1250 DNSRecord dr(*rec);
1251 dr.d_ttl=ttl;
1252 ret.push_back(dr);
1253 }
1254
77499b05 1255 LOG(endl);
f4df5e89 1256 if(found && !expired) {
4d2be65d 1257 if (!giveNegative)
4957a608 1258 res=0;
bcb05770 1259 LOG(prefix<<qname<<": updating validation state with cache content for "<<qname<<" to "<<vStates[cachedState]<<endl);
4d2be65d 1260 state = cachedState;
75b49099 1261 return true;
f4df5e89 1262 }
75b49099 1263 else
2189085d 1264 LOG(prefix<<qname<<": cache had only stale entries"<<endl);
afbe2787 1265 }
f4df5e89 1266
75b49099
BH
1267 return false;
1268}
afbe2787 1269
69cbdef9 1270bool SyncRes::moreSpecificThan(const DNSName& a, const DNSName &b) const
75b49099 1271{
6a1010f7 1272 return (a.isPartOf(b) && a.countLabels() > b.countLabels());
afbe2787
BH
1273}
1274
d8d0bb8f 1275struct speedOrder
eefd15f9 1276{
3ddb9247
PD
1277 speedOrder(map<DNSName,double> &speeds) : d_speeds(speeds) {}
1278 bool operator()(const DNSName &a, const DNSName &b) const
c3d9d009
BH
1279 {
1280 return d_speeds[a] < d_speeds[b];
c3d9d009 1281 }
3ddb9247 1282 map<DNSName, double>& d_speeds;
c3d9d009
BH
1283};
1284
fa1b87ff 1285inline vector<DNSName> SyncRes::shuffleInSpeedOrder(NsSet &tnameservers, const string &prefix)
afbe2787 1286{
e8b23f3b 1287 vector<DNSName> rnameservers;
5ea6f7de 1288 rnameservers.reserve(tnameservers.size());
a2d65f83 1289 for(const auto& tns: tnameservers) {
88490c03 1290 rnameservers.push_back(tns.first);
a2d65f83 1291 if(tns.first.empty()) // this was an authoritative OOB zone, don't pollute the nsSpeeds with that
1292 return rnameservers;
21f0f88b 1293 }
e8b23f3b 1294 map<DNSName, double> speeds;
461df9d2 1295
e8b23f3b 1296 for(const auto& val: rnameservers) {
79b8cdcc 1297 double speed;
a712cb56 1298 speed=t_sstorage.nsSpeeds[val].get(&d_now);
21f0f88b 1299 speeds[val]=speed;
eefd15f9 1300 }
51e2144e 1301 random_shuffle(rnameservers.begin(),rnameservers.end(), dns_random);
996c89cc
BH
1302 speedOrder so(speeds);
1303 stable_sort(rnameservers.begin(),rnameservers.end(), so);
710af846 1304
77499b05
BH
1305 if(doLog()) {
1306 LOG(prefix<<"Nameservers: ");
e325f20c 1307 for(vector<DNSName>::const_iterator i=rnameservers.begin();i!=rnameservers.end();++i) {
3ddb9247 1308 if(i!=rnameservers.begin()) {
77499b05
BH
1309 LOG(", ");
1310 if(!((i-rnameservers.begin())%3)) {
1311 LOG(endl<<prefix<<" ");
1312 }
d8d0bb8f 1313 }
317f7521 1314 LOG(i->toLogString()<<"(" << (boost::format("%0.2f") % (speeds[*i]/1000.0)).str() <<"ms)");
d8d0bb8f 1315 }
77499b05 1316 LOG(endl);
d8d0bb8f 1317 }
728485ca 1318 return rnameservers;
afbe2787
BH
1319}
1320
cc11d7f4 1321inline vector<ComboAddress> SyncRes::shuffleForwardSpeed(const vector<ComboAddress> &rnameservers, const string &prefix, const bool wasRd)
589884b8 1322{
cc11d7f4 1323 vector<ComboAddress> nameservers = rnameservers;
6ed0c28a 1324 map<ComboAddress, double> speeds;
589884b8 1325
cc11d7f4 1326 for(const auto& val: nameservers) {
589884b8 1327 double speed;
6ed0c28a 1328 DNSName nsName = DNSName(val.toStringWithPort());
1329 speed=t_sstorage.nsSpeeds[nsName].get(&d_now);
589884b8 1330 speeds[val]=speed;
1331 }
cc11d7f4 1332 random_shuffle(nameservers.begin(),nameservers.end(), dns_random);
6ed0c28a 1333 speedOrderCA so(speeds);
cc11d7f4 1334 stable_sort(nameservers.begin(),nameservers.end(), so);
589884b8 1335
589884b8 1336 if(doLog()) {
1337 LOG(prefix<<"Nameservers: ");
cc11d7f4 1338 for(vector<ComboAddress>::const_iterator i=nameservers.cbegin();i!=nameservers.cend();++i) {
1339 if(i!=nameservers.cbegin()) {
589884b8 1340 LOG(", ");
cc11d7f4 1341 if(!((i-nameservers.cbegin())%3)) {
589884b8 1342 LOG(endl<<prefix<<" ");
1343 }
1344 }
6ed0c28a 1345 LOG((wasRd ? string("+") : string("-")) << i->toStringWithPort() <<"(" << (boost::format("%0.2f") % (speeds[*i]/1000.0)).str() <<"ms)");
589884b8 1346 }
1347 LOG(endl);
1348 }
cc11d7f4 1349 return nameservers;
589884b8 1350}
1351
dbbef467
RG
1352static uint32_t getRRSIGTTL(const time_t now, const std::shared_ptr<RRSIGRecordContent>& rrsig)
1353{
1354 uint32_t res = 0;
1355 if (now < rrsig->d_sigexpire) {
1356 res = static_cast<uint32_t>(rrsig->d_sigexpire) - now;
1357 }
1358 return res;
1359}
1360
2b984251
RG
1361static const set<uint16_t> nsecTypes = {QType::NSEC, QType::NSEC3};
1362
39ce10b2
PL
1363/* Fills the authoritySOA and DNSSECRecords fields from ne with those found in the records
1364 *
1365 * \param records The records to parse for the authority SOA and NSEC(3) records
1366 * \param ne The NegCacheEntry to be filled out (will not be cleared, only appended to
1367 */
dbbef467 1368static void harvestNXRecords(const vector<DNSRecord>& records, NegCache::NegCacheEntry& ne, const time_t now, uint32_t* lowestTTL) {
620db2c8 1369 for(const auto& rec : records) {
39ce10b2
PL
1370 if(rec.d_place != DNSResourceRecord::AUTHORITY)
1371 // RFC 4035 section 3.1.3. indicates that NSEC records MUST be placed in
1372 // the AUTHORITY section. Section 3.1.1 indicates that that RRSIGs for
1373 // records MUST be in the same section as the records they cover.
1374 // Hence, we ignore all records outside of the AUTHORITY section.
1375 continue;
1376
620db2c8 1377 if(rec.d_type == QType::RRSIG) {
39ce10b2
PL
1378 auto rrsig = getRR<RRSIGRecordContent>(rec);
1379 if(rrsig) {
1380 if(rrsig->d_type == QType::SOA) {
1381 ne.authoritySOA.signatures.push_back(rec);
dbbef467
RG
1382 if (lowestTTL && isRRSIGNotExpired(now, rrsig)) {
1383 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1384 *lowestTTL = min(*lowestTTL, getRRSIGTTL(now, rrsig));
1385 }
39ce10b2
PL
1386 }
1387 if(nsecTypes.count(rrsig->d_type)) {
1388 ne.DNSSECRecords.signatures.push_back(rec);
dbbef467
RG
1389 if (lowestTTL && isRRSIGNotExpired(now, rrsig)) {
1390 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1391 *lowestTTL = min(*lowestTTL, getRRSIGTTL(now, rrsig));
1392 }
39ce10b2
PL
1393 }
1394 }
1395 continue;
1396 }
1397 if(rec.d_type == QType::SOA) {
1398 ne.authoritySOA.records.push_back(rec);
dbbef467
RG
1399 if (lowestTTL) {
1400 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1401 }
39ce10b2
PL
1402 continue;
1403 }
1404 if(nsecTypes.count(rec.d_type)) {
1405 ne.DNSSECRecords.records.push_back(rec);
dbbef467
RG
1406 if (lowestTTL) {
1407 *lowestTTL = min(*lowestTTL, rec.d_ttl);
1408 }
39ce10b2 1409 continue;
620db2c8 1410 }
620db2c8 1411 }
620db2c8 1412}
1413
4d2be65d
RG
1414static cspmap_t harvestCSPFromNE(const NegCache::NegCacheEntry& ne)
1415{
1416 cspmap_t cspmap;
1417 for(const auto& rec : ne.DNSSECRecords.signatures) {
1418 if(rec.d_type == QType::RRSIG) {
1419 auto rrc = getRR<RRSIGRecordContent>(rec);
1420 if (rrc) {
1421 cspmap[{rec.d_name,rrc->d_type}].signatures.push_back(rrc);
1422 }
1423 }
1424 }
1425 for(const auto& rec : ne.DNSSECRecords.records) {
1426 cspmap[{rec.d_name, rec.d_type}].records.push_back(rec.d_content);
1427 }
1428 return cspmap;
1429}
1430
39ce10b2
PL
1431// TODO remove after processRecords is fixed!
1432// Adds the RRSIG for the SOA and the NSEC(3) + RRSIGs to ret
620db2c8 1433static void addNXNSECS(vector<DNSRecord>&ret, const vector<DNSRecord>& records)
1434{
39ce10b2 1435 NegCache::NegCacheEntry ne;
dbbef467 1436 harvestNXRecords(records, ne, 0, nullptr);
39ce10b2
PL
1437 ret.insert(ret.end(), ne.authoritySOA.signatures.begin(), ne.authoritySOA.signatures.end());
1438 ret.insert(ret.end(), ne.DNSSECRecords.records.begin(), ne.DNSSECRecords.records.end());
1439 ret.insert(ret.end(), ne.DNSSECRecords.signatures.begin(), ne.DNSSECRecords.signatures.end());
620db2c8 1440}
1441
69cbdef9 1442bool SyncRes::nameserversBlockedByRPZ(const DNSFilterEngine& dfe, const NsSet& nameservers)
26ca3513
RG
1443{
1444 if(d_wantsRPZ) {
1445 for (auto const &ns : nameservers) {
69cbdef9 1446 d_appliedPolicy = dfe.getProcessingPolicy(ns.first, d_discardedPolicies);
26ca3513
RG
1447 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
1448 LOG(", however nameserver "<<ns.first<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
1449 return true;
1450 }
1451
1452 // Traverse all IP addresses for this NS to see if they have an RPN NSIP policy
1453 for (auto const &address : ns.second.first) {
69cbdef9 1454 d_appliedPolicy = dfe.getProcessingPolicy(address, d_discardedPolicies);
26ca3513
RG
1455 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
1456 LOG(", however nameserver "<<ns.first<<" IP address "<<address.toString()<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
1457 return true;
1458 }
1459 }
1460 }
1461 }
1462 return false;
1463}
1464
69cbdef9 1465bool SyncRes::nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAddress& remoteIP)
26ca3513
RG
1466{
1467 if (d_wantsRPZ) {
69cbdef9 1468 d_appliedPolicy = dfe.getProcessingPolicy(remoteIP, d_discardedPolicies);
26ca3513
RG
1469 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) {
1470 LOG(" (blocked by RPZ policy '"+(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")+"')");
1471 return true;
1472 }
1473 }
1474 return false;
1475}
1476
b4c8789a 1477vector<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, bool cacheOnly)
26ca3513
RG
1478{
1479 vector<ComboAddress> result;
1480
1481 if(!tns->empty()) {
1482 LOG(prefix<<qname<<": Trying to resolve NS '"<<*tns<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<<endl);
b4c8789a 1483 result = getAddrs(*tns, depth+2, beenthere, cacheOnly);
26ca3513
RG
1484 pierceDontQuery=false;
1485 }
1486 else {
1487 LOG(prefix<<qname<<": Domain has hardcoded nameserver");
1488
589884b8 1489 if(nameservers[*tns].first.size() > 1) {
26ca3513
RG
1490 LOG("s");
1491 }
1492 LOG(endl);
1493
1494 sendRDQuery = nameservers[*tns].second;
589884b8 1495 result = shuffleForwardSpeed(nameservers[*tns].first, doLog() ? (prefix+qname.toString()+": ") : string(), sendRDQuery);
26ca3513
RG
1496 pierceDontQuery=true;
1497 }
1498 return result;
1499}
1500
1501bool SyncRes::throttledOrBlocked(const std::string& prefix, const ComboAddress& remoteIP, const DNSName& qname, const QType& qtype, bool pierceDontQuery)
1502{
a712cb56 1503 if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0))) {
26ca3513
RG
1504 LOG(prefix<<qname<<": server throttled "<<endl);
1505 s_throttledqueries++; d_throttledqueries++;
1506 return true;
1507 }
a712cb56 1508 else if(t_sstorage.throttle.shouldThrottle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()))) {
6dfff36f 1509 LOG(prefix<<qname<<": query throttled "<<remoteIP.toString()<<", "<<qname<<"; "<<qtype.getName()<<endl);
26ca3513
RG
1510 s_throttledqueries++; d_throttledqueries++;
1511 return true;
1512 }
9065eb05 1513 else if(!pierceDontQuery && s_dontQuery && s_dontQuery->match(&remoteIP)) {
26ca3513
RG
1514 LOG(prefix<<qname<<": not sending query to " << remoteIP.toString() << ", blocked by 'dont-query' setting" << endl);
1515 s_dontqueries++;
1516 return true;
1517 }
1518 return false;
1519}
1520
4d2be65d
RG
1521bool SyncRes::validationEnabled() const
1522{
8455425c 1523 return g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate;
4d2be65d
RG
1524}
1525
1526uint32_t SyncRes::computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, uint32_t signaturesTTL) const
26ca3513 1527{
4d2be65d
RG
1528 uint32_t lowestTTD = std::numeric_limits<uint32_t>::max();
1529 for(const auto& record : records)
1530 lowestTTD = min(lowestTTD, record.d_ttl);
1531
0c43f455
RG
1532 /* even if it was not requested for that request (Process, and neither AD nor DO set),
1533 it might be requested at a later time so we need to be careful with the TTL. */
4d2be65d 1534 if (validationEnabled() && !signatures.empty()) {
3cef03e9 1535 /* if we are validating, we don't want to cache records after their signatures expire. */
4d2be65d
RG
1536 /* records TTL are now TTD, let's add 'now' to the signatures lowest TTL */
1537 lowestTTD = min(lowestTTD, static_cast<uint32_t>(signaturesTTL + d_now.tv_sec));
1538
1539 for(const auto& sig : signatures) {
dbbef467
RG
1540 if (isRRSIGNotExpired(d_now.tv_sec, sig)) {
1541 // we don't decerement d_sigexpire by 'now' because we actually want a TTD, not a TTL */
4d2be65d
RG
1542 lowestTTD = min(lowestTTD, static_cast<uint32_t>(sig->d_sigexpire));
1543 }
1544 }
1545 }
1546
1547 return lowestTTD;
1548}
1549
1550void SyncRes::updateValidationState(vState& state, const vState stateUpdate)
1551{
f715542c 1552 LOG(d_prefix<<"validation state was "<<std::string(vStates[state])<<", state update is "<<std::string(vStates[stateUpdate]));
4d2be65d 1553
895449a5
RG
1554 if (stateUpdate == TA) {
1555 state = Secure;
4d2be65d
RG
1556 }
1557 else if (stateUpdate == NTA) {
1558 state = Insecure;
1559 }
895449a5
RG
1560 else if (stateUpdate == Bogus) {
1561 state = Bogus;
1562 }
1563 else if (state == Indeterminate) {
1564 state = stateUpdate;
1565 }
4d2be65d
RG
1566 else if (stateUpdate == Insecure) {
1567 if (state != Bogus) {
1568 state = Insecure;
1569 }
1570 }
f715542c 1571 LOG(", validation state is now "<<std::string(vStates[state])<<endl);
4d2be65d
RG
1572}
1573
1574vState SyncRes::getTA(const DNSName& zone, dsmap_t& ds)
1575{
1576 auto luaLocal = g_luaconfs.getLocal();
1577
1578 if (luaLocal->dsAnchors.empty()) {
e77f01d1 1579 LOG(d_prefix<<": No trust anchors configured, everything is Insecure"<<endl);
4d2be65d
RG
1580 /* We have no TA, everything is insecure */
1581 return Insecure;
1582 }
1583
1584 std::string reason;
1585 if (haveNegativeTrustAnchor(luaLocal->negAnchors, zone, reason)) {
e77f01d1 1586 LOG(d_prefix<<": got NTA for '"<<zone<<"'"<<endl);
4d2be65d
RG
1587 return NTA;
1588 }
1589
1590 if (getTrustAnchor(luaLocal->dsAnchors, zone, ds)) {
e77f01d1 1591 LOG(d_prefix<<": got TA for '"<<zone<<"'"<<endl);
895449a5 1592 return TA;
4d2be65d 1593 }
e77f01d1 1594 else {
1595 LOG(d_prefix<<": no TA found for '"<<zone<<"' among "<< luaLocal->dsAnchors.size()<<endl);
1596 }
4d2be65d
RG
1597
1598 if (zone.isRoot()) {
1599 /* No TA for the root */
1600 return Insecure;
1601 }
1602
1603 return Indeterminate;
1604}
1605
8455425c
RG
1606static size_t countSupportedDS(const dsmap_t& dsmap)
1607{
1608 size_t count = 0;
1609
1610 for (const auto& ds : dsmap) {
1611 if (isSupportedDS(ds)) {
1612 count++;
1613 }
1614 }
1615
1616 return count;
1617}
1618
5374b03b 1619vState SyncRes::getDSRecords(const DNSName& zone, dsmap_t& ds, bool taOnly, unsigned int depth, bool bogusOnNXD, bool* foundCut)
4d2be65d
RG
1620{
1621 vState result = getTA(zone, ds);
1622
1623 if (result != Indeterminate || taOnly) {
5374b03b
RG
1624 if (foundCut) {
1625 *foundCut = (result != Indeterminate);
1626 }
1627
18159e92
RG
1628 if (result == TA) {
1629 if (countSupportedDS(ds) == 0) {
1630 ds.clear();
1631 result = Insecure;
1632 }
1633 else {
1634 result = Secure;
1635 }
1636 }
1637 else if (result == NTA) {
8455425c
RG
1638 result = Insecure;
1639 }
1640
4d2be65d
RG
1641 return result;
1642 }
1643
1644 bool oldSkipCNAME = d_skipCNAMECheck;
4d2be65d 1645 d_skipCNAMECheck = true;
4d2be65d
RG
1646
1647 std::set<GetBestNSAnswer> beenthere;
1648 std::vector<DNSRecord> dsrecords;
1649
1650 vState state = Indeterminate;
51b6b728 1651 int rcode = doResolve(zone, QType(QType::DS), dsrecords, depth + 1, beenthere, state);
4d2be65d 1652 d_skipCNAMECheck = oldSkipCNAME;
4d2be65d 1653
3ca6d908 1654 if (rcode == RCode::NoError || (rcode == RCode::NXDomain && !bogusOnNXD)) {
5374b03b 1655
1e332f68
PL
1656 uint8_t bestDigestType = 0;
1657
4d2be65d 1658 if (state == Secure) {
1c39e884 1659 bool gotCNAME = false;
4d2be65d
RG
1660 for (const auto& record : dsrecords) {
1661 if (record.d_type == QType::DS) {
1662 const auto dscontent = getRR<DSRecordContent>(record);
8455425c 1663 if (dscontent && isSupportedDS(*dscontent)) {
1e332f68
PL
1664 // Make GOST a lower prio than SHA256
1665 if (dscontent->d_digesttype == DNSSECKeeper::GOST && bestDigestType == DNSSECKeeper::SHA256) {
1666 continue;
1667 }
1668 if (dscontent->d_digesttype > bestDigestType || (bestDigestType == DNSSECKeeper::GOST && dscontent->d_digesttype == DNSSECKeeper::SHA256)) {
1669 bestDigestType = dscontent->d_digesttype;
1670 }
4d2be65d
RG
1671 ds.insert(*dscontent);
1672 }
1673 }
1c39e884
RG
1674 else if (record.d_type == QType::CNAME && record.d_name == zone) {
1675 gotCNAME = true;
1676 }
4d2be65d 1677 }
4d2be65d 1678
1e332f68
PL
1679 /* RFC 4509 section 3: "Validator implementations SHOULD ignore DS RRs containing SHA-1
1680 * digests if DS RRs with SHA-256 digests are present in the DS RRset."
1681 * As SHA348 is specified as well, the spirit of the this line is "use the best algorithm".
1682 */
a211ccb5
RG
1683 for (auto dsrec = ds.begin(); dsrec != ds.end(); ) {
1684 if (dsrec->d_digesttype != bestDigestType) {
1685 dsrec = ds.erase(dsrec);
1686 }
1687 else {
1688 ++dsrec;
1e332f68
PL
1689 }
1690 }
1691
5374b03b
RG
1692 if (rcode == RCode::NoError && ds.empty()) {
1693 if (foundCut) {
1c39e884 1694 if (gotCNAME || denialProvesNoDelegation(zone, dsrecords)) {
5374b03b
RG
1695 /* we are still inside the same Secure zone */
1696
1697 *foundCut = false;
1698 return Secure;
1699 }
1700
1701 *foundCut = true;
1702 }
1703
b7f378d1 1704 return Insecure;
5374b03b
RG
1705 } else if (foundCut && rcode == RCode::NoError && !ds.empty()) {
1706 *foundCut = true;
b7f378d1 1707 }
4d2be65d 1708 }
b7f378d1 1709
4d2be65d
RG
1710 return state;
1711 }
1712
bcb05770 1713 LOG(d_prefix<<": returning Bogus state from "<<__func__<<"("<<zone<<")"<<endl);
4d2be65d
RG
1714 return Bogus;
1715}
1716
0735b60f
RG
1717bool SyncRes::haveExactValidationStatus(const DNSName& domain)
1718{
e1636f82 1719 if (!shouldValidate()) {
0735b60f
RG
1720 return false;
1721 }
1722 const auto& it = d_cutStates.find(domain);
1723 if (it != d_cutStates.cend()) {
1724 return true;
1725 }
1726 return false;
1727}
1728
5374b03b 1729vState SyncRes::getValidationStatus(const DNSName& subdomain, bool allowIndeterminate)
70b3fe7a
RG
1730{
1731 vState result = Indeterminate;
1732
e1636f82 1733 if (!shouldValidate()) {
70b3fe7a
RG
1734 return result;
1735 }
1736 DNSName name(subdomain);
1737 do {
51b6b728
RG
1738 const auto& it = d_cutStates.find(name);
1739 if (it != d_cutStates.cend()) {
5374b03b
RG
1740 if (allowIndeterminate || it->second != Indeterminate) {
1741 LOG(d_prefix<<": got status "<<vStates[it->second]<<" for name "<<subdomain<<" (from "<<name<<")"<<endl);
1742 return it->second;
1743 }
70b3fe7a
RG
1744 }
1745 }
1746 while (name.chopOff());
1747
1748 return result;
1749}
1750
c405e222
RG
1751bool SyncRes::lookForCut(const DNSName& qname, unsigned int depth, const vState existingState, vState& newState)
1752{
1753 bool foundCut = false;
5374b03b
RG
1754 dsmap_t ds;
1755 vState dsState = getDSRecords(qname, ds, newState == Bogus || existingState == Insecure || existingState == Bogus, depth, false, &foundCut);
c405e222 1756
5374b03b
RG
1757 if (dsState != Indeterminate) {
1758 newState = dsState;
1759 }
c405e222 1760
c405e222
RG
1761 return foundCut;
1762}
1763
51b6b728 1764void SyncRes::computeZoneCuts(const DNSName& begin, const DNSName& end, unsigned int depth)
4d2be65d 1765{
428f41b7 1766 if(!begin.isPartOf(end)) {
86f1af1c
KM
1767 LOG(d_prefix<<" "<<begin.toLogString()<<" is not part of "<<end.toLogString()<<endl);
1768 throw PDNSException(begin.toLogString() + " is not part of " + end.toLogString());
428f41b7
RG
1769 }
1770
51b6b728 1771 if (d_cutStates.count(begin) != 0) {
ad75fdbd 1772 return;
4d2be65d
RG
1773 }
1774
1775 dsmap_t ds;
51b6b728 1776 vState cutState = getDSRecords(end, ds, false, depth);
bcb05770 1777 LOG(d_prefix<<": setting cut state for "<<end<<" to "<<vStates[cutState]<<endl);
51b6b728 1778 d_cutStates[end] = cutState;
70b3fe7a 1779
e1636f82 1780 if (!shouldValidate()) {
ad75fdbd 1781 return;
70b3fe7a
RG
1782 }
1783
70b3fe7a
RG
1784 DNSName qname(end);
1785 std::vector<string> labelsToAdd = begin.makeRelative(end).getRawLabels();
1786
ad75fdbd 1787 bool oldSkipCNAME = d_skipCNAMECheck;
ad75fdbd 1788 d_skipCNAMECheck = true;
ad75fdbd 1789
70b3fe7a 1790 while(qname != begin) {
70b3fe7a
RG
1791 if (labelsToAdd.empty())
1792 break;
1793
1794 qname.prependRawLabel(labelsToAdd.back());
1795 labelsToAdd.pop_back();
bcb05770
RG
1796 LOG(d_prefix<<": - Looking for a cut at "<<qname<<endl);
1797
1798 const auto cutIt = d_cutStates.find(qname);
1799 if (cutIt != d_cutStates.cend()) {
1800 if (cutIt->second != Indeterminate) {
1801 LOG(d_prefix<<": - Cut already known at "<<qname<<endl);
3d4e836e 1802 cutState = cutIt->second;
bcb05770
RG
1803 continue;
1804 }
1805 }
70b3fe7a 1806
3d4e836e
RG
1807 /* no need to look for NS and DS if we are already insecure or bogus,
1808 just look for (N)TA
1809 */
1810 if (cutState == Insecure || cutState == Bogus) {
2010ac95
RG
1811 dsmap_t cutDS;
1812 vState newState = getDSRecords(qname, cutDS, true, depth);
3d4e836e
RG
1813 if (newState == Indeterminate) {
1814 continue;
1815 }
1816
1817 LOG(d_prefix<<": New state for "<<qname<<" is "<<vStates[newState]<<endl);
3d4e836e
RG
1818 cutState = newState;
1819
1820 d_cutStates[qname] = cutState;
1821
1822 continue;
1823 }
70b3fe7a 1824
c405e222 1825 vState newState = Indeterminate;
428f41b7
RG
1826 /* temporarily mark as Indeterminate, so that we won't enter an endless loop
1827 trying to determine that zone cut again. */
c405e222
RG
1828 d_cutStates[qname] = newState;
1829 bool foundCut = lookForCut(qname, depth + 1, cutState, newState);
1830 if (foundCut) {
1831 LOG(d_prefix<<": - Found cut at "<<qname<<endl);
1832 if (newState != Indeterminate) {
1833 cutState = newState;
70b3fe7a 1834 }
c405e222
RG
1835 LOG(d_prefix<<": New state for "<<qname<<" is "<<vStates[cutState]<<endl);
1836 d_cutStates[qname] = cutState;
70b3fe7a 1837 }
c405e222 1838 else {
428f41b7 1839 /* remove the temporary cut */
b25712fd 1840 LOG(d_prefix<<qname<<": removing cut state for "<<qname<<endl);
51b6b728 1841 d_cutStates.erase(qname);
428f41b7 1842 }
70b3fe7a
RG
1843 }
1844
ad75fdbd 1845 d_skipCNAMECheck = oldSkipCNAME;
ad75fdbd 1846
bcb05770 1847 LOG(d_prefix<<": list of cuts from "<<begin<<" to "<<end<<endl);
51b6b728 1848 for (const auto& cut : d_cutStates) {
bcb05770 1849 if (cut.first.isRoot() || (begin.isPartOf(cut.first) && cut.first.isPartOf(end))) {
51b6b728
RG
1850 LOG(" - "<<cut.first<<": "<<vStates[cut.second]<<endl);
1851 }
70b3fe7a 1852 }
4d2be65d
RG
1853}
1854
51b6b728 1855vState SyncRes::validateDNSKeys(const DNSName& zone, const std::vector<DNSRecord>& dnskeys, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures, unsigned int depth)
4d2be65d
RG
1856{
1857 dsmap_t ds;
1858 if (!signatures.empty()) {
1859 DNSName signer = getSigner(signatures);
1860
8d2e7fa1 1861 if (!signer.empty() && zone.isPartOf(signer)) {
51b6b728 1862 vState state = getDSRecords(signer, ds, false, depth);
b7f378d1 1863
4d2be65d
RG
1864 if (state != Secure) {
1865 return state;
1866 }
1867 }
1868 }
1869
1870 skeyset_t tentativeKeys;
1871 std::vector<shared_ptr<DNSRecordContent> > toSign;
1872
1873 for (const auto& dnskey : dnskeys) {
1874 if (dnskey.d_type == QType::DNSKEY) {
1875 auto content = getRR<DNSKEYRecordContent>(dnskey);
1876 if (content) {
1877 tentativeKeys.insert(content);
1878 toSign.push_back(content);
1879 }
1880 }
1881 }
1882
bcb05770 1883 LOG(d_prefix<<": trying to validate "<<std::to_string(tentativeKeys.size())<<" DNSKEYs with "<<std::to_string(ds.size())<<" DS"<<endl);
4d2be65d
RG
1884 skeyset_t validatedKeys;
1885 validateDNSKeysAgainstDS(d_now.tv_sec, zone, ds, tentativeKeys, toSign, signatures, validatedKeys);
1886
bcb05770 1887 LOG(d_prefix<<": we now have "<<std::to_string(validatedKeys.size())<<" DNSKEYs"<<endl);
4d2be65d 1888
82fbd934
RG
1889 /* if we found at least one valid RRSIG covering the set,
1890 all tentative keys are validated keys. Otherwise it means
1891 we haven't found at least one DNSKEY and a matching RRSIG
1892 covering this set, this looks Bogus. */
4d2be65d 1893 if (validatedKeys.size() != tentativeKeys.size()) {
bcb05770 1894 LOG(d_prefix<<": returning Bogus state from "<<__func__<<"("<<zone<<")"<<endl);
4d2be65d
RG
1895 return Bogus;
1896 }
1897
1898 return Secure;
1899}
1900
51b6b728 1901vState SyncRes::getDNSKeys(const DNSName& signer, skeyset_t& keys, unsigned int depth)
4d2be65d
RG
1902{
1903 std::vector<DNSRecord> records;
1904 std::set<GetBestNSAnswer> beenthere;
bcb05770 1905 LOG(d_prefix<<"Retrieving DNSKeys for "<<signer<<endl);
4d2be65d
RG
1906
1907 vState state = Indeterminate;
c7385ddb
RG
1908 /* following CNAME might lead to us to the wrong DNSKEY */
1909 bool oldSkipCNAME = d_skipCNAMECheck;
1910 d_skipCNAMECheck = true;
51b6b728 1911 int rcode = doResolve(signer, QType(QType::DNSKEY), records, depth + 1, beenthere, state);
c7385ddb 1912 d_skipCNAMECheck = oldSkipCNAME;
4d2be65d
RG
1913
1914 if (rcode == RCode::NoError) {
1915 if (state == Secure) {
1916 for (const auto& key : records) {
1917 if (key.d_type == QType::DNSKEY) {
1918 auto content = getRR<DNSKEYRecordContent>(key);
1919 if (content) {
1920 keys.insert(content);
1921 }
1922 }
1923 }
1924 }
bcb05770 1925 LOG(d_prefix<<"Retrieved "<<keys.size()<<" DNSKeys for "<<signer<<", state is "<<vStates[state]<<endl);
4d2be65d
RG
1926 return state;
1927 }
1928
bcb05770 1929 LOG(d_prefix<<"Returning Bogus state from "<<__func__<<"("<<signer<<")"<<endl);
4d2be65d
RG
1930 return Bogus;
1931}
1932
51b6b728 1933vState SyncRes::validateRecordsWithSigs(unsigned int depth, const DNSName& qname, const QType& qtype, const DNSName& name, const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures)
4d2be65d
RG
1934{
1935 skeyset_t keys;
1936 if (!signatures.empty()) {
1937 const DNSName signer = getSigner(signatures);
1938 if (!signer.empty() && name.isPartOf(signer)) {
f715542c 1939 if ((qtype == QType::DNSKEY || qtype == QType::DS) && signer == qname) {
15f44f1d
RG
1940 /* we are already retrieving those keys, sorry */
1941 return Indeterminate;
1942 }
51b6b728 1943 vState state = getDNSKeys(signer, keys, depth);
4d2be65d
RG
1944 if (state != Secure) {
1945 return state;
1946 }
1947 }
1948 } else {
bcb05770 1949 LOG(d_prefix<<"Bogus!"<<endl);
4d2be65d
RG
1950 return Bogus;
1951 }
1952
1953 std::vector<std::shared_ptr<DNSRecordContent> > recordcontents;
1954 for (const auto& record : records) {
1955 recordcontents.push_back(record.d_content);
1956 }
1957
bcb05770 1958 LOG(d_prefix<<"Going to validate "<<recordcontents.size()<< " record contents with "<<signatures.size()<<" sigs and "<<keys.size()<<" keys for "<<name<<endl);
4d2be65d 1959 if (validateWithKeySet(d_now.tv_sec, name, recordcontents, signatures, keys, false)) {
bcb05770 1960 LOG(d_prefix<<"Secure!"<<endl);
4d2be65d
RG
1961 return Secure;
1962 }
1963
bcb05770 1964 LOG(d_prefix<<"Bogus!"<<endl);
4d2be65d
RG
1965 return Bogus;
1966}
1967
e4894ce0 1968RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType& qtype, const DNSName& auth, bool wasForwarded, const boost::optional<Netmask> ednsmask, vState& state, bool& needWildcardProof, unsigned int& wildcardLabelsCount)
4d2be65d 1969{
26ca3513
RG
1970 tcache_t tcache;
1971
4d2be65d
RG
1972 string prefix;
1973 if(doLog()) {
1974 prefix=d_prefix;
1975 prefix.append(depth, ' ');
1976 }
1977
2b984251 1978 std::vector<std::shared_ptr<DNSRecord>> authorityRecs;
142ab370 1979 const unsigned int labelCount = qname.countLabels();
a82d4e27 1980 bool isCNAMEAnswer = false;
26ca3513 1981 for(const auto& rec : lwr.d_records) {
c5310862
RG
1982 if (rec.d_class != QClass::IN) {
1983 continue;
1984 }
1985
a82d4e27
RG
1986 if(!isCNAMEAnswer && rec.d_place == DNSResourceRecord::ANSWER && rec.d_type == QType::CNAME && (!(qtype==QType(QType::CNAME))) && rec.d_name == qname) {
1987 isCNAMEAnswer = true;
1988 }
1989
9b061cf5
RG
1990 /* if we have a positive answer synthetized from a wildcard,
1991 we need to store the corresponding NSEC/NSEC3 records proving
1992 that the exact name did not exist in the negative cache */
2b984251
RG
1993 if(needWildcardProof) {
1994 if (nsecTypes.count(rec.d_type)) {
1995 authorityRecs.push_back(std::make_shared<DNSRecord>(rec));
1996 }
1997 else if (rec.d_type == QType::RRSIG) {
1998 auto rrsig = getRR<RRSIGRecordContent>(rec);
1999 if (rrsig && nsecTypes.count(rrsig->d_type)) {
2000 authorityRecs.push_back(std::make_shared<DNSRecord>(rec));
2001 }
2002 }
2003 }
26ca3513
RG
2004 if(rec.d_type == QType::RRSIG) {
2005 auto rrsig = getRR<RRSIGRecordContent>(rec);
2006 if (rrsig) {
bb07ad8e
RG
2007 /* As illustrated in rfc4035's Appendix B.6, the RRSIG label
2008 count can be lower than the name's label count if it was
9b061cf5 2009 synthetized from the wildcard. Note that the difference might
bb07ad8e
RG
2010 be > 1. */
2011 if (rec.d_name == qname && rrsig->d_labels < labelCount) {
9b061cf5 2012 LOG(prefix<<qname<<": RRSIG indicates the name was synthetized from a wildcard, we need a wildcard proof"<<endl);
2b984251 2013 needWildcardProof = true;
e4894ce0 2014 wildcardLabelsCount = rrsig->d_labels;
2b984251
RG
2015 }
2016
26ca3513
RG
2017 // cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.d_name<<"'"<<endl;
2018 tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signatures.push_back(rrsig);
4d2be65d 2019 tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signaturesTTL = std::min(tcache[{rec.d_name, rrsig->d_type, rec.d_place}].signaturesTTL, rec.d_ttl);
26ca3513
RG
2020 }
2021 }
2022 }
2023
2024 // reap all answers from this packet that are acceptable
2025 for(auto& rec : lwr.d_records) {
2026 if(rec.d_type == QType::OPT) {
2027 LOG(prefix<<qname<<": OPT answer '"<<rec.d_name<<"' from '"<<auth<<"' nameservers" <<endl);
2028 continue;
2029 }
e77f01d1 2030 LOG(prefix<<qname<<": accept answer '"<<rec.d_name<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<"|"<<rec.d_content->getZoneRepresentation()<<"' from '"<<auth<<"' nameservers? ttl="<<rec.d_ttl<<", place="<<(int)rec.d_place<<" ");
26ca3513 2031 if(rec.d_type == QType::ANY) {
c5310862
RG
2032 LOG("NO! - we don't accept 'ANY'-typed data"<<endl);
2033 continue;
2034 }
2035
2036 if(rec.d_class != QClass::IN) {
2037 LOG("NO! - we don't accept records for any other class than 'IN'"<<endl);
26ca3513
RG
2038 continue;
2039 }
2040
2041 if(rec.d_name.isPartOf(auth)) {
2042 if(rec.d_type == QType::RRSIG) {
2043 LOG("RRSIG - separate"<<endl);
2044 }
4d2be65d 2045 else if(lwr.d_aabit && lwr.d_rcode==RCode::NoError && rec.d_place==DNSResourceRecord::ANSWER && ((rec.d_type != QType::DNSKEY && rec.d_type != QType::DS) || rec.d_name != auth) && s_delegationOnly.count(auth)) {
26ca3513
RG
2046 LOG("NO! Is from delegation-only zone"<<endl);
2047 s_nodelegated++;
2048 return RCode::NXDomain;
2049 }
2050 else {
2051 bool haveLogged = false;
a712cb56 2052 if (!t_sstorage.domainmap->empty()) {
26ca3513
RG
2053 // Check if we are authoritative for a zone in this answer
2054 DNSName tmp_qname(rec.d_name);
2055 auto auth_domain_iter=getBestAuthZone(&tmp_qname);
a712cb56 2056 if(auth_domain_iter!=t_sstorage.domainmap->end() &&
26ca3513
RG
2057 auth.countLabels() <= auth_domain_iter->first.countLabels()) {
2058 if (auth_domain_iter->first != auth) {
2059 LOG("NO! - we are authoritative for the zone "<<auth_domain_iter->first<<endl);
2060 continue;
2061 } else {
2062 LOG("YES! - This answer was ");
6dfff36f 2063 if (!wasForwarded) {
26ca3513
RG
2064 LOG("retrieved from the local auth store.");
2065 } else {
2066 LOG("received from a server we forward to.");
2067 }
2068 haveLogged = true;
2069 LOG(endl);
2070 }
2071 }
2072 }
2073 if (!haveLogged) {
2074 LOG("YES!"<<endl);
2075 }
2076
2077 rec.d_ttl=min(s_maxcachettl, rec.d_ttl);
2078
2079 DNSRecord dr(rec);
26ca3513 2080 dr.d_ttl += d_now.tv_sec;
2b984251 2081 dr.d_place=DNSResourceRecord::ANSWER;
26ca3513
RG
2082 tcache[{rec.d_name,rec.d_type,rec.d_place}].records.push_back(dr);
2083 }
2084 }
2085 else
2086 LOG("NO!"<<endl);
2087 }
2088
2089 // supplant
4d2be65d
RG
2090 for(tcache_t::iterator i = tcache.begin(); i != tcache.end(); ++i) {
2091 if((i->second.records.size() + i->second.signatures.size()) > 1) { // need to group the ttl to be the minimum of the RRSET (RFC 2181, 5.2)
2092 uint32_t lowestTTD=computeLowestTTD(i->second.records, i->second.signatures, i->second.signaturesTTL);
26ca3513
RG
2093
2094 for(auto& record : i->second.records)
4d2be65d 2095 record.d_ttl = lowestTTD; // boom
26ca3513
RG
2096 }
2097
2098// cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.name;
2099// cout<<'|'<<DNSRecordContent::NumberToType(i->first.type)<<endl;
4d2be65d
RG
2100 }
2101
2102 for(tcache_t::iterator i = tcache.begin(); i != tcache.end(); ++i) {
4d2be65d 2103
26ca3513
RG
2104 if(i->second.records.empty()) // this happens when we did store signatures, but passed on the records themselves
2105 continue;
6dfff36f 2106
405a26bd
RG
2107 /* Even if the AA bit is set, additional data cannot be considered
2108 as authoritative. This is especially important during validation
2109 because keeping records in the additional section is allowed even
2110 if the corresponding RRSIGs are not included, without setting the TC
2111 bit, as stated in rfc4035's section 3.1.1. Including RRSIG RRs in a Response:
2112 "When placing a signed RRset in the Additional section, the name
2113 server MUST also place its RRSIG RRs in the Additional section.
2114 If space does not permit inclusion of both the RRset and its
2115 associated RRSIG RRs, the name server MAY retain the RRset while
2116 dropping the RRSIG RRs. If this happens, the name server MUST NOT
2117 set the TC bit solely because these RRSIG RRs didn't fit."
2118 */
2119 bool isAA = lwr.d_aabit && i->first.place != DNSResourceRecord::ADDITIONAL;
cdc5d0c0 2120 if (isAA && isCNAMEAnswer && i->first.place == DNSResourceRecord::ANSWER && (i->first.type != QType::CNAME || i->first.name != qname)) {
a82d4e27
RG
2121 /*
2122 rfc2181 states:
2123 Note that the answer section of an authoritative answer normally
2124 contains only authoritative data. However when the name sought is an
2125 alias (see section 10.1.1) only the record describing that alias is
2126 necessarily authoritative. Clients should assume that other records
2127 may have come from the server's cache. Where authoritative answers
2128 are required, the client should query again, using the canonical name
2129 associated with the alias.
2130 */
2131 isAA = false;
2132 }
2133
5374b03b 2134 vState recordState = getValidationStatus(i->first.name, false);
1a8d6a9e 2135 LOG(d_prefix<<": got initial zone status "<<vStates[recordState]<<" for record "<<i->first.name<<"|"<<DNSRecordContent::NumberToType(i->first.type)<<endl);
70b3fe7a 2136
e1636f82 2137 if (shouldValidate() && recordState == Secure) {
5374b03b
RG
2138 vState initialState = recordState;
2139
a82d4e27 2140 if (isAA) {
4d2be65d
RG
2141 if (i->first.place != DNSResourceRecord::ADDITIONAL) {
2142 /* the additional entries can be insecure,
2143 like glue:
2144 "Glue address RRsets associated with delegations MUST NOT be signed"
2145 */
2146 if (i->first.type == QType::DNSKEY && i->first.place == DNSResourceRecord::ANSWER) {
bcb05770 2147 LOG(d_prefix<<"Validating DNSKEY for "<<i->first.name<<endl);
51b6b728 2148 recordState = validateDNSKeys(i->first.name, i->second.records, i->second.signatures, depth);
4d2be65d
RG
2149 }
2150 else {
bcb05770 2151 LOG(d_prefix<<"Validating non-additional record for "<<i->first.name<<endl);
51b6b728 2152 recordState = validateRecordsWithSigs(depth, qname, qtype, i->first.name, i->second.records, i->second.signatures);
0735b60f
RG
2153 /* we might have missed a cut (zone cut within the same auth servers), causing the NS query for an Insecure zone to seem Bogus during zone cut determination */
2154 if (qtype == QType::NS && i->second.signatures.empty() && recordState == Bogus && haveExactValidationStatus(i->first.name) && getValidationStatus(i->first.name) == Indeterminate) {
2155 recordState = Indeterminate;
2156 }
4d2be65d
RG
2157 }
2158 }
2159 }
2160 else {
933299e8
RG
2161 recordState = Indeterminate;
2162
a82d4e27 2163 /* in a non authoritative answer, we only care about the DS record (or lack of) */
88cb0fe0 2164 if ((i->first.type == QType::DS || i->first.type == QType::NSEC || i->first.type == QType::NSEC3) && i->first.place == DNSResourceRecord::AUTHORITY) {
bcb05770 2165 LOG(d_prefix<<"Validating DS record for "<<i->first.name<<endl);
51b6b728 2166 recordState = validateRecordsWithSigs(depth, qname, qtype, i->first.name, i->second.records, i->second.signatures);
4d2be65d
RG
2167 }
2168 }
0735b60f 2169
933299e8 2170 if (initialState == Secure && state != recordState && isAA) {
5374b03b
RG
2171 updateValidationState(state, recordState);
2172 }
4d2be65d
RG
2173 }
2174 else {
e1636f82 2175 if (shouldValidate()) {
bcb05770 2176 LOG(d_prefix<<"Skipping validation because the current state is "<<vStates[recordState]<<endl);
4d2be65d
RG
2177 }
2178 }
2179
005b4b98
RG
2180 /* We don't need to store NSEC3 records in the positive cache because:
2181 - we don't allow direct NSEC3 queries
2182 - denial of existence proofs in wildcard expanded positive responses are stored in authorityRecs
2183 - denial of existence proofs for negative responses are stored in the negative cache
2184 */
2185 if (i->first.type != QType::NSEC3) {
142ab370 2186 t_RC->replace(d_now.tv_sec, i->first.name, QType(i->first.type), i->second.records, i->second.signatures, authorityRecs, i->first.type == QType::DS ? true : isAA, i->first.place == DNSResourceRecord::ANSWER ? ednsmask : boost::none, recordState);
005b4b98 2187 }
6dfff36f 2188
26ca3513
RG
2189 if(i->first.place == DNSResourceRecord::ANSWER && ednsmask)
2190 d_wasVariable=true;
2191 }
2192
2193 return RCode::NoError;
2194}
2195
28364e4b 2196void SyncRes::updateDenialValidationState(vState& neValidationState, const DNSName& neName, vState& state, const dState denialState, const dState expectedState, bool allowOptOut)
4d2be65d 2197{
b25712fd 2198 if (denialState == expectedState) {
28364e4b 2199 neValidationState = Secure;
b25712fd
RG
2200 }
2201 else {
142ab370 2202 if (denialState == OPTOUT && allowOptOut) {
28364e4b
RG
2203 LOG(d_prefix<<"OPT-out denial found for "<<neName<<endl);
2204 neValidationState = Secure;
142ab370 2205 return;
4d2be65d 2206 }
142ab370 2207 else if (denialState == INSECURE) {
28364e4b
RG
2208 LOG(d_prefix<<"Insecure denial found for "<<neName<<", returning Insecure"<<endl);
2209 neValidationState = Insecure;
4d2be65d 2210 }
142ab370 2211 else {
28364e4b
RG
2212 LOG(d_prefix<<"Invalid denial found for "<<neName<<", returning Bogus, res="<<denialState<<", expectedState="<<expectedState<<endl);
2213 neValidationState = Bogus;
142ab370 2214 }
28364e4b 2215 updateValidationState(state, neValidationState);
4d2be65d
RG
2216 }
2217}
2218
28364e4b 2219dState SyncRes::getDenialValidationState(const NegCache::NegCacheEntry& ne, const vState state, const dState expectedState, bool referralToUnsigned)
142ab370
RG
2220{
2221 cspmap_t csp = harvestCSPFromNE(ne);
2222 return getDenial(csp, ne.d_name, ne.d_qtype.getCode(), referralToUnsigned, expectedState == NXQTYPE);
2223}
2224
e4894ce0 2225bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, const QType& qtype, const DNSName& auth, LWResult& lwr, const bool sendRDQuery, vector<DNSRecord>& ret, set<DNSName>& nsset, DNSName& newtarget, DNSName& newauth, bool& realreferral, bool& negindic, vState& state, const bool needWildcardProof, const unsigned int wildcardLabelsCount)
26ca3513
RG
2226{
2227 bool done = false;
2228
2229 for(auto& rec : lwr.d_records) {
2230 if (rec.d_type!=QType::OPT && rec.d_class!=QClass::IN)
2231 continue;
2232
2233 if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::SOA &&
2234 lwr.d_rcode==RCode::NXDomain && qname.isPartOf(rec.d_name) && rec.d_name.isPartOf(auth)) {
2235 LOG(prefix<<qname<<": got negative caching indication for name '"<<qname<<"' (accept="<<rec.d_name.isPartOf(auth)<<"), newtarget='"<<newtarget<<"'"<<endl);
2236
2237 rec.d_ttl = min(rec.d_ttl, s_maxnegttl);
2238 if(newtarget.empty()) // only add a SOA if we're not going anywhere after this
2239 ret.push_back(rec);
39ce10b2 2240
114829cc
RG
2241 NegCache::NegCacheEntry ne;
2242
dbbef467 2243 uint32_t lowestTTL = rec.d_ttl;
9b061cf5
RG
2244 /* if we get an NXDomain answer with a CNAME, the name
2245 does exist but the target does not */
2246 ne.d_name = newtarget.empty() ? qname : newtarget;
114829cc
RG
2247 ne.d_qtype = QType(0); // this encodes 'whole record'
2248 ne.d_auth = rec.d_name;
dbbef467
RG
2249 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2250 ne.d_ttd = d_now.tv_sec + lowestTTL;
2251
142ab370
RG
2252 if (state == Secure) {
2253 dState denialState = getDenialValidationState(ne, state, NXDOMAIN, false);
28364e4b 2254 updateDenialValidationState(ne.d_validationState, ne.d_name, state, denialState, NXDOMAIN, false);
142ab370
RG
2255 }
2256 else {
2257 ne.d_validationState = state;
2258 }
114829cc 2259
9b061cf5
RG
2260 /* if we get an NXDomain answer with a CNAME, let's not cache the
2261 target, even the server was authoritative for it,
2262 and do an additional query for the CNAME target.
2263 We have a regression test making sure we do exactly that.
2264 */
2265 if(!wasVariable() && newtarget.empty()) {
a712cb56 2266 t_sstorage.negcache.add(ne);
07e3cfb6 2267 if(s_rootNXTrust && ne.d_auth.isRoot() && auth.isRoot()) {
9a1e060b 2268 ne.d_name = ne.d_name.getLastLabel();
a712cb56 2269 t_sstorage.negcache.add(ne);
26ca3513
RG
2270 }
2271 }
2272
2273 negindic=true;
2274 }
4d2be65d 2275 else if(rec.d_place==DNSResourceRecord::ANSWER && rec.d_type==QType::CNAME && (!(qtype==QType(QType::CNAME))) && rec.d_name == qname) {
26ca3513
RG
2276 ret.push_back(rec);
2277 if (auto content = getRR<CNAMERecordContent>(rec)) {
2278 newtarget=content->getTarget();
2279 }
2280 }
9b061cf5
RG
2281 /* if we have a positive answer synthetized from a wildcard, we need to
2282 return the corresponding NSEC/NSEC3 records from the AUTHORITY section
2283 proving that the exact name did not exist */
2b984251
RG
2284 else if(needWildcardProof && (rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSResourceRecord::AUTHORITY) {
2285 ret.push_back(rec); // enjoy your DNSSEC
2286 }
26ca3513
RG
2287 // for ANY answers we *must* have an authoritative answer, unless we are forwarding recursively
2288 else if(rec.d_place==DNSResourceRecord::ANSWER && rec.d_name == qname &&
2289 (
331222c4 2290 rec.d_type==qtype.getCode() || ((lwr.d_aabit || sendRDQuery) && qtype == QType(QType::ANY))
26ca3513
RG
2291 )
2292 )
2293 {
2294 LOG(prefix<<qname<<": answer is in: resolved to '"<< rec.d_content->getZoneRepresentation()<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<"'"<<endl);
2295
2296 done=true;
2297 ret.push_back(rec);
9b061cf5
RG
2298
2299 if (state == Secure && needWildcardProof) {
2300 /* We have a positive answer synthetized from a wildcard, we need to check that we have
2301 proof that the exact name doesn't exist so the wildcard can be used,
2302 as described in section 5.3.4 of RFC 4035 and 5.3 of FRC 7129.
2303 */
2304 NegCache::NegCacheEntry ne;
2305
2306 uint32_t lowestTTL = rec.d_ttl;
2307 ne.d_name = qname;
2308 ne.d_qtype = QType(0); // this encodes 'whole record'
2309 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2310
2311 cspmap_t csp = harvestCSPFromNE(ne);
e4894ce0 2312 dState res = getDenial(csp, qname, ne.d_qtype.getCode(), false, false, false, wildcardLabelsCount);
9b061cf5 2313 if (res != NXDOMAIN) {
b7c40613
RG
2314 vState st = Bogus;
2315 if (res == INSECURE) {
2316 /* Some part could not be validated, for example a NSEC3 record with a too large number of iterations,
2317 this is not enough to warrant a Bogus, but go Insecure. */
2318 st = Insecure;
2319 LOG(d_prefix<<"Unable to validate denial in wildcard expanded positive response found for "<<qname<<", returning Insecure, res="<<res<<endl);
2320 }
2321 else {
2322 LOG(d_prefix<<"Invalid denial in wildcard expanded positive response found for "<<qname<<", returning Bogus, res="<<res<<endl);
2323 }
2324
2325 updateValidationState(state, st);
2326 /* we already stored the record with a different validation status, let's fix it */
2fe3354d 2327 t_RC->updateValidationStatus(d_now.tv_sec, qname, qtype, d_cacheRemote, lwr.d_aabit, st);
9b061cf5
RG
2328 }
2329 }
26ca3513 2330 }
7030a59b
RG
2331 else if((rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSResourceRecord::ANSWER) {
2332 if(rec.d_type != QType::RRSIG || rec.d_name == qname)
2333 ret.push_back(rec); // enjoy your DNSSEC
2334 }
4d2be65d 2335 else if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::NS && qname.isPartOf(rec.d_name)) {
26ca3513
RG
2336 if(moreSpecificThan(rec.d_name,auth)) {
2337 newauth=rec.d_name;
2338 LOG(prefix<<qname<<": got NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
2339 realreferral=true;
2340 }
2341 else {
2342 LOG(prefix<<qname<<": got upwards/level NS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"', had '"<<auth<<"'"<<endl);
2343 }
2344 if (auto content = getRR<NSRecordContent>(rec)) {
2345 nsset.insert(content->getNS());
2346 }
2347 }
4d2be65d 2348 else if(rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::DS && qname.isPartOf(rec.d_name)) {
26ca3513 2349 LOG(prefix<<qname<<": got DS record '"<<rec.d_name<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
26ca3513 2350 }
860d5e8e 2351 else if(realreferral && rec.d_place==DNSResourceRecord::AUTHORITY && (rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && newauth.isPartOf(auth)) {
4d2be65d
RG
2352 /* we might have received a denial of the DS, let's check */
2353 if (state == Secure) {
2354 NegCache::NegCacheEntry ne;
2355 ne.d_auth = auth;
860d5e8e
RG
2356 ne.d_name = newauth;
2357 ne.d_qtype = QType::DS;
dbbef467
RG
2358 rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
2359 uint32_t lowestTTL = rec.d_ttl;
2360 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2361
142ab370
RG
2362 dState denialState = getDenialValidationState(ne, state, NXQTYPE, true);
2363
d377bb54 2364 if (denialState == NXQTYPE || denialState == OPTOUT || denialState == INSECURE) {
dbbef467 2365 ne.d_ttd = lowestTTL + d_now.tv_sec;
860d5e8e 2366 ne.d_validationState = Secure;
812c3a69 2367 LOG(prefix<<qname<<": got negative indication of DS record for '"<<newauth<<"'"<<endl);
5374b03b 2368
4d2be65d
RG
2369 if(!wasVariable()) {
2370 t_sstorage.negcache.add(ne);
2371 }
5374b03b
RG
2372
2373 if (qname == newauth && qtype == QType::DS) {
2374 /* we are actually done! */
2375 negindic=true;
2376 nsset.clear();
2377 }
4d2be65d
RG
2378 }
2379 }
2380 }
2381 else if(!done && rec.d_place==DNSResourceRecord::AUTHORITY && rec.d_type==QType::SOA &&
2382 lwr.d_rcode==RCode::NoError && qname.isPartOf(rec.d_name)) {
26ca3513
RG
2383 LOG(prefix<<qname<<": got negative caching indication for '"<< qname<<"|"<<qtype.getName()<<"'"<<endl);
2384
2385 if(!newtarget.empty()) {
2386 LOG(prefix<<qname<<": Hang on! Got a redirect to '"<<newtarget<<"' already"<<endl);
2387 }
2388 else {
2389 rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
2390 ret.push_back(rec);
114829cc
RG
2391
2392 NegCache::NegCacheEntry ne;
2393 ne.d_auth = rec.d_name;
dbbef467 2394 uint32_t lowestTTL = rec.d_ttl;
114829cc
RG
2395 ne.d_name = qname;
2396 ne.d_qtype = qtype;
dbbef467
RG
2397 harvestNXRecords(lwr.d_records, ne, d_now.tv_sec, &lowestTTL);
2398 ne.d_ttd = d_now.tv_sec + lowestTTL;
2399
142ab370
RG
2400 if (state == Secure) {
2401 dState denialState = getDenialValidationState(ne, state, NXQTYPE, false);
28364e4b 2402 updateDenialValidationState(ne.d_validationState, ne.d_name, state, denialState, NXQTYPE, qtype == QType::DS);
142ab370
RG
2403 } else {
2404 ne.d_validationState = state;
2405 }
114829cc 2406
26ca3513 2407 if(!wasVariable()) {
26ca3513 2408 if(qtype.getCode()) { // prevents us from blacking out a whole domain
a712cb56 2409 t_sstorage.negcache.add(ne);
26ca3513
RG
2410 }
2411 }
2412 negindic=true;
2413 }
2414 }
2415 }
2416
2417 return done;
2418}
2419
6dfff36f
RG
2420bool 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)
2421{
deca7d8f 2422 bool chained = false;
17cecc84 2423 int resolveret = RCode::NoError;
6dfff36f
RG
2424 s_outqueries++;
2425 d_outqueries++;
2426
2427 if(d_outqueries + d_throttledqueries > s_maxqperq) {
2428 throw ImmediateServFailException("more than "+std::to_string(s_maxqperq)+" (max-qperq) queries sent while resolving "+qname.toLogString());
2429 }
2430
2431 if(s_maxtotusec && d_totUsec > s_maxtotusec) {
2432 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");
2433 }
2434
2435 if(doTCP) {
2436 LOG(prefix<<qname<<": using TCP with "<< remoteIP.toStringWithPort() <<endl);
2437 s_tcpoutqueries++;
2438 d_tcpoutqueries++;
2439 }
2440
2441 if(d_pdl && d_pdl->preoutquery(remoteIP, d_requestor, qname, qtype, doTCP, lwr.d_records, resolveret)) {
2442 LOG(prefix<<qname<<": query handled by Lua"<<endl);
2443 }
2444 else {
2fe3354d 2445 ednsmask=getEDNSSubnetMask(qname, remoteIP);
6dfff36f
RG
2446 if(ednsmask) {
2447 LOG(prefix<<qname<<": Adding EDNS Client Subnet Mask "<<ednsmask->toString()<<" to query"<<endl);
d6923beb 2448 s_ecsqueries++;
6dfff36f
RG
2449 }
2450 resolveret = asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, qtype.getCode(),
deca7d8f 2451 doTCP, sendRDQuery, &d_now, ednsmask, &lwr, &chained); // <- we go out on the wire!
6dfff36f 2452 if(ednsmask) {
d6923beb 2453 s_ecsresponses++;
6dfff36f
RG
2454 LOG(prefix<<qname<<": Received EDNS Client Subnet Mask "<<ednsmask->toString()<<" on response"<<endl);
2455 }
2456 }
2457
2458 /* preoutquery killed the query by setting dq.rcode to -3 */
2459 if(resolveret==-3) {
2460 throw ImmediateServFailException("Query killed by policy");
2461 }
2462
2463 d_totUsec += lwr.d_usec;
2464 accountAuthLatency(lwr.d_usec, remoteIP.sin4.sin_family);
2465
2466 if(resolveret != 1) {
2467 /* Error while resolving */
2468 if(resolveret == 0) {
2469 /* Time out */
2470
2471 LOG(prefix<<qname<<": timeout resolving after "<<lwr.d_usec/1000.0<<"msec "<< (doTCP ? "over TCP" : "")<<endl);
2472 d_timeouts++;
2473 s_outgoingtimeouts++;
2474
2475 if(remoteIP.sin4.sin_family == AF_INET)
2476 s_outgoing4timeouts++;
2477 else
2478 s_outgoing6timeouts++;
be9078b3 2479
2480 if(t_timeouts)
2481 t_timeouts->push_back(remoteIP);
6dfff36f
RG
2482 }
2483 else if(resolveret == -2) {
2484 /* OS resource limit reached */
2485 LOG(prefix<<qname<<": hit a local resource limit resolving"<< (doTCP ? " over TCP" : "")<<", probable error: "<<stringerror()<<endl);
2486 g_stats.resourceLimits++;
2487 }
2488 else {
2489 /* -1 means server unreachable */
2490 s_unreachables++;
2491 d_unreachables++;
2492 LOG(prefix<<qname<<": error resolving from "<<remoteIP.toString()<< (doTCP ? " over TCP" : "") <<", possible error: "<<strerror(errno)<< endl);
2493 }
2494
deca7d8f 2495 if(resolveret != -2 && !chained) { // don't account for resource limits, they are our own fault
589884b8 2496 t_sstorage.nsSpeeds[nsName.empty()? DNSName(remoteIP.toStringWithPort()) : nsName].submit(remoteIP, 1000000, &d_now); // 1 sec
6dfff36f
RG
2497
2498 // code below makes sure we don't filter COM or the root
2499 if (s_serverdownmaxfails > 0 && (auth != g_rootdnsname) && t_sstorage.fails.incr(remoteIP) >= s_serverdownmaxfails) {
2500 LOG(prefix<<qname<<": Max fails reached resolving on "<< remoteIP.toString() <<". Going full throttle for "<< s_serverdownthrottletime <<" seconds" <<endl);
2501 // mark server as down
2502 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, "", 0), s_serverdownthrottletime, 10000);
2503 }
2504 else if (resolveret == -1) {
2505 // unreachable, 1 minute or 100 queries
2506 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 100);
2507 }
2508 else {
2509 // timeout
2510 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 10, 5);
2511 }
2512 }
2513
2514 return false;
2515 }
2516
2517 /* we got an answer */
2518 if(lwr.d_rcode==RCode::ServFail || lwr.d_rcode==RCode::Refused) {
2519 LOG(prefix<<qname<<": "<<nsName<<" ("<<remoteIP.toString()<<") returned a "<< (lwr.d_rcode==RCode::ServFail ? "ServFail" : "Refused") << ", trying sibling IP or NS"<<endl);
deca7d8f
RG
2520 if (!chained) {
2521 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
2522 }
6dfff36f
RG
2523 return false;
2524 }
2525
2526 /* this server sent a valid answer, mark it backup up if it was down */
2527 if(s_serverdownmaxfails > 0) {
2528 t_sstorage.fails.clear(remoteIP);
2529 }
2530
2531 if(lwr.d_tcbit) {
2532 *truncated = true;
2533
2534 if (doTCP) {
2535 LOG(prefix<<qname<<": truncated bit set, over TCP?"<<endl);
2536 /* let's treat that as a ServFail answer from this server */
2537 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(remoteIP, qname, qtype.getCode()), 60, 3);
2538 return false;
2539 }
2540
2541 return true;
2542 }
2543
2544 return true;
2545}
2546
51b6b728 2547bool SyncRes::processAnswer(unsigned int depth, LWResult& lwr, const DNSName& qname, const QType& qtype, DNSName& auth, bool wasForwarded, const boost::optional<Netmask> ednsmask, bool sendRDQuery, NsSet &nameservers, std::vector<DNSRecord>& ret, const DNSFilterEngine& dfe, bool* gotNewServers, int* rcode, vState& state)
6dfff36f
RG
2548{
2549 string prefix;
2550 if(doLog()) {
2551 prefix=d_prefix;
2552 prefix.append(depth, ' ');
2553 }
2554
2555 if(s_minimumTTL) {
2556 for(auto& rec : lwr.d_records) {
2557 rec.d_ttl = max(rec.d_ttl, s_minimumTTL);
2558 }
2559 }
2560
2b984251 2561 bool needWildcardProof = false;
e4894ce0
RG
2562 unsigned int wildcardLabelsCount;
2563 *rcode = updateCacheFromRecords(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, state, needWildcardProof, wildcardLabelsCount);
6dfff36f
RG
2564 if (*rcode != RCode::NoError) {
2565 return true;
2566 }
2567
2568 LOG(prefix<<qname<<": determining status after receiving this packet"<<endl);
2569
2570 set<DNSName> nsset;
2571 bool realreferral=false, negindic=false;
2572 DNSName newauth;
2573 DNSName newtarget;
2574
e4894ce0 2575 bool done = processRecords(prefix, qname, qtype, auth, lwr, sendRDQuery, ret, nsset, newtarget, newauth, realreferral, negindic, state, needWildcardProof, wildcardLabelsCount);
6dfff36f
RG
2576
2577 if(done){
2578 LOG(prefix<<qname<<": status=got results, this level of recursion done"<<endl);
5374b03b 2579 LOG(prefix<<qname<<": validation status is "<<vStates[state]<<endl);
6dfff36f
RG
2580 *rcode = RCode::NoError;
2581 return true;
2582 }
2583
2584 if(!newtarget.empty()) {
2585 if(newtarget == qname) {
2586 LOG(prefix<<qname<<": status=got a CNAME referral to self, returning SERVFAIL"<<endl);
2587 *rcode = RCode::ServFail;
2588 return true;
2589 }
2590
2591 if(depth > 10) {
2592 LOG(prefix<<qname<<": status=got a CNAME referral, but recursing too deep, returning SERVFAIL"<<endl);
2593 *rcode = RCode::ServFail;
2594 return true;
2595 }
2596
5374b03b
RG
2597 if (qtype == QType::DS) {
2598 LOG(prefix<<qname<<": status=got a CNAME referral, but we are looking for a DS"<<endl);
6dfff36f 2599
1c39e884
RG
2600 if(d_doDNSSEC)
2601 addNXNSECS(ret, lwr.d_records);
2602
2603 *rcode = RCode::NoError;
2604 return true;
5374b03b
RG
2605 }
2606 else {
2607 LOG(prefix<<qname<<": status=got a CNAME referral, starting over with "<<newtarget<<endl);
6dfff36f 2608
5374b03b
RG
2609 set<GetBestNSAnswer> beenthere2;
2610 vState cnameState = Indeterminate;
2611 *rcode = doResolve(newtarget, qtype, ret, depth + 1, beenthere2, cnameState);
2612 LOG(prefix<<qname<<": updating validation state for response to "<<qname<<" from "<<vStates[state]<<" with the state from the CNAME quest: "<<vStates[cnameState]<<endl);
2613 updateValidationState(state, cnameState);
2614 return true;
2615 }
6dfff36f
RG
2616 }
2617
2618 if(lwr.d_rcode == RCode::NXDomain) {
2619 LOG(prefix<<qname<<": status=NXDOMAIN, we are done "<<(negindic ? "(have negative SOA)" : "")<<endl);
2620
2621 if(d_doDNSSEC)
2622 addNXNSECS(ret, lwr.d_records);
2623
2624 *rcode = RCode::NXDomain;
2625 return true;
2626 }
2627
2628 if(nsset.empty() && !lwr.d_rcode && (negindic || lwr.d_aabit || sendRDQuery)) {
2629 LOG(prefix<<qname<<": status=noerror, other types may exist, but we are done "<<(negindic ? "(have negative SOA) " : "")<<(lwr.d_aabit ? "(have aa bit) " : "")<<endl);
2630
114829cc
RG
2631 if(state == Secure && lwr.d_aabit && !negindic) {
2632 updateValidationState(state, Bogus);
2633 }
2634
6dfff36f
RG
2635 if(d_doDNSSEC)
2636 addNXNSECS(ret, lwr.d_records);
2637
2638 *rcode = RCode::NoError;
2639 return true;
2640 }
2641
2642 if(realreferral) {
2643 LOG(prefix<<qname<<": status=did not resolve, got "<<(unsigned int)nsset.size()<<" NS, ");
6dfff36f
RG
2644
2645 nameservers.clear();
2646 for (auto const &nameserver : nsset) {
2647 if (d_wantsRPZ) {
2648 d_appliedPolicy = dfe.getProcessingPolicy(nameserver, d_discardedPolicies);
2649 if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
2650 LOG("however "<<nameserver<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
2651 *rcode = -2;
2652 return true;
2653 }
2654 }
2655 nameservers.insert({nameserver, {{}, false}});
2656 }
2657 LOG("looping to them"<<endl);
2658 *gotNewServers = true;
812c3a69 2659 auth=newauth;
4d2be65d 2660
6dfff36f
RG
2661 return false;
2662 }
2663
2664 return false;
2665}
2666
b8470add
PL
2667/** returns:
2668 * -1 in case of no results
2669 * -2 when a FilterEngine Policy was hit
2670 * rcode otherwise
2671 */
fa1b87ff 2672int SyncRes::doResolveAt(NsSet &nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype,
e325f20c 2673 vector<DNSRecord>&ret,
51b6b728 2674 unsigned int depth, set<GetBestNSAnswer>&beenthere, vState& state)
86c152f2 2675{
69cbdef9 2676 auto luaconfsLocal = g_luaconfs.getLocal();
ded77b10 2677 string prefix;
77499b05 2678 if(doLog()) {
ded77b10
BH
2679 prefix=d_prefix;
2680 prefix.append(depth, ' ');
2681 }
3ddb9247 2682
b8470add
PL
2683 LOG(prefix<<qname<<": Cache consultations done, have "<<(unsigned int)nameservers.size()<<" NS to contact");
2684
69cbdef9 2685 if (nameserversBlockedByRPZ(luaconfsLocal->dfe, nameservers)) {
26ca3513 2686 return -2;
b8470add
PL
2687 }
2688
2689 LOG(endl);
afbe2787
BH
2690
2691 for(;;) { // we may get more specific nameservers
e8b23f3b 2692 vector<DNSName > rnameservers = shuffleInSpeedOrder(nameservers, doLog() ? (prefix+qname.toString()+": ") : string() );
3ddb9247 2693
26ca3513
RG
2694 for(auto tns=rnameservers.cbegin();;++tns) {
2695 if(tns==rnameservers.cend()) {
2189085d 2696 LOG(prefix<<qname<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth<<"'"<<endl);
03c09afe 2697 if(!auth.isRoot() && flawedNSSet) {
2189085d 2698 LOG(prefix<<qname<<": Ageing nameservers for level '"<<auth<<"', next query might succeed"<<endl);
88490c03 2699
49a699c4 2700 if(t_RC->doAgeCache(d_now.tv_sec, auth, QType::NS, 10))
4957a608
BH
2701 g_stats.nsSetInvalidations++;
2702 }
2703 return -1;
afbe2787 2704 }
6dfff36f 2705
b4c8789a
RG
2706 bool cacheOnly = false;
2707 // this line needs to identify the 'self-resolving' behaviour
2708 if(qname == *tns && (qtype.getCode() == QType::A || qtype.getCode() == QType::AAAA)) {
2709 /* we might have a glue entry in cache so let's try this NS
2710 but only if we have enough in the cache to know how to reach it */
2711 LOG(prefix<<qname<<": Using NS to resolve itself, but only using what we have in cache ("<<(1+tns-rnameservers.cbegin())<<"/"<<rnameservers.size()<<")"<<endl);
2712 cacheOnly = true;
20177d1d 2713 }
5605c067 2714
996c89cc 2715 typedef vector<ComboAddress> remoteIPs_t;
5605c067 2716 remoteIPs_t remoteIPs;
bfea0d0b 2717 remoteIPs_t::const_iterator remoteIP;
1c21f389 2718 bool pierceDontQuery=false;
c1d73d94 2719 bool sendRDQuery=false;
376effcf 2720 boost::optional<Netmask> ednsmask;
263f6a5a 2721 LWResult lwr;
6dfff36f
RG
2722 const bool wasForwarded = tns->empty() && (!nameservers[*tns].first.empty());
2723 int rcode = RCode::NoError;
2724 bool gotNewServers = false;
2725
2726 if(tns->empty() && !wasForwarded) {
2189085d 2727 LOG(prefix<<qname<<": Domain is out-of-band"<<endl);
e1636f82
RG
2728 /* setting state to indeterminate since validation is disabled for local auth zone,
2729 and Insecure would be misleading. */
2730 state = Indeterminate;
9fc36e90 2731 d_wasOutOfBand = doOOBResolve(qname, qtype, lwr.d_records, depth, lwr.d_rcode);
4957a608
BH
2732 lwr.d_tcbit=false;
2733 lwr.d_aabit=true;
6dfff36f
RG
2734
2735 /* we have received an answer, are we done ? */
51b6b728 2736 bool done = processAnswer(depth, lwr, qname, qtype, auth, false, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state);
6dfff36f
RG
2737 if (done) {
2738 return rcode;
2739 }
2740 if (gotNewServers) {
2741 break;
2742 }
5605c067
BH
2743 }
2744 else {
6dfff36f 2745 /* if tns is empty, retrieveAddressesForNS() knows we have hardcoded servers (i.e. "forwards") */
b4c8789a 2746 remoteIPs = retrieveAddressesForNS(prefix, qname, tns, depth, beenthere, rnameservers, nameservers, sendRDQuery, pierceDontQuery, flawedNSSet, cacheOnly);
4957a608
BH
2747
2748 if(remoteIPs.empty()) {
2189085d 2749 LOG(prefix<<qname<<": Failed to get IP for NS "<<*tns<<", trying next if available"<<endl);
4957a608
BH
2750 flawedNSSet=true;
2751 continue;
2752 }
2753 else {
b8470add 2754 bool hitPolicy{false};
2189085d 2755 LOG(prefix<<qname<<": Resolved '"<<auth<<"' NS "<<*tns<<" to: ");
26ca3513
RG
2756 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
2757 if(remoteIP != remoteIPs.cbegin()) {
77499b05
BH
2758 LOG(", ");
2759 }
2760 LOG(remoteIP->toString());
69cbdef9 2761 if(nameserverIPBlockedByRPZ(luaconfsLocal->dfe, *remoteIP)) {
26ca3513 2762 hitPolicy = true;
b8470add 2763 }
4957a608 2764 }
77499b05 2765 LOG(endl);
b8470add
PL
2766 if (hitPolicy) //implies d_wantsRPZ
2767 return -2;
4957a608
BH
2768 }
2769
26ca3513 2770 for(remoteIP = remoteIPs.cbegin(); remoteIP != remoteIPs.cend(); ++remoteIP) {
2189085d 2771 LOG(prefix<<qname<<": Trying IP "<< remoteIP->toStringWithPort() <<", asking '"<<qname<<"|"<<qtype.getName()<<"'"<<endl);
6dfff36f 2772
26ca3513 2773 if (throttledOrBlocked(prefix, *remoteIP, qname, qtype, pierceDontQuery)) {
4957a608
BH
2774 continue;
2775 }
9de3e034 2776
6dfff36f
RG
2777 bool truncated = false;
2778 bool gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery,
2779 *tns, *remoteIP, false, &truncated);
2780 if (gotAnswer && truncated ) {
2781 /* retry, over TCP this time */
2782 gotAnswer = doResolveAtThisIP(prefix, qname, qtype, lwr, ednsmask, auth, sendRDQuery,
2783 *tns, *remoteIP, true, &truncated);
2784 }
710af846 2785
6dfff36f
RG
2786 if (!gotAnswer) {
2787 continue;
2788 }
352b4183 2789
6dfff36f 2790 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 2791
6dfff36f
RG
2792 /* // for you IPv6 fanatics :-)
2793 if(remoteIP->sin4.sin_family==AF_INET6)
2794 lwr.d_usec/=3;
2795 */
2796 // cout<<"msec: "<<lwr.d_usec/1000.0<<", "<<g_avgLatency/1000.0<<'\n';
710af846 2797
589884b8 2798 t_sstorage.nsSpeeds[tns->empty()? DNSName(remoteIP->toStringWithPort()) : *tns].submit(*remoteIP, lwr.d_usec, &d_now);
628e2c7b 2799
6dfff36f 2800 /* we have received an answer, are we done ? */
51b6b728 2801 bool done = processAnswer(depth, lwr, qname, qtype, auth, wasForwarded, ednsmask, sendRDQuery, nameservers, ret, luaconfsLocal->dfe, &gotNewServers, &rcode, state);
6dfff36f
RG
2802 if (done) {
2803 return rcode;
4957a608 2804 }
6dfff36f
RG
2805 if (gotNewServers) {
2806 break;
4957a608 2807 }
6dfff36f
RG
2808 /* was lame */
2809 t_sstorage.throttle.throttle(d_now.tv_sec, boost::make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100);
4957a608 2810 }
aadceba8 2811
6dfff36f
RG
2812 if (gotNewServers) {
2813 break;
4957a608 2814 }
620db2c8 2815
6dfff36f
RG
2816 if(remoteIP == remoteIPs.cend()) // we tried all IP addresses, none worked
2817 continue;
620db2c8 2818
86c152f2
BH
2819 }
2820 }
86c152f2 2821 }
ac539791 2822 return -1;
86c152f2
BH
2823}
2824
2fe3354d 2825void SyncRes::setQuerySource(const ComboAddress& requestor, boost::optional<const EDNSSubnetOpts&> incomingECS)
8a3a3822 2826{
2fe3354d
CH
2827 d_requestor = requestor;
2828
2829 if (incomingECS && incomingECS->source.getBits() > 0) {
2830 d_cacheRemote = incomingECS->source.getMaskedNetwork();
2831 uint8_t bits = std::min(incomingECS->source.getBits(), (incomingECS->source.isIpv4() ? s_ecsipv4limit : s_ecsipv6limit));
2832 ComboAddress trunc = incomingECS->source.getNetwork();
2833 trunc.truncate(bits);
2834 d_outgoingECSNetwork = boost::optional<Netmask>(Netmask(trunc, bits));
2835 } else {
2836 d_cacheRemote = d_requestor;
2837 if(!incomingECS && s_ednslocalsubnets.match(d_requestor)) {
2838 ComboAddress trunc = d_requestor;
2839 uint8_t bits = d_requestor.isIPv4() ? 32 : 128;
2840 bits = std::min(bits, (trunc.isIPv4() ? s_ecsipv4limit : s_ecsipv6limit));
2841 trunc.truncate(bits);
2842 d_outgoingECSNetwork = boost::optional<Netmask>(Netmask(trunc, bits));
2843 } else if (s_ecsScopeZero.source.getBits() > 0) {
8a3a3822
RG
2844 /* RFC7871 says we MUST NOT send any ECS if the source scope is 0.
2845 But using an empty ECS in that case would mean inserting
2846 a non ECS-specific entry into the cache, preventing any further
2847 ECS-specific query to be sent.
2848 So instead we use the trick described in section 7.1.2:
2849 "The subsequent Recursive Resolver query to the Authoritative Nameserver
2850 will then either not include an ECS option or MAY optionally include
2851 its own address information, which is what the Authoritative
2852 Nameserver will almost certainly use to generate any Tailored
2853 Response in lieu of an option. This allows the answer to be handled
2854 by the same caching mechanism as other queries, with an explicit
2855 indicator of the applicable scope. Subsequent Stub Resolver queries
2856 for /0 can then be answered from this cached response.
2857 */
2fe3354d
CH
2858 d_outgoingECSNetwork = boost::optional<Netmask>(s_ecsScopeZero.source.getMaskedNetwork());
2859 d_cacheRemote = s_ecsScopeZero.source.getNetwork();
2860 } else {
2861 // ECS disabled because no scope-zero address could be derived.
2862 d_outgoingECSNetwork = boost::none;
8a3a3822
RG
2863 }
2864 }
8a3a3822
RG
2865}
2866
2fe3354d 2867boost::optional<Netmask> SyncRes::getEDNSSubnetMask(const DNSName& dn, const ComboAddress& rem)
e9f9b8ec 2868{
2fe3354d
CH
2869 if(d_outgoingECSNetwork && (s_ednsdomains.check(dn) || s_ednsremotesubnets.match(rem))) {
2870 return d_outgoingECSNetwork;
e9f9b8ec 2871 }
2fe3354d 2872 return boost::none;
e9f9b8ec 2873}
bd53ea9d 2874
9065eb05
RG
2875void SyncRes::parseEDNSSubnetWhitelist(const std::string& wlist)
2876{
2877 vector<string> parts;
2878 stringtok(parts, wlist, ",; ");
2879 for(const auto& a : parts) {
2880 try {
2fe3354d 2881 s_ednsremotesubnets.addMask(Netmask(a));
9065eb05
RG
2882 }
2883 catch(...) {
2884 s_ednsdomains.add(DNSName(a));
2885 }
2886 }
2887}
2888
2fe3354d
CH
2889void SyncRes::parseEDNSSubnetAddFor(const std::string& subnetlist)
2890{
2891 vector<string> parts;
2892 stringtok(parts, subnetlist, ",; ");
2893 for(const auto& a : parts) {
2894 s_ednslocalsubnets.addMask(a);
2895 }
2896}
2897
8ce79a22 2898// used by PowerDNSLua - note that this neglects to add the packet count & statistics back to pdns_ercursor.cc
a3e7b735 2899int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<DNSRecord>& ret)
bd53ea9d
PD
2900{
2901 struct timeval now;
2902 gettimeofday(&now, 0);
710af846 2903
bd53ea9d 2904 SyncRes sr(now);
a3e7b735 2905 int res = sr.beginResolve(qname, QType(qtype), qclass, ret);
e325f20c 2906
bd53ea9d
PD
2907 return res;
2908}
30ee601a 2909
30ee601a
RG
2910int SyncRes::getRootNS(struct timeval now, asyncresolve_t asyncCallback) {
2911 SyncRes sr(now);
2912 sr.setDoEDNS0(true);
0b29b9c5 2913 sr.setUpdatingRootNS();
30ee601a 2914 sr.setDoDNSSEC(g_dnssecmode != DNSSECMode::Off);
0c43f455 2915 sr.setDNSSECValidationRequested(g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate);
30ee601a
RG
2916 sr.setAsyncCallback(asyncCallback);
2917
2918 vector<DNSRecord> ret;
2919 int res=-1;
2920 try {
2921 res=sr.beginResolve(g_rootdnsname, QType(QType::NS), 1, ret);
2922 if (g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate) {
4d2be65d 2923 auto state = sr.getValidationState();
30ee601a
RG
2924 if (state == Bogus)
2925 throw PDNSException("Got Bogus validation result for .|NS");
2926 }
2927 return res;
2928 }
c78ceb39 2929 catch(const PDNSException& e) {
e6a9dde5 2930 g_log<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
30ee601a 2931 }
c78ceb39 2932 catch(const ImmediateServFailException& e) {
e6a9dde5 2933 g_log<<Logger::Error<<"Failed to update . records, got an exception: "<<e.reason<<endl;
c78ceb39
RG
2934 }
2935 catch(const std::exception& e) {
e6a9dde5 2936 g_log<<Logger::Error<<"Failed to update . records, got an exception: "<<e.what()<<endl;
30ee601a 2937 }
c78ceb39 2938 catch(...) {
e6a9dde5 2939 g_log<<Logger::Error<<"Failed to update . records, got an exception"<<endl;
30ee601a 2940 }
c78ceb39 2941
30ee601a 2942 if(!res) {
e6a9dde5 2943 g_log<<Logger::Notice<<"Refreshed . records"<<endl;
30ee601a
RG
2944 }
2945 else
e6a9dde5 2946 g_log<<Logger::Error<<"Failed to update . records, RCODE="<<res<<endl;
c78ceb39 2947
30ee601a
RG
2948 return res;
2949}