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