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