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