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