]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/packethandler.cc
pkcs11signers: Use emplace_back for attributes
[thirdparty/pdns.git] / pdns / packethandler.cc
1 /*
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 */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include "packetcache.hh"
26 #include "utility.hh"
27 #include "base32.hh"
28 #include <string>
29 #include <sys/types.h>
30 #include <boost/algorithm/string.hpp>
31 #include "dnssecinfra.hh"
32 #include "dnsseckeeper.hh"
33 #include "dns.hh"
34 #include "dnsbackend.hh"
35 #include "ueberbackend.hh"
36 #include "dnspacket.hh"
37 #include "nameserver.hh"
38 #include "distributor.hh"
39 #include "logger.hh"
40 #include "arguments.hh"
41 #include "packethandler.hh"
42 #include "statbag.hh"
43 #include "resolver.hh"
44 #include "communicator.hh"
45 #include "dnsproxy.hh"
46 #include "version.hh"
47 #include "auth-main.hh"
48 #include "trusted-notification-proxy.hh"
49 #include "gss_context.hh"
50
51 #if 0
52 #undef DLOG
53 #define DLOG(x) x
54 #endif
55
56 AtomicCounter PacketHandler::s_count;
57 NetmaskGroup PacketHandler::s_allowNotifyFrom;
58 set<string> PacketHandler::s_forwardNotify;
59 bool PacketHandler::s_SVCAutohints{false};
60
61 extern string g_programname;
62
63 // See https://www.rfc-editor.org/rfc/rfc8078.txt and https://www.rfc-editor.org/errata/eid5049 for details
64 const std::shared_ptr<CDNSKEYRecordContent> PacketHandler::s_deleteCDNSKEYContent = std::make_shared<CDNSKEYRecordContent>("0 3 0 AA==");
65 const std::shared_ptr<CDSRecordContent> PacketHandler::s_deleteCDSContent = std::make_shared<CDSRecordContent>("0 0 0 00");
66
67 PacketHandler::PacketHandler():B(g_programname), d_dk(&B)
68 {
69 ++s_count;
70 d_doDNAME=::arg().mustDo("dname-processing");
71 d_doExpandALIAS = ::arg().mustDo("expand-alias");
72 d_logDNSDetails= ::arg().mustDo("log-dns-details");
73 string fname= ::arg()["lua-prequery-script"];
74 if(fname.empty())
75 {
76 d_pdl = nullptr;
77 }
78 else
79 {
80 d_pdl = std::make_unique<AuthLua4>();
81 d_pdl->loadFile(fname); // XXX exception handling?
82 }
83 fname = ::arg()["lua-dnsupdate-policy-script"];
84 if (fname.empty())
85 {
86 d_update_policy_lua = nullptr;
87 }
88 else
89 {
90 d_update_policy_lua = std::make_unique<AuthLua4>();
91 try {
92 d_update_policy_lua->loadFile(fname);
93 }
94 catch (const std::runtime_error&) {
95 d_update_policy_lua = nullptr;
96 }
97 }
98 }
99
100 UeberBackend *PacketHandler::getBackend()
101 {
102 return &B;
103 }
104
105 PacketHandler::~PacketHandler()
106 {
107 --s_count;
108 DLOG(g_log<<Logger::Error<<"PacketHandler destructor called - "<<s_count<<" left"<<endl);
109 }
110
111 /**
112 * This adds CDNSKEY records to the answer packet. Returns true if one was added.
113 *
114 * @param p Pointer to the DNSPacket containing the original question
115 * @param r Pointer to the DNSPacket where the records should be inserted into
116 * @return bool that shows if any records were added
117 **/
118 bool PacketHandler::addCDNSKEY(DNSPacket& p, std::unique_ptr<DNSPacket>& r)
119 {
120 string publishCDNSKEY;
121 d_dk.getPublishCDNSKEY(p.qdomain,publishCDNSKEY);
122 if (publishCDNSKEY.empty())
123 return false;
124
125 DNSZoneRecord rr;
126 rr.dr.d_type=QType::CDNSKEY;
127 rr.dr.d_ttl=d_sd.minimum;
128 rr.dr.d_name=p.qdomain;
129 rr.auth=true;
130
131 if (publishCDNSKEY == "0") { // delete DS via CDNSKEY
132 rr.dr.setContent(s_deleteCDNSKEYContent);
133 r->addRecord(std::move(rr));
134 return true;
135 }
136
137 bool haveOne=false;
138 DNSSECKeeper::keyset_t entryPoints = d_dk.getEntryPoints(p.qdomain);
139 for(const auto& value: entryPoints) {
140 if (!value.second.published) {
141 continue;
142 }
143 rr.dr.setContent(std::make_shared<DNSKEYRecordContent>(value.first.getDNSKEY()));
144 r->addRecord(DNSZoneRecord(rr));
145 haveOne=true;
146 }
147
148 if(::arg().mustDo("direct-dnskey")) {
149 B.lookup(QType(QType::CDNSKEY), p.qdomain, d_sd.domain_id, &p);
150
151 while(B.get(rr)) {
152 rr.dr.d_ttl=d_sd.minimum;
153 r->addRecord(std::move(rr));
154 haveOne=true;
155 }
156 }
157 return haveOne;
158 }
159
160 /**
161 * This adds DNSKEY records to the answer packet. Returns true if one was added.
162 *
163 * @param p Pointer to the DNSPacket containing the original question
164 * @param r Pointer to the DNSPacket where the records should be inserted into
165 * @return bool that shows if any records were added
166 **/
167 bool PacketHandler::addDNSKEY(DNSPacket& p, std::unique_ptr<DNSPacket>& r)
168 {
169 DNSZoneRecord rr;
170 bool haveOne=false;
171
172 DNSSECKeeper::keyset_t keyset = d_dk.getKeys(p.qdomain);
173 for(const auto& value: keyset) {
174 if (!value.second.published) {
175 continue;
176 }
177 rr.dr.d_type=QType::DNSKEY;
178 rr.dr.d_ttl=d_sd.minimum;
179 rr.dr.d_name=p.qdomain;
180 rr.dr.setContent(std::make_shared<DNSKEYRecordContent>(value.first.getDNSKEY()));
181 rr.auth=true;
182 r->addRecord(std::move(rr));
183 haveOne=true;
184 }
185
186 if(::arg().mustDo("direct-dnskey")) {
187 B.lookup(QType(QType::DNSKEY), p.qdomain, d_sd.domain_id, &p);
188
189 while(B.get(rr)) {
190 rr.dr.d_ttl=d_sd.minimum;
191 r->addRecord(std::move(rr));
192 haveOne=true;
193 }
194 }
195
196 return haveOne;
197 }
198
199 /**
200 * This adds CDS records to the answer packet r.
201 *
202 * @param p Pointer to the DNSPacket containing the original question.
203 * @param r Pointer to the DNSPacket where the records should be inserted into.
204 * used to determine record TTL.
205 * @return bool that shows if any records were added.
206 **/
207 bool PacketHandler::addCDS(DNSPacket& p, std::unique_ptr<DNSPacket>& r)
208 {
209 string publishCDS;
210 d_dk.getPublishCDS(p.qdomain, publishCDS);
211 if (publishCDS.empty())
212 return false;
213
214 vector<string> digestAlgos;
215 stringtok(digestAlgos, publishCDS, ", ");
216
217 DNSZoneRecord rr;
218 rr.dr.d_type=QType::CDS;
219 rr.dr.d_ttl=d_sd.minimum;
220 rr.dr.d_name=p.qdomain;
221 rr.auth=true;
222
223 if(std::find(digestAlgos.begin(), digestAlgos.end(), "0") != digestAlgos.end()) { // delete DS via CDS
224 rr.dr.setContent(s_deleteCDSContent);
225 r->addRecord(std::move(rr));
226 return true;
227 }
228
229 bool haveOne=false;
230
231 DNSSECKeeper::keyset_t keyset = d_dk.getEntryPoints(p.qdomain);
232
233 for(auto const &value : keyset) {
234 if (!value.second.published) {
235 continue;
236 }
237 for(auto const &digestAlgo : digestAlgos){
238 rr.dr.setContent(std::make_shared<DSRecordContent>(makeDSFromDNSKey(p.qdomain, value.first.getDNSKEY(), pdns::checked_stoi<uint8_t>(digestAlgo))));
239 r->addRecord(DNSZoneRecord(rr));
240 haveOne=true;
241 }
242 }
243
244 if(::arg().mustDo("direct-dnskey")) {
245 B.lookup(QType(QType::CDS), p.qdomain, d_sd.domain_id, &p);
246
247 while(B.get(rr)) {
248 rr.dr.d_ttl=d_sd.minimum;
249 r->addRecord(std::move(rr));
250 haveOne=true;
251 }
252 }
253
254 return haveOne;
255 }
256
257 /** This adds NSEC3PARAM records. Returns true if one was added */
258 bool PacketHandler::addNSEC3PARAM(const DNSPacket& p, std::unique_ptr<DNSPacket>& r)
259 {
260 DNSZoneRecord rr;
261
262 NSEC3PARAMRecordContent ns3prc;
263 if(d_dk.getNSEC3PARAM(p.qdomain, &ns3prc)) {
264 rr.dr.d_type=QType::NSEC3PARAM;
265 rr.dr.d_ttl=d_sd.minimum;
266 rr.dr.d_name=p.qdomain;
267 ns3prc.d_flags = 0; // the NSEC3PARAM 'flag' is defined to always be zero in RFC5155.
268 rr.dr.setContent(std::make_shared<NSEC3PARAMRecordContent>(ns3prc));
269 rr.auth = true;
270 r->addRecord(std::move(rr));
271 return true;
272 }
273 return false;
274 }
275
276
277 // This is our chaos class requests handler. Return 1 if content was added, 0 if it wasn't
278 int PacketHandler::doChaosRequest(const DNSPacket& p, std::unique_ptr<DNSPacket>& r, DNSName &target) const
279 {
280 DNSZoneRecord rr;
281
282 if(p.qtype.getCode()==QType::TXT) {
283 static const DNSName versionbind("version.bind."), versionpdns("version.pdns."), idserver("id.server.");
284 if (target==versionbind || target==versionpdns) {
285 // modes: full, powerdns only, anonymous or custom
286 const static string mode=::arg()["version-string"];
287 string content;
288 if(mode.empty() || mode=="full")
289 content=fullVersionString();
290 else if(mode=="powerdns")
291 content="Served by PowerDNS - https://www.powerdns.com/";
292 else if(mode=="anonymous") {
293 r->setRcode(RCode::ServFail);
294 return 0;
295 }
296 else
297 content=mode;
298 rr.dr.setContent(DNSRecordContent::mastermake(QType::TXT, 1, "\""+content+"\""));
299 }
300 else if (target==idserver) {
301 // modes: disabled, hostname or custom
302 const static string id=::arg()["server-id"];
303
304 if (id == "disabled") {
305 r->setRcode(RCode::Refused);
306 return 0;
307 }
308 string tid=id;
309 if(!tid.empty() && tid[0]!='"') { // see #6010 however
310 tid = "\"" + tid + "\"";
311 }
312 rr.dr.setContent(DNSRecordContent::mastermake(QType::TXT, 1, tid));
313 }
314 else {
315 r->setRcode(RCode::Refused);
316 return 0;
317 }
318
319 rr.dr.d_ttl=5;
320 rr.dr.d_name=target;
321 rr.dr.d_type=QType::TXT;
322 rr.dr.d_class=QClass::CHAOS;
323 r->addRecord(std::move(rr));
324 return 1;
325 }
326
327 r->setRcode(RCode::NotImp);
328 return 0;
329 }
330
331 vector<DNSZoneRecord> PacketHandler::getBestReferralNS(DNSPacket& p, const DNSName &target)
332 {
333 vector<DNSZoneRecord> ret;
334 DNSZoneRecord rr;
335 DNSName subdomain(target);
336 do {
337 if(subdomain == d_sd.qname) // stop at SOA
338 break;
339 B.lookup(QType(QType::NS), subdomain, d_sd.domain_id, &p);
340 while(B.get(rr)) {
341 ret.push_back(rr); // this used to exclude auth NS records for some reason
342 }
343 if(!ret.empty())
344 return ret;
345 } while( subdomain.chopOff() ); // 'www.powerdns.org' -> 'powerdns.org' -> 'org' -> ''
346 return ret;
347 }
348
349 void PacketHandler::getBestDNAMESynth(DNSPacket& p, DNSName &target, vector<DNSZoneRecord> &ret)
350 {
351 ret.clear();
352 DNSZoneRecord rr;
353 DNSName prefix;
354 DNSName subdomain(target);
355 do {
356 DLOG(g_log<<"Attempting DNAME lookup for "<<subdomain<<", d_sd.qname="<<d_sd.qname<<endl);
357
358 B.lookup(QType(QType::DNAME), subdomain, d_sd.domain_id, &p);
359 while(B.get(rr)) {
360 ret.push_back(rr); // put in the original
361 rr.dr.d_type = QType::CNAME;
362 rr.dr.d_name = prefix + rr.dr.d_name;
363 rr.dr.setContent(std::make_shared<CNAMERecordContent>(CNAMERecordContent(prefix + getRR<DNAMERecordContent>(rr.dr)->getTarget())));
364 rr.auth = false; // don't sign CNAME
365 target = getRR<CNAMERecordContent>(rr.dr)->getTarget();
366 ret.push_back(rr);
367 }
368 if(!ret.empty())
369 return;
370 if(subdomain.countLabels())
371 prefix.appendRawLabel(subdomain.getRawLabels()[0]); // XXX DNSName pain this feels wrong
372 if(subdomain == d_sd.qname) // stop at SOA
373 break;
374
375 } while( subdomain.chopOff() ); // 'www.powerdns.org' -> 'powerdns.org' -> 'org' -> ''
376 return;
377 }
378
379
380 // Return best matching wildcard or next closer name
381 bool PacketHandler::getBestWildcard(DNSPacket& p, const DNSName &target, DNSName &wildcard, vector<DNSZoneRecord>* ret)
382 {
383 ret->clear();
384 DNSZoneRecord rr;
385 DNSName subdomain(target);
386 bool haveSomething=false;
387
388 #ifdef HAVE_LUA_RECORDS
389 bool doLua=g_doLuaRecord;
390 if(!doLua) {
391 string val;
392 d_dk.getFromMeta(d_sd.qname, "ENABLE-LUA-RECORDS", val);
393 doLua = (val=="1");
394 }
395 #endif
396
397 wildcard=subdomain;
398 while( subdomain.chopOff() && !haveSomething ) {
399 if (subdomain.empty()) {
400 B.lookup(QType(QType::ANY), g_wildcarddnsname, d_sd.domain_id, &p);
401 } else {
402 B.lookup(QType(QType::ANY), g_wildcarddnsname+subdomain, d_sd.domain_id, &p);
403 }
404 while(B.get(rr)) {
405 #ifdef HAVE_LUA_RECORDS
406 if (rr.dr.d_type == QType::LUA && !d_dk.isPresigned(d_sd.qname)) {
407 if(!doLua) {
408 DLOG(g_log<<"Have a wildcard LUA match, but not doing LUA record for this zone"<<endl);
409 continue;
410 }
411
412 DLOG(g_log<<"Have a wildcard LUA match"<<endl);
413
414 auto rec=getRR<LUARecordContent>(rr.dr);
415 if (!rec) {
416 continue;
417 }
418 if(rec->d_type == QType::CNAME || rec->d_type == p.qtype.getCode() || (p.qtype.getCode() == QType::ANY && rec->d_type != QType::RRSIG)) {
419 // noCache=true;
420 DLOG(g_log<<"Executing Lua: '"<<rec->getCode()<<"'"<<endl);
421 try {
422 auto recvec=luaSynth(rec->getCode(), target, d_sd.qname, d_sd.domain_id, p, rec->d_type, s_LUA);
423 for (const auto& r : recvec) {
424 rr.dr.d_type = rec->d_type; // might be CNAME
425 rr.dr.setContent(r);
426 rr.scopeMask = p.getRealRemote().getBits(); // this makes sure answer is a specific as your question
427 ret->push_back(rr);
428 }
429 }
430 catch (std::exception &e) {
431 while (B.get(rr)) ; // don't leave DB handle in bad state
432
433 throw;
434 }
435 }
436 }
437 else
438 #endif
439 if(rr.dr.d_type != QType::ENT && (rr.dr.d_type == p.qtype.getCode() || rr.dr.d_type == QType::CNAME || (p.qtype.getCode() == QType::ANY && rr.dr.d_type != QType::RRSIG))) {
440 ret->push_back(rr);
441 }
442
443 wildcard=g_wildcarddnsname+subdomain;
444 haveSomething=true;
445 }
446
447 if ( subdomain == d_sd.qname || haveSomething ) // stop at SOA or result
448 break;
449
450 B.lookup(QType(QType::ANY), subdomain, d_sd.domain_id, &p);
451 if (B.get(rr)) {
452 DLOG(g_log<<"No wildcard match, ancestor exists"<<endl);
453 while (B.get(rr)) ;
454 break;
455 }
456 wildcard=subdomain;
457 }
458
459 return haveSomething;
460 }
461
462 DNSName PacketHandler::doAdditionalServiceProcessing(const DNSName &firstTarget, const uint16_t &qtype, std::unique_ptr<DNSPacket>& /* r */, vector<DNSZoneRecord>& extraRecords) {
463 DNSName ret = firstTarget;
464 size_t ctr = 5; // Max 5 SVCB Aliasforms per query
465 bool done = false;
466 while (!done && ctr > 0) {
467 DNSZoneRecord rr;
468 done = true;
469
470 if(!ret.isPartOf(d_sd.qname)) {
471 continue;
472 }
473
474 B.lookup(QType(qtype), ret, d_sd.domain_id);
475 while (B.get(rr)) {
476 rr.dr.d_place = DNSResourceRecord::ADDITIONAL;
477 switch (qtype) {
478 case QType::SVCB: /* fall-through */
479 case QType::HTTPS: {
480 auto rrc = getRR<SVCBBaseRecordContent>(rr.dr);
481 extraRecords.push_back(std::move(rr));
482 ret = rrc->getTarget().isRoot() ? ret : rrc->getTarget();
483 if (rrc->getPriority() == 0) {
484 done = false;
485 }
486 break;
487 }
488 default:
489 while (B.get(rr)) ; // don't leave DB handle in bad state
490
491 throw PDNSException("Unknown type (" + QType(qtype).toString() + ") for additional service processing");
492 }
493 }
494 ctr--;
495 }
496 return ret;
497 }
498
499
500 void PacketHandler::doAdditionalProcessing(DNSPacket& p, std::unique_ptr<DNSPacket>& r)
501 {
502 DNSName content;
503 std::unordered_set<DNSName> lookup;
504 vector<DNSZoneRecord> extraRecords;
505 const auto& rrs = r->getRRS();
506
507 lookup.reserve(rrs.size());
508 for(auto& rr : rrs) {
509 if(rr.dr.d_place != DNSResourceRecord::ADDITIONAL) {
510 switch(rr.dr.d_type) {
511 case QType::NS:
512 content=getRR<NSRecordContent>(rr.dr)->getNS();
513 break;
514 case QType::MX:
515 content=getRR<MXRecordContent>(rr.dr)->d_mxname;
516 break;
517 case QType::SRV:
518 content=getRR<SRVRecordContent>(rr.dr)->d_target;
519 break;
520 case QType::SVCB: /* fall-through */
521 case QType::HTTPS: {
522 auto rrc = getRR<SVCBBaseRecordContent>(rr.dr);
523 content = rrc->getTarget();
524 if (content.isRoot()) {
525 content = rr.dr.d_name;
526 }
527 if (rrc->getPriority() == 0) {
528 content = doAdditionalServiceProcessing(content, rr.dr.d_type, r, extraRecords);
529 }
530 break;
531 }
532 default:
533 continue;
534 }
535 if(content.isPartOf(d_sd.qname)) {
536 lookup.emplace(content);
537 }
538 }
539 }
540
541 for(auto& rr : extraRecords) {
542 r->addRecord(std::move(rr));
543 }
544 extraRecords.clear();
545 // TODO should we have a setting to do this?
546 for (auto &rec : r->getServiceRecords()) {
547 // Process auto hints
548 auto rrc = getRR<SVCBBaseRecordContent>(rec->dr);
549 DNSName target = rrc->getTarget().isRoot() ? rec->dr.d_name : rrc->getTarget();
550
551 if (rrc->hasParam(SvcParam::ipv4hint) && rrc->autoHint(SvcParam::ipv4hint)) {
552 auto newRRC = rrc->clone();
553 if (!newRRC) {
554 continue;
555 }
556 if (s_SVCAutohints) {
557 auto hints = getIPAddressFor(target, QType::A);
558 if (hints.size() == 0) {
559 newRRC->removeParam(SvcParam::ipv4hint);
560 } else {
561 newRRC->setHints(SvcParam::ipv4hint, hints);
562 }
563 } else {
564 newRRC->removeParam(SvcParam::ipv4hint);
565 }
566 rrc = newRRC;
567 rec->dr.setContent(std::move(newRRC));
568 }
569
570 if (rrc->hasParam(SvcParam::ipv6hint) && rrc->autoHint(SvcParam::ipv6hint)) {
571 auto newRRC = rrc->clone();
572 if (!newRRC) {
573 continue;
574 }
575 if (s_SVCAutohints) {
576 auto hints = getIPAddressFor(target, QType::AAAA);
577 if (hints.size() == 0) {
578 newRRC->removeParam(SvcParam::ipv6hint);
579 } else {
580 newRRC->setHints(SvcParam::ipv6hint, hints);
581 }
582 } else {
583 newRRC->removeParam(SvcParam::ipv6hint);
584 }
585 rec->dr.setContent(std::move(newRRC));
586 }
587 }
588
589 DNSZoneRecord dzr;
590 for(const auto& name : lookup) {
591 B.lookup(QType(QType::ANY), name, d_sd.domain_id, &p);
592 while(B.get(dzr)) {
593 if(dzr.dr.d_type == QType::A || dzr.dr.d_type == QType::AAAA) {
594 dzr.dr.d_place=DNSResourceRecord::ADDITIONAL;
595 r->addRecord(std::move(dzr));
596 }
597 }
598 }
599 }
600
601 vector<ComboAddress> PacketHandler::getIPAddressFor(const DNSName &target, const uint16_t qtype) {
602 vector<ComboAddress> ret;
603 if (qtype != QType::A && qtype != QType::AAAA) {
604 return ret;
605 }
606 B.lookup(qtype, target, d_sd.domain_id);
607 DNSZoneRecord rr;
608 while (B.get(rr)) {
609 if (qtype == QType::AAAA) {
610 auto aaaarrc = getRR<AAAARecordContent>(rr.dr);
611 ret.push_back(aaaarrc->getCA());
612 } else if (qtype == QType::A) {
613 auto arrc = getRR<ARecordContent>(rr.dr);
614 ret.push_back(arrc->getCA());
615 }
616 }
617 return ret;
618 }
619
620 void PacketHandler::emitNSEC(std::unique_ptr<DNSPacket>& r, const DNSName& name, const DNSName& next, int mode)
621 {
622 NSECRecordContent nrc;
623 nrc.d_next = next;
624
625 nrc.set(QType::NSEC);
626 nrc.set(QType::RRSIG);
627 if(d_sd.qname == name) {
628 nrc.set(QType::SOA); // 1dfd8ad SOA can live outside the records table
629 if(!d_dk.isPresigned(d_sd.qname)) {
630 auto keyset = d_dk.getKeys(name);
631 for(const auto& value: keyset) {
632 if (value.second.published) {
633 nrc.set(QType::DNSKEY);
634 string publishCDNSKEY;
635 d_dk.getPublishCDNSKEY(name, publishCDNSKEY);
636 if (! publishCDNSKEY.empty())
637 nrc.set(QType::CDNSKEY);
638 string publishCDS;
639 d_dk.getPublishCDS(name, publishCDS);
640 if (! publishCDS.empty())
641 nrc.set(QType::CDS);
642 break;
643 }
644 }
645 }
646 }
647
648 DNSZoneRecord rr;
649 #ifdef HAVE_LUA_RECORDS
650 bool first{true};
651 bool doLua{false};
652 #endif
653
654 B.lookup(QType(QType::ANY), name, d_sd.domain_id);
655 while(B.get(rr)) {
656 #ifdef HAVE_LUA_RECORDS
657 if (rr.dr.d_type == QType::LUA && first && !d_dk.isPresigned(d_sd.qname)) {
658 first = false;
659 doLua = g_doLuaRecord;
660 if (!doLua) {
661 string val;
662 d_dk.getFromMeta(d_sd.qname, "ENABLE-LUA-RECORDS", val);
663 doLua = (val == "1");
664 }
665 }
666
667 if (rr.dr.d_type == QType::LUA && doLua) {
668 nrc.set(getRR<LUARecordContent>(rr.dr)->d_type);
669 }
670 else
671 #endif
672 if (d_doExpandALIAS && rr.dr.d_type == QType::ALIAS) {
673 // Set the A and AAAA in the NSEC bitmap so aggressive NSEC
674 // does not falsely deny the type for this name.
675 // This does NOT add the ALIAS to the bitmap, as that record cannot
676 // be requested.
677 if (!d_dk.isPresigned(d_sd.qname)) {
678 nrc.set(QType::A);
679 nrc.set(QType::AAAA);
680 }
681 }
682 else if((rr.dr.d_type == QType::DNSKEY || rr.dr.d_type == QType::CDS || rr.dr.d_type == QType::CDNSKEY) && !d_dk.isPresigned(d_sd.qname) && !::arg().mustDo("direct-dnskey")) {
683 continue;
684 }
685 else if(rr.dr.d_type == QType::NS || rr.auth) {
686 nrc.set(rr.dr.d_type);
687 }
688 }
689
690 rr.dr.d_name = name;
691 rr.dr.d_ttl = d_sd.getNegativeTTL();
692 rr.dr.d_type = QType::NSEC;
693 rr.dr.setContent(std::make_shared<NSECRecordContent>(std::move(nrc)));
694 rr.dr.d_place = (mode == 5 ) ? DNSResourceRecord::ANSWER: DNSResourceRecord::AUTHORITY;
695 rr.auth = true;
696
697 r->addRecord(std::move(rr));
698 }
699
700 void PacketHandler::emitNSEC3(std::unique_ptr<DNSPacket>& r, const NSEC3PARAMRecordContent& ns3prc, const DNSName& name, const string& namehash, const string& nexthash, int mode)
701 {
702 NSEC3RecordContent n3rc;
703 n3rc.d_algorithm = ns3prc.d_algorithm;
704 n3rc.d_flags = ns3prc.d_flags;
705 n3rc.d_iterations = ns3prc.d_iterations;
706 n3rc.d_salt = ns3prc.d_salt;
707 n3rc.d_nexthash = nexthash;
708
709 DNSZoneRecord rr;
710
711 if(!name.empty()) {
712 if (d_sd.qname == name) {
713 n3rc.set(QType::SOA); // 1dfd8ad SOA can live outside the records table
714 n3rc.set(QType::NSEC3PARAM);
715 if(!d_dk.isPresigned(d_sd.qname)) {
716 auto keyset = d_dk.getKeys(name);
717 for(const auto& value: keyset) {
718 if (value.second.published) {
719 n3rc.set(QType::DNSKEY);
720 string publishCDNSKEY;
721 d_dk.getPublishCDNSKEY(name, publishCDNSKEY);
722 if (! publishCDNSKEY.empty())
723 n3rc.set(QType::CDNSKEY);
724 string publishCDS;
725 d_dk.getPublishCDS(name, publishCDS);
726 if (! publishCDS.empty())
727 n3rc.set(QType::CDS);
728 break;
729 }
730 }
731 }
732 }
733
734 #ifdef HAVE_LUA_RECORDS
735 bool first{true};
736 bool doLua{false};
737 #endif
738
739 B.lookup(QType(QType::ANY), name, d_sd.domain_id);
740 while(B.get(rr)) {
741 #ifdef HAVE_LUA_RECORDS
742 if (rr.dr.d_type == QType::LUA && first && !d_dk.isPresigned(d_sd.qname)) {
743 first = false;
744 doLua = g_doLuaRecord;
745 if (!doLua) {
746 string val;
747 d_dk.getFromMeta(d_sd.qname, "ENABLE-LUA-RECORDS", val);
748 doLua = (val == "1");
749 }
750 }
751
752 if (rr.dr.d_type == QType::LUA && doLua) {
753 n3rc.set(getRR<LUARecordContent>(rr.dr)->d_type);
754 }
755 else
756 #endif
757 if (d_doExpandALIAS && rr.dr.d_type == QType::ALIAS) {
758 // Set the A and AAAA in the NSEC3 bitmap so aggressive NSEC
759 // does not falsely deny the type for this name.
760 // This does NOT add the ALIAS to the bitmap, as that record cannot
761 // be requested.
762 if (!d_dk.isPresigned(d_sd.qname)) {
763 n3rc.set(QType::A);
764 n3rc.set(QType::AAAA);
765 }
766 }
767 else if((rr.dr.d_type == QType::DNSKEY || rr.dr.d_type == QType::CDS || rr.dr.d_type == QType::CDNSKEY) && !d_dk.isPresigned(d_sd.qname) && !::arg().mustDo("direct-dnskey")) {
768 continue;
769 }
770 else if(rr.dr.d_type && (rr.dr.d_type == QType::NS || rr.auth)) {
771 // skip empty non-terminals
772 n3rc.set(rr.dr.d_type);
773 }
774 }
775 }
776
777 const auto numberOfTypesSet = n3rc.numberOfTypesSet();
778 if (numberOfTypesSet != 0 && !(numberOfTypesSet == 1 && n3rc.isSet(QType::NS))) {
779 n3rc.set(QType::RRSIG);
780 }
781
782 rr.dr.d_name = DNSName(toBase32Hex(namehash))+d_sd.qname;
783 rr.dr.d_ttl = d_sd.getNegativeTTL();
784 rr.dr.d_type=QType::NSEC3;
785 rr.dr.setContent(std::make_shared<NSEC3RecordContent>(std::move(n3rc)));
786 rr.dr.d_place = (mode == 5 ) ? DNSResourceRecord::ANSWER: DNSResourceRecord::AUTHORITY;
787 rr.auth = true;
788
789 r->addRecord(std::move(rr));
790 }
791
792 /*
793 mode 0 = No Data Responses, QTYPE is not DS
794 mode 1 = No Data Responses, QTYPE is DS
795 mode 2 = Wildcard No Data Responses
796 mode 3 = Wildcard Answer Responses
797 mode 4 = Name Error Responses
798 mode 5 = Direct NSEC request
799 */
800 void PacketHandler::addNSECX(DNSPacket& p, std::unique_ptr<DNSPacket>& r, const DNSName& target, const DNSName& wildcard, int mode)
801 {
802 NSEC3PARAMRecordContent ns3rc;
803 bool narrow = false;
804 if(d_dk.getNSEC3PARAM(d_sd.qname, &ns3rc, &narrow)) {
805 if (mode != 5) // no direct NSEC3 queries, rfc5155 7.2.8
806 addNSEC3(p, r, target, wildcard, ns3rc, narrow, mode);
807 }
808 else {
809 addNSEC(p, r, target, wildcard, mode);
810 }
811 }
812
813 bool PacketHandler::getNSEC3Hashes(bool narrow, const std::string& hashed, bool decrement, DNSName& unhashed, std::string& before, std::string& after, int mode)
814 {
815 bool ret;
816 if(narrow) { // nsec3-narrow
817 ret=true;
818 before=hashed;
819 if(decrement) {
820 decrementHash(before);
821 unhashed.clear();
822 }
823 after=hashed;
824 incrementHash(after);
825 }
826 else {
827 DNSName hashedName = DNSName(toBase32Hex(hashed));
828 DNSName beforeName, afterName;
829 if (!decrement && mode >= 2)
830 beforeName = hashedName;
831 ret=d_sd.db->getBeforeAndAfterNamesAbsolute(d_sd.domain_id, hashedName, unhashed, beforeName, afterName);
832 before=fromBase32Hex(beforeName.toString());
833 after=fromBase32Hex(afterName.toString());
834 }
835 return ret;
836 }
837
838 void PacketHandler::addNSEC3(DNSPacket& p, std::unique_ptr<DNSPacket>& r, const DNSName& target, const DNSName& wildcard, const NSEC3PARAMRecordContent& ns3rc, bool narrow, int mode)
839 {
840 DLOG(g_log<<"addNSEC3() mode="<<mode<<" auth="<<d_sd.qname<<" target="<<target<<" wildcard="<<wildcard<<endl);
841
842 if (d_sd.db == nullptr) {
843 if(!B.getSOAUncached(d_sd.qname, d_sd)) {
844 DLOG(g_log<<"Could not get SOA for domain");
845 return;
846 }
847 }
848
849 bool doNextcloser = false;
850 string before, after, hashed;
851 DNSName unhashed, closest;
852
853 if (mode == 2 || mode == 3 || mode == 4) {
854 closest=wildcard;
855 closest.chopOff();
856 } else
857 closest=target;
858
859 // add matching NSEC3 RR
860 if (mode != 3) {
861 unhashed=(mode == 0 || mode == 1 || mode == 5) ? target : closest;
862 hashed=hashQNameWithSalt(ns3rc, unhashed);
863 DLOG(g_log<<"1 hash: "<<toBase32Hex(hashed)<<" "<<unhashed<<endl);
864
865 getNSEC3Hashes(narrow, hashed, false, unhashed, before, after, mode);
866
867 if (((mode == 0 && ns3rc.d_flags) || mode == 1) && (hashed != before)) {
868 DLOG(g_log<<"No matching NSEC3, do closest (provable) encloser"<<endl);
869
870 bool doBreak = false;
871 DNSZoneRecord rr;
872 while( closest.chopOff() && (closest != d_sd.qname)) { // stop at SOA
873 B.lookup(QType(QType::ANY), closest, d_sd.domain_id, &p);
874 while(B.get(rr))
875 if (rr.auth)
876 doBreak = true;
877 if(doBreak)
878 break;
879 }
880 doNextcloser = true;
881 unhashed=closest;
882 hashed=hashQNameWithSalt(ns3rc, unhashed);
883 DLOG(g_log<<"1 hash: "<<toBase32Hex(hashed)<<" "<<unhashed<<endl);
884
885 getNSEC3Hashes(narrow, hashed, false, unhashed, before, after);
886 }
887
888 if (!after.empty()) {
889 DLOG(g_log<<"Done calling for matching, hashed: '"<<toBase32Hex(hashed)<<"' before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"'"<<endl);
890 emitNSEC3(r, ns3rc, unhashed, before, after, mode);
891 }
892 }
893
894 // add covering NSEC3 RR
895 if ((mode >= 2 && mode <= 4) || doNextcloser) {
896 DNSName next(target);
897 do {
898 unhashed=next;
899 }
900 while( next.chopOff() && !(next==closest));
901
902 hashed=hashQNameWithSalt(ns3rc, unhashed);
903 DLOG(g_log<<"2 hash: "<<toBase32Hex(hashed)<<" "<<unhashed<<endl);
904
905 getNSEC3Hashes(narrow, hashed, true, unhashed, before, after);
906 DLOG(g_log<<"Done calling for covering, hashed: '"<<toBase32Hex(hashed)<<"' before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"'"<<endl);
907 emitNSEC3( r, ns3rc, unhashed, before, after, mode);
908 }
909
910 // wildcard denial
911 if (mode == 2 || mode == 4) {
912 unhashed=g_wildcarddnsname+closest;
913
914 hashed=hashQNameWithSalt(ns3rc, unhashed);
915 DLOG(g_log<<"3 hash: "<<toBase32Hex(hashed)<<" "<<unhashed<<endl);
916
917 getNSEC3Hashes(narrow, hashed, (mode != 2), unhashed, before, after);
918 DLOG(g_log<<"Done calling for '*', hashed: '"<<toBase32Hex(hashed)<<"' before='"<<toBase32Hex(before)<<"', after='"<<toBase32Hex(after)<<"'"<<endl);
919 emitNSEC3( r, ns3rc, unhashed, before, after, mode);
920 }
921 }
922
923 void PacketHandler::addNSEC(DNSPacket& /* p */, std::unique_ptr<DNSPacket>& r, const DNSName& target, const DNSName& wildcard, int mode)
924 {
925 DLOG(g_log<<"addNSEC() mode="<<mode<<" auth="<<d_sd.qname<<" target="<<target<<" wildcard="<<wildcard<<endl);
926
927 if (d_sd.db == nullptr) {
928 if(!B.getSOAUncached(d_sd.qname, d_sd)) {
929 DLOG(g_log<<"Could not get SOA for domain"<<endl);
930 return;
931 }
932 }
933
934 DNSName before,after;
935 d_sd.db->getBeforeAndAfterNames(d_sd.domain_id, d_sd.qname, target, before, after);
936 if (mode != 5 || before == target)
937 emitNSEC(r, before, after, mode);
938
939 if (mode == 2 || mode == 4) {
940 // wildcard NO-DATA or wildcard denial
941 before.clear();
942 DNSName closest(wildcard);
943 if (mode == 4) {
944 closest.chopOff();
945 closest.prependRawLabel("*");
946 }
947 d_sd.db->getBeforeAndAfterNames(d_sd.domain_id, d_sd.qname, closest, before, after);
948 emitNSEC(r, before, after, mode);
949 }
950 return;
951 }
952
953 /* Semantics:
954
955 - only one backend owns the SOA of a zone
956 - only one AXFR per zone at a time - double startTransaction should fail
957 - backends need to implement transaction semantics
958
959
960 How BindBackend would implement this:
961 startTransaction makes a file
962 feedRecord sends everything to that file
963 commitTransaction moves that file atomically over the regular file, and triggers a reload
964 rollbackTransaction removes the file
965
966
967 How PostgreSQLBackend would implement this:
968 startTransaction starts a sql transaction, which also deletes all records
969 feedRecord is an insert statement
970 commitTransaction commits the transaction
971 rollbackTransaction aborts it
972
973 How MySQLBackend would implement this:
974 (good question!)
975
976 */
977
978 int PacketHandler::trySuperMaster(const DNSPacket& p, const DNSName& tsigkeyname)
979 {
980 if(p.d_tcp)
981 {
982 // do it right now if the client is TCP
983 // rarely happens
984 return trySuperMasterSynchronous(p, tsigkeyname);
985 }
986 else
987 {
988 // queue it if the client is on UDP
989 Communicator.addTrySuperMasterRequest(p);
990 return 0;
991 }
992 }
993
994 int PacketHandler::trySuperMasterSynchronous(const DNSPacket& p, const DNSName& tsigkeyname)
995 {
996 ComboAddress remote = p.getInnerRemote();
997 if(p.hasEDNSSubnet() && pdns::isAddressTrustedNotificationProxy(remote)) {
998 remote = p.getRealRemote().getNetwork();
999 }
1000 else {
1001 remote = p.getInnerRemote();
1002 }
1003 remote.setPort(53);
1004
1005 Resolver::res_t nsset;
1006 try {
1007 Resolver resolver;
1008 uint32_t theirserial;
1009 resolver.getSoaSerial(remote, p.qdomain, &theirserial);
1010 resolver.resolve(remote, p.qdomain, QType::NS, &nsset);
1011 }
1012 catch(ResolverException &re) {
1013 g_log<<Logger::Error<<"Error resolving SOA or NS for "<<p.qdomain<<" at: "<< remote <<": "<<re.reason<<endl;
1014 return RCode::ServFail;
1015 }
1016
1017 // check if the returned records are NS records
1018 bool haveNS=false;
1019 for(const auto& ns: nsset) {
1020 if(ns.qtype==QType::NS)
1021 haveNS=true;
1022 }
1023
1024 if(!haveNS) {
1025 g_log<<Logger::Error<<"While checking for supermaster, did not find NS for "<<p.qdomain<<" at: "<< remote <<endl;
1026 return RCode::ServFail;
1027 }
1028
1029 string nameserver, account;
1030 DNSBackend *db;
1031
1032 if (!::arg().mustDo("allow-unsigned-autoprimary") && tsigkeyname.empty()) {
1033 g_log<<Logger::Error<<"Received unsigned NOTIFY for "<<p.qdomain<<" from potential supermaster "<<remote<<". Refusing."<<endl;
1034 return RCode::Refused;
1035 }
1036
1037 if(!B.superMasterBackend(remote.toString(), p.qdomain, nsset, &nameserver, &account, &db)) {
1038 g_log<<Logger::Error<<"Unable to find backend willing to host "<<p.qdomain<<" for potential supermaster "<<remote<<". Remote nameservers: "<<endl;
1039 for(const auto& rr: nsset) {
1040 if(rr.qtype==QType::NS)
1041 g_log<<Logger::Error<<rr.content<<endl;
1042 }
1043 return RCode::Refused;
1044 }
1045 try {
1046 db->createSlaveDomain(remote.toString(), p.qdomain, nameserver, account);
1047 DomainInfo di;
1048 if (!db->getDomainInfo(p.qdomain, di, false)) {
1049 g_log << Logger::Error << "Failed to create " << p.qdomain << " for potential supermaster " << remote << endl;
1050 return RCode::ServFail;
1051 }
1052 g_zoneCache.add(p.qdomain, di.id);
1053 if (tsigkeyname.empty() == false) {
1054 vector<string> meta;
1055 meta.push_back(tsigkeyname.toStringNoDot());
1056 db->setDomainMetadata(p.qdomain, "AXFR-MASTER-TSIG", meta);
1057 }
1058 }
1059 catch(PDNSException& ae) {
1060 g_log<<Logger::Error<<"Database error trying to create "<<p.qdomain<<" for potential supermaster "<<remote<<": "<<ae.reason<<endl;
1061 return RCode::ServFail;
1062 }
1063 g_log<<Logger::Warning<<"Created new slave zone '"<<p.qdomain<<"' from supermaster "<<remote<<endl;
1064 return RCode::NoError;
1065 }
1066
1067 int PacketHandler::processNotify(const DNSPacket& p)
1068 {
1069 /* now what?
1070 was this notification from an approved address?
1071 was this notification approved by TSIG?
1072 We determine our internal SOA id (via UeberBackend)
1073 We determine the SOA at our (known) master
1074 if master is higher -> do stuff
1075 */
1076
1077 g_log<<Logger::Debug<<"Received NOTIFY for "<<p.qdomain<<" from "<<p.getRemoteString()<<endl;
1078
1079 if(!::arg().mustDo("secondary") && s_forwardNotify.empty()) {
1080 g_log<<Logger::Warning<<"Received NOTIFY for "<<p.qdomain<<" from "<<p.getRemoteString()<<" but slave support is disabled in the configuration"<<endl;
1081 return RCode::Refused;
1082 }
1083
1084 // Sender verification
1085 //
1086 if(!s_allowNotifyFrom.match(p.getInnerRemote()) || p.d_havetsig) {
1087 if (p.d_havetsig && p.getTSIGKeyname().empty() == false) {
1088 g_log<<Logger::Notice<<"Received secure NOTIFY for "<<p.qdomain<<" from "<<p.getRemoteString()<<", with TSIG key '"<<p.getTSIGKeyname()<<"'"<<endl;
1089 } else {
1090 g_log<<Logger::Warning<<"Received NOTIFY for "<<p.qdomain<<" from "<<p.getRemoteString()<<" but the remote is not providing a TSIG key or in allow-notify-from (Refused)"<<endl;
1091 return RCode::Refused;
1092 }
1093 }
1094
1095 if ((!::arg().mustDo("allow-unsigned-notify") && !p.d_havetsig) || p.d_havetsig) {
1096 if (!p.d_havetsig) {
1097 g_log<<Logger::Warning<<"Received unsigned NOTIFY for "<<p.qdomain<<" from "<<p.getRemoteString()<<" while a TSIG key was required (Refused)"<<endl;
1098 return RCode::Refused;
1099 }
1100 vector<string> meta;
1101 if (B.getDomainMetadata(p.qdomain,"AXFR-MASTER-TSIG",meta) && meta.size() > 0) {
1102 DNSName expected{meta[0]};
1103 if (p.getTSIGKeyname() != expected) {
1104 g_log<<Logger::Warning<<"Received secure NOTIFY for "<<p.qdomain<<" from "<<p.getRemoteString()<<": expected TSIG key '"<<expected<<"', got '"<<p.getTSIGKeyname()<<"' (Refused)"<<endl;
1105 return RCode::Refused;
1106 }
1107 }
1108 }
1109
1110 // Domain verification
1111 //
1112 DomainInfo di;
1113 if(!B.getDomainInfo(p.qdomain, di, false) || !di.backend) {
1114 if(::arg().mustDo("autosecondary")) {
1115 g_log<<Logger::Warning<<"Received NOTIFY for "<<p.qdomain<<" from "<<p.getRemoteString()<<" for which we are not authoritative, trying supermaster"<<endl;
1116 return trySuperMaster(p, p.getTSIGKeyname());
1117 }
1118 g_log<<Logger::Notice<<"Received NOTIFY for "<<p.qdomain<<" from "<<p.getRemoteString()<<" for which we are not authoritative (Refused)"<<endl;
1119 return RCode::Refused;
1120 }
1121
1122 if(pdns::isAddressTrustedNotificationProxy(p.getInnerRemote())) {
1123 if(di.masters.empty()) {
1124 g_log<<Logger::Warning<<"Received NOTIFY for "<<p.qdomain<<" from trusted-notification-proxy "<<p.getRemoteString()<<", zone does not have any masters defined (Refused)"<<endl;
1125 return RCode::Refused;
1126 }
1127 g_log<<Logger::Notice<<"Received NOTIFY for "<<p.qdomain<<" from trusted-notification-proxy "<<p.getRemoteString()<<endl;
1128 }
1129 else if (::arg().mustDo("primary") && di.isPrimaryType()) {
1130 g_log << Logger::Warning << "Received NOTIFY for " << p.qdomain << " from " << p.getRemoteString() << " but we are primary (Refused)" << endl;
1131 return RCode::Refused;
1132 }
1133 else if(!di.isMaster(p.getInnerRemote())) {
1134 g_log<<Logger::Warning<<"Received NOTIFY for "<<p.qdomain<<" from "<<p.getRemoteString()<<" which is not a master (Refused)"<<endl;
1135 return RCode::Refused;
1136 }
1137
1138 if(!s_forwardNotify.empty()) {
1139 set<string> forwardNotify(s_forwardNotify);
1140 for(const auto & j : forwardNotify) {
1141 g_log<<Logger::Notice<<"Relaying notification of domain "<<p.qdomain<<" from "<<p.getRemoteString()<<" to "<<j<<endl;
1142 Communicator.notify(p.qdomain,j);
1143 }
1144 }
1145
1146 if(::arg().mustDo("secondary")) {
1147 g_log<<Logger::Notice<<"Received NOTIFY for "<<p.qdomain<<" from "<<p.getRemoteString()<<" - queueing check"<<endl;
1148 di.receivedNotify = true;
1149 Communicator.addSlaveCheckRequest(di, p.getInnerRemote());
1150 }
1151 return 0;
1152 }
1153
1154 static bool validDNSName(const DNSName& name)
1155 {
1156 if (!g_8bitDNS) {
1157 return name.has8bitBytes() == false;
1158 }
1159 return true;
1160 }
1161
1162 std::unique_ptr<DNSPacket> PacketHandler::question(DNSPacket& p)
1163 {
1164 std::unique_ptr<DNSPacket> ret{nullptr};
1165
1166 if(d_pdl)
1167 {
1168 ret=d_pdl->prequery(p);
1169 if(ret)
1170 return ret;
1171 }
1172
1173 if(p.d.rd) {
1174 static AtomicCounter &rdqueries=*S.getPointer("rd-queries");
1175 rdqueries++;
1176 }
1177
1178 return doQuestion(p);
1179 }
1180
1181
1182 void PacketHandler::makeNXDomain(DNSPacket& p, std::unique_ptr<DNSPacket>& r, const DNSName& target, const DNSName& wildcard)
1183 {
1184 DNSZoneRecord rr;
1185 rr=makeEditedDNSZRFromSOAData(d_dk, d_sd, DNSResourceRecord::AUTHORITY);
1186 rr.dr.d_ttl=d_sd.getNegativeTTL();
1187 r->addRecord(std::move(rr));
1188
1189 if(d_dnssec) {
1190 addNSECX(p, r, target, wildcard, 4);
1191 }
1192
1193 r->setRcode(RCode::NXDomain);
1194 }
1195
1196 void PacketHandler::makeNOError(DNSPacket& p, std::unique_ptr<DNSPacket>& r, const DNSName& target, const DNSName& wildcard, int mode)
1197 {
1198 DNSZoneRecord rr;
1199 rr=makeEditedDNSZRFromSOAData(d_dk, d_sd, DNSResourceRecord::AUTHORITY);
1200 rr.dr.d_ttl=d_sd.getNegativeTTL();
1201 r->addRecord(std::move(rr));
1202
1203 if(d_dnssec) {
1204 addNSECX(p, r, target, wildcard, mode);
1205 }
1206
1207 S.inc("noerror-packets");
1208 S.ringAccount("noerror-queries", p.qdomain, p.qtype);
1209 }
1210
1211
1212 bool PacketHandler::addDSforNS(DNSPacket& p, std::unique_ptr<DNSPacket>& r, const DNSName& dsname)
1213 {
1214 //cerr<<"Trying to find a DS for '"<<dsname<<"', domain_id = "<<d_sd.domain_id<<endl;
1215 B.lookup(QType(QType::DS), dsname, d_sd.domain_id, &p);
1216 DNSZoneRecord rr;
1217 bool gotOne=false;
1218 while(B.get(rr)) {
1219 gotOne=true;
1220 rr.dr.d_place = DNSResourceRecord::AUTHORITY;
1221 r->addRecord(std::move(rr));
1222 }
1223 return gotOne;
1224 }
1225
1226 bool PacketHandler::tryReferral(DNSPacket& p, std::unique_ptr<DNSPacket>& r, const DNSName &target, bool retargeted)
1227 {
1228 vector<DNSZoneRecord> rrset = getBestReferralNS(p, target);
1229 if(rrset.empty())
1230 return false;
1231
1232 DNSName name = rrset.begin()->dr.d_name;
1233 for(auto& rr: rrset) {
1234 rr.dr.d_place=DNSResourceRecord::AUTHORITY;
1235 r->addRecord(std::move(rr));
1236 }
1237 if(!retargeted)
1238 r->setA(false);
1239
1240 if(d_dk.isSecuredZone(d_sd.qname) && !addDSforNS(p, r, name) && d_dnssec) {
1241 addNSECX(p, r, name, DNSName(), 1);
1242 }
1243
1244 return true;
1245 }
1246
1247 void PacketHandler::completeANYRecords(DNSPacket& p, std::unique_ptr<DNSPacket>& r, const DNSName &target)
1248 {
1249 addNSECX(p, r, target, DNSName(), 5);
1250 if(d_sd.qname == p.qdomain) {
1251 if(!d_dk.isPresigned(d_sd.qname)) {
1252 addDNSKEY(p, r);
1253 addCDNSKEY(p, r);
1254 addCDS(p, r);
1255 }
1256 addNSEC3PARAM(p, r);
1257 }
1258 }
1259
1260 bool PacketHandler::tryDNAME(DNSPacket& p, std::unique_ptr<DNSPacket>& r, DNSName &target)
1261 {
1262 if(!d_doDNAME)
1263 return false;
1264 DLOG(g_log<<Logger::Warning<<"Let's try DNAME.."<<endl);
1265 vector<DNSZoneRecord> rrset;
1266 try {
1267 getBestDNAMESynth(p, target, rrset);
1268 if(!rrset.empty()) {
1269 for(size_t i = 0; i < rrset.size(); i++) {
1270 rrset.at(i).dr.d_place = DNSResourceRecord::ANSWER;
1271 r->addRecord(std::move(rrset.at(i)));
1272 }
1273 return true;
1274 }
1275 } catch (const std::range_error &e) {
1276 // Add the DNAME regardless, but throw to let the caller know we could not
1277 // synthesize a CNAME
1278 if(!rrset.empty()) {
1279 for(size_t i = 0; i < rrset.size(); i++) {
1280 rrset.at(i).dr.d_place = DNSResourceRecord::ANSWER;
1281 r->addRecord(std::move(rrset.at(i)));
1282 }
1283 }
1284 throw e;
1285 }
1286 return false;
1287 }
1288 bool PacketHandler::tryWildcard(DNSPacket& p, std::unique_ptr<DNSPacket>& r, DNSName &target, DNSName &wildcard, bool& retargeted, bool& nodata)
1289 {
1290 retargeted = nodata = false;
1291 DNSName bestmatch;
1292
1293 vector<DNSZoneRecord> rrset;
1294 if(!getBestWildcard(p, target, wildcard, &rrset))
1295 return false;
1296
1297 if(rrset.empty()) {
1298 DLOG(g_log<<"Wildcard matched something, but not of the correct type"<<endl);
1299 nodata=true;
1300 }
1301 else {
1302 for(auto& rr: rrset) {
1303 rr.wildcardname = rr.dr.d_name;
1304 rr.dr.d_name=bestmatch=target;
1305
1306 if(rr.dr.d_type == QType::CNAME) {
1307 retargeted=true;
1308 target=getRR<CNAMERecordContent>(rr.dr)->getTarget();
1309 }
1310
1311 rr.dr.d_place=DNSResourceRecord::ANSWER;
1312 r->addRecord(std::move(rr));
1313 }
1314 }
1315 if(d_dnssec && !nodata) {
1316 addNSECX(p, r, bestmatch, wildcard, 3);
1317 }
1318
1319 return true;
1320 }
1321
1322 //! Called by the Distributor to ask a question. Returns 0 in case of an error
1323 std::unique_ptr<DNSPacket> PacketHandler::doQuestion(DNSPacket& p)
1324 {
1325 DNSZoneRecord rr;
1326
1327 int retargetcount=0;
1328 set<DNSName> authSet;
1329
1330 vector<DNSZoneRecord> rrset;
1331 bool weDone=false, weRedirected=false, weHaveUnauth=false, doSigs=false;
1332 DNSName haveAlias;
1333 uint8_t aliasScopeMask;
1334
1335 std::unique_ptr<DNSPacket> r{nullptr};
1336 bool noCache=false;
1337
1338 #ifdef HAVE_LUA_RECORDS
1339 bool doLua=g_doLuaRecord;
1340 #endif
1341
1342 if(p.d.qr) { // QR bit from dns packet (thanks RA from N)
1343 if(d_logDNSDetails)
1344 g_log<<Logger::Error<<"Received an answer (non-query) packet from "<<p.getRemoteString()<<", dropping"<<endl;
1345 S.inc("corrupt-packets");
1346 S.ringAccount("remotes-corrupt", p.getInnerRemote());
1347 return nullptr;
1348 }
1349
1350 if(p.d.tc) { // truncated query. MOADNSParser would silently parse this packet in an incomplete way.
1351 if(d_logDNSDetails)
1352 g_log<<Logger::Error<<"Received truncated query packet from "<<p.getRemoteString()<<", dropping"<<endl;
1353 S.inc("corrupt-packets");
1354 S.ringAccount("remotes-corrupt", p.getInnerRemote());
1355 return nullptr;
1356 }
1357
1358 if (p.hasEDNS()) {
1359 if(p.getEDNSVersion() > 0) {
1360 r = p.replyPacket();
1361
1362 // PacketWriter::addOpt will take care of setting this correctly in the packet
1363 r->setEDNSRcode(ERCode::BADVERS);
1364 return r;
1365 }
1366 if (p.hasEDNSCookie()) {
1367 if (!p.hasWellFormedEDNSCookie()) {
1368 r = p.replyPacket();
1369 r->setRcode(RCode::FormErr);
1370 return r;
1371 }
1372 if (!p.hasValidEDNSCookie() && !p.d_tcp) {
1373 r = p.replyPacket();
1374 r->setEDNSRcode(ERCode::BADCOOKIE);
1375 return r;
1376 }
1377 }
1378 }
1379
1380 if(p.d_havetsig) {
1381 DNSName keyname;
1382 string secret;
1383 TSIGRecordContent trc;
1384 if(!p.checkForCorrectTSIG(&B, &keyname, &secret, &trc)) {
1385 r=p.replyPacket(); // generate an empty reply packet
1386 if(d_logDNSDetails)
1387 g_log<<Logger::Error<<"Received a TSIG signed message with a non-validating key"<<endl;
1388 // RFC3007 describes that a non-secure message should be sending Refused for DNS Updates
1389 if (p.d.opcode == Opcode::Update)
1390 r->setRcode(RCode::Refused);
1391 else
1392 r->setRcode(RCode::NotAuth);
1393 return r;
1394 } else {
1395 getTSIGHashEnum(trc.d_algoName, p.d_tsig_algo);
1396 #ifdef ENABLE_GSS_TSIG
1397 if (g_doGssTSIG && p.d_tsig_algo == TSIG_GSS) {
1398 GssContext gssctx(keyname);
1399 if (!gssctx.getPeerPrincipal(p.d_peer_principal)) {
1400 g_log<<Logger::Warning<<"Failed to extract peer principal from GSS context with keyname '"<<keyname<<"'"<<endl;
1401 }
1402 }
1403 #endif
1404 }
1405 p.setTSIGDetails(trc, keyname, secret, trc.d_mac); // this will get copied by replyPacket()
1406 noCache=true;
1407 }
1408
1409 r=p.replyPacket(); // generate an empty reply packet, possibly with TSIG details inside
1410
1411 if (p.qtype == QType::TKEY) {
1412 this->tkeyHandler(p, r);
1413 return r;
1414 }
1415
1416 try {
1417
1418 // XXX FIXME do this in DNSPacket::parse ?
1419
1420 if(!validDNSName(p.qdomain)) {
1421 if(d_logDNSDetails)
1422 g_log<<Logger::Error<<"Received a malformed qdomain from "<<p.getRemoteString()<<", '"<<p.qdomain<<"': sending servfail"<<endl;
1423 S.inc("corrupt-packets");
1424 S.ringAccount("remotes-corrupt", p.getInnerRemote());
1425 S.inc("servfail-packets");
1426 r->setRcode(RCode::ServFail);
1427 return r;
1428 }
1429 if(p.d.opcode) { // non-zero opcode (again thanks RA!)
1430 if(p.d.opcode==Opcode::Update) {
1431 S.inc("dnsupdate-queries");
1432 int res=processUpdate(p);
1433 if (res == RCode::Refused)
1434 S.inc("dnsupdate-refused");
1435 else if (res != RCode::ServFail)
1436 S.inc("dnsupdate-answers");
1437 r->setRcode(res);
1438 r->setOpcode(Opcode::Update);
1439 return r;
1440 }
1441 else if(p.d.opcode==Opcode::Notify) {
1442 S.inc("incoming-notifications");
1443 int res=processNotify(p);
1444 if(res>=0) {
1445 r->setRcode(res);
1446 r->setOpcode(Opcode::Notify);
1447 return r;
1448 }
1449 return nullptr;
1450 }
1451
1452 g_log<<Logger::Error<<"Received an unknown opcode "<<p.d.opcode<<" from "<<p.getRemoteString()<<" for "<<p.qdomain<<endl;
1453
1454 r->setRcode(RCode::NotImp);
1455 return r;
1456 }
1457
1458 // g_log<<Logger::Warning<<"Query for '"<<p.qdomain<<"' "<<p.qtype.toString()<<" from "<<p.getRemoteString()<< " (tcp="<<p.d_tcp<<")"<<endl;
1459
1460 if(p.qtype.getCode()==QType::IXFR) {
1461 r->setRcode(RCode::Refused);
1462 return r;
1463 }
1464
1465 DNSName target=p.qdomain;
1466
1467 // catch chaos qclass requests
1468 if(p.qclass == QClass::CHAOS) {
1469 if (doChaosRequest(p,r,target))
1470 goto sendit;
1471 else
1472 return r;
1473 }
1474
1475 // we only know about qclass IN (and ANY), send Refused for everything else.
1476 if(p.qclass != QClass::IN && p.qclass!=QClass::ANY) {
1477 r->setRcode(RCode::Refused);
1478 return r;
1479 }
1480
1481 // send TC for udp ANY query if any-to-tcp is enabled.
1482 if(p.qtype.getCode() == QType::ANY && !p.d_tcp && g_anyToTcp) {
1483 r->d.tc = 1;
1484 r->commitD();
1485 return r;
1486 }
1487
1488 // for qclass ANY the response should never be authoritative unless the response covers all classes.
1489 if(p.qclass==QClass::ANY)
1490 r->setA(false);
1491
1492
1493 retargeted:;
1494 if(retargetcount > 10) { // XXX FIXME, retargetcount++?
1495 g_log<<Logger::Warning<<"Abort CNAME chain resolution after "<<--retargetcount<<" redirects, sending out servfail. Initial query: '"<<p.qdomain<<"'"<<endl;
1496 r=p.replyPacket();
1497 r->setRcode(RCode::ServFail);
1498 return r;
1499 }
1500
1501 if(!B.getAuth(target, p.qtype, &d_sd)) {
1502 DLOG(g_log<<Logger::Error<<"We have no authority over zone '"<<target<<"'"<<endl);
1503 if(!retargetcount) {
1504 r->setA(false); // drop AA if we never had a SOA in the first place
1505 r->setRcode(RCode::Refused); // send REFUSED - but only on empty 'no idea'
1506 }
1507 goto sendit;
1508 }
1509 DLOG(g_log<<Logger::Error<<"We have authority, zone='"<<d_sd.qname<<"', id="<<d_sd.domain_id<<endl);
1510
1511 authSet.insert(d_sd.qname);
1512 d_dnssec=(p.d_dnssecOk && d_dk.isSecuredZone(d_sd.qname));
1513 doSigs |= d_dnssec;
1514
1515 if(!retargetcount) r->qdomainzone=d_sd.qname;
1516
1517 if(d_sd.qname==p.qdomain) {
1518 if(!d_dk.isPresigned(d_sd.qname)) {
1519 if(p.qtype.getCode() == QType::DNSKEY)
1520 {
1521 if(addDNSKEY(p, r))
1522 goto sendit;
1523 }
1524 else if(p.qtype.getCode() == QType::CDNSKEY)
1525 {
1526 if(addCDNSKEY(p,r))
1527 goto sendit;
1528 }
1529 else if(p.qtype.getCode() == QType::CDS)
1530 {
1531 if(addCDS(p,r))
1532 goto sendit;
1533 }
1534 }
1535 if(p.qtype.getCode() == QType::NSEC3PARAM)
1536 {
1537 if(addNSEC3PARAM(p,r))
1538 goto sendit;
1539 }
1540 }
1541
1542 if(p.qtype.getCode() == QType::SOA && d_sd.qname==p.qdomain) {
1543 rr=makeEditedDNSZRFromSOAData(d_dk, d_sd);
1544 r->addRecord(std::move(rr));
1545 goto sendit;
1546 }
1547
1548 // this TRUMPS a cname!
1549 if(d_dnssec && p.qtype.getCode() == QType::NSEC && !d_dk.getNSEC3PARAM(d_sd.qname, nullptr)) {
1550 addNSEC(p, r, target, DNSName(), 5);
1551 if (!r->isEmpty())
1552 goto sendit;
1553 }
1554
1555 // this TRUMPS a cname!
1556 if(p.qtype.getCode() == QType::RRSIG) {
1557 g_log<<Logger::Info<<"Direct RRSIG query for "<<target<<" from "<<p.getRemoteString()<<endl;
1558 r->setRcode(RCode::Refused);
1559 goto sendit;
1560 }
1561
1562 DLOG(g_log<<"Checking for referrals first, unless this is a DS query"<<endl);
1563 if(p.qtype.getCode() != QType::DS && tryReferral(p, r, target, retargetcount))
1564 goto sendit;
1565
1566 DLOG(g_log<<"Got no referrals, trying ANY"<<endl);
1567
1568 #ifdef HAVE_LUA_RECORDS
1569 if(!doLua) {
1570 string val;
1571 d_dk.getFromMeta(d_sd.qname, "ENABLE-LUA-RECORDS", val);
1572 doLua = (val=="1");
1573 }
1574 #endif
1575
1576 // see what we get..
1577 B.lookup(QType(QType::ANY), target, d_sd.domain_id, &p);
1578 rrset.clear();
1579 haveAlias.clear();
1580 aliasScopeMask = 0;
1581 weDone = weRedirected = weHaveUnauth = false;
1582
1583 while(B.get(rr)) {
1584 #ifdef HAVE_LUA_RECORDS
1585 if (rr.dr.d_type == QType::LUA && !d_dk.isPresigned(d_sd.qname)) {
1586 if(!doLua)
1587 continue;
1588 auto rec=getRR<LUARecordContent>(rr.dr);
1589 if (!rec) {
1590 continue;
1591 }
1592 if(rec->d_type == QType::CNAME || rec->d_type == p.qtype.getCode() || (p.qtype.getCode() == QType::ANY && rec->d_type != QType::RRSIG)) {
1593 noCache=true;
1594 try {
1595 auto recvec=luaSynth(rec->getCode(), target, d_sd.qname, d_sd.domain_id, p, rec->d_type, s_LUA);
1596 if(!recvec.empty()) {
1597 for (const auto& r_it : recvec) {
1598 rr.dr.d_type = rec->d_type; // might be CNAME
1599 rr.dr.setContent(r_it);
1600 rr.scopeMask = p.getRealRemote().getBits(); // this makes sure answer is a specific as your question
1601 rrset.push_back(rr);
1602 }
1603 if(rec->d_type == QType::CNAME && p.qtype.getCode() != QType::CNAME)
1604 weRedirected = true;
1605 else
1606 weDone = true;
1607 }
1608 }
1609 catch(std::exception &e) {
1610 while (B.get(rr)) ; // don't leave DB handle in bad state
1611
1612 r=p.replyPacket();
1613 r->setRcode(RCode::ServFail);
1614
1615 return r;
1616 }
1617 }
1618 }
1619 #endif
1620 //cerr<<"got content: ["<<rr.content<<"]"<<endl;
1621 if (!d_dnssec && p.qtype.getCode() == QType::ANY && (rr.dr.d_type == QType:: DNSKEY || rr.dr.d_type == QType::NSEC3PARAM))
1622 continue; // Don't send dnssec info.
1623 if (rr.dr.d_type == QType::RRSIG) // RRSIGS are added later any way.
1624 continue; // TODO: this actually means addRRSig should check if the RRSig is already there
1625
1626 // cerr<<"Auth: "<<rr.auth<<", "<<(rr.dr.d_type == p.qtype)<<", "<<rr.dr.d_type.toString()<<endl;
1627 if((p.qtype.getCode() == QType::ANY || rr.dr.d_type == p.qtype.getCode()) && rr.auth)
1628 weDone=true;
1629 // the line below fakes 'unauth NS' for delegations for non-DNSSEC backends.
1630 if((rr.dr.d_type == p.qtype.getCode() && !rr.auth) || (rr.dr.d_type == QType::NS && (!rr.auth || !(d_sd.qname==rr.dr.d_name))))
1631 weHaveUnauth=true;
1632
1633 if(rr.dr.d_type == QType::CNAME && p.qtype.getCode() != QType::CNAME)
1634 weRedirected=true;
1635
1636 if (DP && rr.dr.d_type == QType::ALIAS && (p.qtype.getCode() == QType::A || p.qtype.getCode() == QType::AAAA || p.qtype.getCode() == QType::ANY) && !d_dk.isPresigned(d_sd.qname)) {
1637 if (!d_doExpandALIAS) {
1638 g_log<<Logger::Info<<"ALIAS record found for "<<target<<", but ALIAS expansion is disabled."<<endl;
1639 continue;
1640 }
1641 haveAlias=getRR<ALIASRecordContent>(rr.dr)->getContent();
1642 aliasScopeMask=rr.scopeMask;
1643 }
1644
1645 // Filter out all SOA's and add them in later
1646 if(rr.dr.d_type == QType::SOA)
1647 continue;
1648
1649 rrset.push_back(rr);
1650 }
1651
1652 /* Add in SOA if required */
1653 if(target==d_sd.qname) {
1654 rr=makeEditedDNSZRFromSOAData(d_dk, d_sd);
1655 rrset.push_back(rr);
1656 }
1657
1658
1659 DLOG(g_log<<"After first ANY query for '"<<target<<"', id="<<d_sd.domain_id<<": weDone="<<weDone<<", weHaveUnauth="<<weHaveUnauth<<", weRedirected="<<weRedirected<<", haveAlias='"<<haveAlias<<"'"<<endl);
1660 if(p.qtype.getCode() == QType::DS && weHaveUnauth && !weDone && !weRedirected) {
1661 DLOG(g_log<<"Q for DS of a name for which we do have NS, but for which we don't have DS; need to provide an AUTH answer that shows we don't"<<endl);
1662 makeNOError(p, r, target, DNSName(), 1);
1663 goto sendit;
1664 }
1665
1666 if(!haveAlias.empty() && (!weDone || p.qtype.getCode() == QType::ANY)) {
1667 DLOG(g_log<<Logger::Warning<<"Found nothing that matched for '"<<target<<"', but did get alias to '"<<haveAlias<<"', referring"<<endl);
1668 DP->completePacket(r, haveAlias, target, aliasScopeMask);
1669 return nullptr;
1670 }
1671
1672
1673 // referral for DS query
1674 if(p.qtype.getCode() == QType::DS) {
1675 DLOG(g_log<<"Qtype is DS"<<endl);
1676 bool doReferral = true;
1677 if(d_dk.doesDNSSEC()) {
1678 for(auto& loopRR: rrset) {
1679 // In a dnssec capable backend auth=true means, there is no delegation at
1680 // or above this qname in this zone (for DS queries). Without a delegation,
1681 // at or above this level, it is pointless to search for referrals.
1682 if(loopRR.auth) {
1683 doReferral = false;
1684 break;
1685 }
1686 }
1687 } else {
1688 for(auto& loopRR: rrset) {
1689 // In a non dnssec capable backend auth is always true, so our only option
1690 // is, always look for referrals. Unless there is a direct match for DS.
1691 if(loopRR.dr.d_type == QType::DS) {
1692 doReferral = false;
1693 break;
1694 }
1695 }
1696 }
1697 if(doReferral) {
1698 DLOG(g_log<<"DS query found no direct result, trying referral now"<<endl);
1699 if(tryReferral(p, r, target, retargetcount))
1700 {
1701 DLOG(g_log<<"Got referral for DS query"<<endl);
1702 goto sendit;
1703 }
1704 }
1705 }
1706
1707
1708 if(rrset.empty()) {
1709 DLOG(g_log<<Logger::Warning<<"Found nothing in the by-name ANY, but let's try wildcards.."<<endl);
1710 bool wereRetargeted(false), nodata(false);
1711 DNSName wildcard;
1712 if(tryWildcard(p, r, target, wildcard, wereRetargeted, nodata)) {
1713 if(wereRetargeted) {
1714 if(!retargetcount) r->qdomainwild=wildcard;
1715 retargetcount++;
1716 goto retargeted;
1717 }
1718 if(nodata)
1719 makeNOError(p, r, target, wildcard, 2);
1720
1721 goto sendit;
1722 }
1723 try {
1724 if (tryDNAME(p, r, target)) {
1725 retargetcount++;
1726 goto retargeted;
1727 }
1728 } catch (const std::range_error &e) {
1729 // We couldn't make a CNAME.....
1730 r->setRcode(RCode::YXDomain);
1731 goto sendit;
1732 }
1733
1734 if (!(((p.qtype.getCode() == QType::CNAME) || (p.qtype.getCode() == QType::ANY)) && retargetcount > 0))
1735 makeNXDomain(p, r, target, wildcard);
1736
1737 goto sendit;
1738 }
1739
1740 if(weRedirected) {
1741 for(auto& loopRR: rrset) {
1742 if(loopRR.dr.d_type == QType::CNAME) {
1743 r->addRecord(DNSZoneRecord(loopRR));
1744 target = getRR<CNAMERecordContent>(loopRR.dr)->getTarget();
1745 retargetcount++;
1746 goto retargeted;
1747 }
1748 }
1749 }
1750 else if(weDone) {
1751 bool haveRecords = false;
1752 bool presigned = d_dk.isPresigned(d_sd.qname);
1753 for(const auto& loopRR: rrset) {
1754 if (loopRR.dr.d_type == QType::ENT) {
1755 continue;
1756 }
1757 if (loopRR.dr.d_type == QType::ALIAS && d_doExpandALIAS && !presigned) {
1758 continue;
1759 }
1760 #ifdef HAVE_LUA_RECORDS
1761 if (loopRR.dr.d_type == QType::LUA && !presigned) {
1762 continue;
1763 }
1764 #endif
1765 if ((p.qtype.getCode() == QType::ANY || loopRR.dr.d_type == p.qtype.getCode()) && loopRR.auth) {
1766 r->addRecord(DNSZoneRecord(loopRR));
1767 haveRecords = true;
1768 }
1769 }
1770
1771 if (haveRecords) {
1772 if(d_dnssec && p.qtype.getCode() == QType::ANY)
1773 completeANYRecords(p, r, target);
1774 }
1775 else
1776 makeNOError(p, r, target, DNSName(), 0);
1777
1778 goto sendit;
1779 }
1780 else if(weHaveUnauth) {
1781 DLOG(g_log<<"Have unauth data, so need to hunt for best NS records"<<endl);
1782 if(tryReferral(p, r, target, retargetcount))
1783 goto sendit;
1784 // check whether this could be fixed easily
1785 // if (*(rr.dr.d_name.rbegin()) == '.') {
1786 // g_log<<Logger::Error<<"Should not get here ("<<p.qdomain<<"|"<<p.qtype.toString()<<"): you have a trailing dot, this could be the problem (or run pdnsutil rectify-zone " <<d_sd.qname<<")"<<endl;
1787 // } else {
1788 g_log<<Logger::Error<<"Should not get here ("<<p.qdomain<<"|"<<p.qtype.toString()<<"): please run pdnsutil rectify-zone "<<d_sd.qname<<endl;
1789 // }
1790 }
1791 else {
1792 DLOG(g_log<<"Have some data, but not the right data"<<endl);
1793 makeNOError(p, r, target, DNSName(), 0);
1794 }
1795
1796 sendit:;
1797 doAdditionalProcessing(p, r);
1798
1799 for(const auto& loopRR: r->getRRS()) {
1800 if(loopRR.scopeMask) {
1801 noCache=true;
1802 break;
1803 }
1804 }
1805 if(doSigs)
1806 addRRSigs(d_dk, B, authSet, r->getRRS());
1807
1808 if(PC.enabled() && !noCache && p.couldBeCached())
1809 PC.insert(p, *r, r->getMinTTL()); // in the packet cache
1810 }
1811 catch(const DBException &e) {
1812 g_log<<Logger::Error<<"Backend reported condition which prevented lookup ("+e.reason+") sending out servfail"<<endl;
1813 r=p.replyPacket(); // generate an empty reply packet
1814 r->setRcode(RCode::ServFail);
1815 S.inc("servfail-packets");
1816 S.ringAccount("servfail-queries", p.qdomain, p.qtype);
1817 }
1818 catch(const PDNSException &e) {
1819 g_log<<Logger::Error<<"Backend reported permanent error which prevented lookup ("+e.reason+"), aborting"<<endl;
1820 throw; // we WANT to die at this point
1821 }
1822 catch(const std::exception &e) {
1823 g_log<<Logger::Error<<"Exception building answer packet for "<<p.qdomain<<"/"<<p.qtype.toString()<<" ("<<e.what()<<") sending out servfail"<<endl;
1824 r=p.replyPacket(); // generate an empty reply packet
1825 r->setRcode(RCode::ServFail);
1826 S.inc("servfail-packets");
1827 S.ringAccount("servfail-queries", p.qdomain, p.qtype);
1828 }
1829 return r;
1830
1831 }