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