5 #include "rec_channel.hh"
6 #include <boost/bind.hpp>
9 #include "malloctrace.hh"
12 #include "recursor_cache.hh"
14 #include "negcache.hh"
15 #include <boost/function.hpp>
16 #include <boost/optional.hpp>
17 #include <boost/tuple/tuple.hpp>
18 #include <boost/format.hpp>
19 #include <boost/algorithm/string.hpp>
22 #include <sys/types.h>
26 #include "dnsparser.hh"
27 #include "arguments.hh"
28 #include <sys/resource.h>
31 #include "responsestats.hh"
32 #include "rec-lua-conf.hh"
34 #include "validate-recursor.hh"
35 #include "filterpo.hh"
37 #include "secpoll-recursor.hh"
38 #include "pubsuffix.hh"
39 #include "namespaces.hh"
40 pthread_mutex_t g_carbon_config_lock
=PTHREAD_MUTEX_INITIALIZER
;
42 static map
<string
, const uint32_t*> d_get32bitpointers
;
43 static map
<string
, const uint64_t*> d_get64bitpointers
;
44 static map
<string
, const std::atomic
<uint64_t>*> d_getatomics
;
45 static map
<string
, function
< uint64_t() > > d_get64bitmembers
;
46 static pthread_mutex_t d_dynmetricslock
= PTHREAD_MUTEX_INITIALIZER
;
47 static map
<string
, std::atomic
<unsigned long>* > d_dynmetrics
;
49 static void addGetStat(const string
& name
, const uint32_t* place
)
51 d_get32bitpointers
[name
]=place
;
54 static void addGetStat(const string
& name
, const std::atomic
<uint64_t>* place
)
56 d_getatomics
[name
]=place
;
59 static void addGetStat(const string
& name
, function
<uint64_t ()> f
)
61 d_get64bitmembers
[name
]=f
;
64 std::atomic
<unsigned long>* getDynMetric(const std::string
& str
)
66 Lock
l(&d_dynmetricslock
);
67 auto f
= d_dynmetrics
.find(str
);
68 if(f
!= d_dynmetrics
.end())
71 auto ret
= new std::atomic
<unsigned long>();
72 d_dynmetrics
[str
]= ret
;
76 static optional
<uint64_t> get(const string
& name
)
78 optional
<uint64_t> ret
;
80 if(d_get32bitpointers
.count(name
))
81 return *d_get32bitpointers
.find(name
)->second
;
82 if(d_get64bitpointers
.count(name
))
83 return *d_get64bitpointers
.find(name
)->second
;
84 if(d_getatomics
.count(name
))
85 return d_getatomics
.find(name
)->second
->load();
86 if(d_get64bitmembers
.count(name
))
87 return d_get64bitmembers
.find(name
)->second();
89 Lock
l(&d_dynmetricslock
);
90 auto f
=rplookup(d_dynmetrics
, name
);
97 optional
<uint64_t> getStatByName(const std::string
& name
)
102 map
<string
,string
> getAllStatsMap()
104 map
<string
,string
> ret
;
106 for(const auto& the32bits
: d_get32bitpointers
) {
107 ret
.insert(make_pair(the32bits
.first
, std::to_string(*the32bits
.second
)));
109 for(const auto& the64bits
: d_get64bitpointers
) {
110 ret
.insert(make_pair(the64bits
.first
, std::to_string(*the64bits
.second
)));
112 for(const auto& atomic
: d_getatomics
) {
113 ret
.insert(make_pair(atomic
.first
, std::to_string(atomic
.second
->load())));
116 for(const auto& the64bitmembers
: d_get64bitmembers
) {
117 if(the64bitmembers
.first
== "cache-bytes" || the64bitmembers
.first
=="packetcache-bytes")
118 continue; // too slow for 'get-all'
119 ret
.insert(make_pair(the64bitmembers
.first
, std::to_string(the64bitmembers
.second())));
121 Lock
l(&d_dynmetricslock
);
122 for(const auto& a
: d_dynmetrics
)
123 ret
.insert({a
.first
, std::to_string(*a
.second
)});
129 typedef map
<string
, string
> varmap_t
;
130 varmap_t varmap
= getAllStatsMap();
132 for(varmap_t::value_type
& tup
: varmap
) {
133 ret
+= tup
.first
+ "\t" + tup
.second
+"\n";
139 string
doGet(T begin
, T end
)
143 for(T i
=begin
; i
!= end
; ++i
) {
144 optional
<uint64_t> num
=get(*i
);
146 ret
+=std::to_string(*num
)+"\n";
154 string
doGetParameter(T begin
, T end
)
158 using boost::replace_all
;
159 for(T i
=begin
; i
!= end
; ++i
) {
160 if(::arg().parmIsset(*i
)) {
162 replace_all(parm
, "\\", "\\\\");
163 replace_all(parm
, "\"", "\\\"");
164 replace_all(parm
, "\n", "\\n");
165 ret
+= *i
+"=\""+ parm
+"\"\n";
168 ret
+= *i
+" not known\n";
174 static uint64_t dumpNegCache(NegCache
& negcache
, int fd
)
176 FILE* fp
=fdopen(dup(fd
), "w");
177 if(!fp
) { // dup probably failed
181 fprintf(fp
, "; negcache dump from thread follows\n;\n");
182 ret
= negcache
.dumpToFile(fp
);
187 static uint64_t* pleaseDump(int fd
)
189 return new uint64_t(t_RC
->doDump(fd
) + dumpNegCache(SyncRes::t_sstorage
.negcache
, fd
) + t_packetCache
->doDump(fd
));
192 static uint64_t* pleaseDumpNSSpeeds(int fd
)
194 return new uint64_t(SyncRes::doDumpNSSpeeds(fd
));
198 string
doDumpNSSpeeds(T begin
, T end
)
206 int fd
=open(fname
.c_str(), O_CREAT
| O_EXCL
| O_WRONLY
, 0660);
208 return "Error opening dump file for writing: "+string(strerror(errno
))+"\n";
211 total
= broadcastAccFunction
<uint64_t>(boost::bind(pleaseDumpNSSpeeds
, fd
));
213 catch(std::exception
& e
)
216 return "error dumping NS speeds: "+string(e
.what())+"\n";
218 catch(PDNSException
& e
)
221 return "error dumping NS speeds: "+e
.reason
+"\n";
225 return "dumped "+std::to_string(total
)+" records\n";
229 string
doDumpCache(T begin
, T end
)
237 int fd
=open(fname
.c_str(), O_CREAT
| O_EXCL
| O_WRONLY
, 0660);
239 return "Error opening dump file for writing: "+string(strerror(errno
))+"\n";
242 total
= broadcastAccFunction
<uint64_t>(boost::bind(pleaseDump
, fd
));
247 return "dumped "+std::to_string(total
)+" records\n";
251 string
doDumpEDNSStatus(T begin
, T end
)
259 int fd
=open(fname
.c_str(), O_CREAT
| O_EXCL
| O_WRONLY
, 0660);
261 return "Error opening dump file for writing: "+string(strerror(errno
))+"\n";
263 SyncRes::doEDNSDumpAndClose(fd
);
269 string
doDumpRPZ(T begin
, T end
)
274 return "No zone name specified\n";
276 string zoneName
= *i
;
280 return "No file name specified\n";
284 auto luaconf
= g_luaconfs
.getLocal();
285 const auto zone
= luaconf
->dfe
.getZone(zoneName
);
287 return "No RPZ zone named "+zoneName
+"\n";
290 int fd
= open(fname
.c_str(), O_CREAT
| O_EXCL
| O_WRONLY
, 0660);
293 return "Error opening dump file for writing: "+string(strerror(errno
))+"\n";
296 FILE* fp
= fdopen(fd
, "w");
299 return "Error converting file descriptor: "+string(strerror(errno
))+"\n";
308 uint64_t* pleaseWipeCache(const DNSName
& canon
, bool subtree
)
310 return new uint64_t(t_RC
->doWipeCache(canon
, subtree
));
313 uint64_t* pleaseWipePacketCache(const DNSName
& canon
, bool subtree
)
315 return new uint64_t(t_packetCache
->doWipePacketCache(canon
,0xffff, subtree
));
319 uint64_t* pleaseWipeAndCountNegCache(const DNSName
& canon
, bool subtree
)
321 uint64_t ret
= SyncRes::wipeNegCache(canon
, subtree
);
322 return new uint64_t(ret
);
327 string
doWipeCache(T begin
, T end
)
329 vector
<pair
<DNSName
, bool> > toWipe
;
330 for(T i
=begin
; i
!= end
; ++i
) {
335 if(boost::ends_with(*i
, "$")) {
336 canon
=DNSName(i
->substr(0, i
->size()-1));
341 } catch (std::exception
&e
) {
342 return "Error: " + std::string(e
.what()) + ", nothing wiped\n";
344 toWipe
.push_back({canon
, subtree
});
347 int count
=0, pcount
=0, countNeg
=0;
348 for (auto wipe
: toWipe
) {
349 count
+= broadcastAccFunction
<uint64_t>(boost::bind(pleaseWipeCache
, wipe
.first
, wipe
.second
));
350 pcount
+= broadcastAccFunction
<uint64_t>(boost::bind(pleaseWipePacketCache
, wipe
.first
, wipe
.second
));
351 countNeg
+=broadcastAccFunction
<uint64_t>(boost::bind(pleaseWipeAndCountNegCache
, wipe
.first
, wipe
.second
));
354 return "wiped "+std::to_string(count
)+" records, "+std::to_string(countNeg
)+" negative records, "+std::to_string(pcount
)+" packets\n";
358 string
doSetCarbonServer(T begin
, T end
)
360 Lock
l(&g_carbon_config_lock
);
362 ::arg().set("carbon-server").clear();
363 return "cleared carbon-server setting\n";
366 ::arg().set("carbon-server")=*begin
;
367 ret
="set carbon-server to '"+::arg()["carbon-server"]+"'\n";
370 ::arg().set("carbon-ourname")=*begin
;
371 ret
+="set carbon-ourname to '"+*begin
+"'\n";
377 string
doSetDnssecLogBogus(T begin
, T end
)
379 if(checkDNSSECDisabled())
380 return "DNSSEC is disabled in the configuration, not changing the Bogus logging setting\n";
383 return "No DNSSEC Bogus logging setting specified\n";
385 if (pdns_iequals(*begin
, "on") || pdns_iequals(*begin
, "yes")) {
386 if (!g_dnssecLogBogus
) {
387 L
<<Logger::Warning
<<"Enabling DNSSEC Bogus logging, requested via control channel"<<endl
;
388 g_dnssecLogBogus
= true;
389 return "DNSSEC Bogus logging enabled\n";
391 return "DNSSEC Bogus logging was already enabled\n";
394 if (pdns_iequals(*begin
, "off") || pdns_iequals(*begin
, "no")) {
395 if (g_dnssecLogBogus
) {
396 L
<<Logger::Warning
<<"Disabling DNSSEC Bogus logging, requested via control channel"<<endl
;
397 g_dnssecLogBogus
= false;
398 return "DNSSEC Bogus logging disabled\n";
400 return "DNSSEC Bogus logging was already disabled\n";
403 return "Unknown DNSSEC Bogus setting: '" + *begin
+"'\n";
407 string
doAddNTA(T begin
, T end
)
409 if(checkDNSSECDisabled())
410 return "DNSSEC is disabled in the configuration, not adding a Negative Trust Anchor\n";
413 return "No NTA specified, doing nothing\n";
417 who
= DNSName(*begin
);
419 catch(std::exception
&e
) {
420 string
ret("Can't add Negative Trust Anchor: ");
428 while (begin
!= end
) {
434 L
<<Logger::Warning
<<"Adding Negative Trust Anchor for "<<who
<<" with reason '"<<why
<<"', requested via control channel"<<endl
;
435 g_luaconfs
.modify([who
, why
](LuaConfigItems
& lci
) {
436 lci
.negAnchors
[who
] = why
;
438 broadcastAccFunction
<uint64_t>(boost::bind(pleaseWipePacketCache
, who
, true));
439 return "Added Negative Trust Anchor for " + who
.toLogString() + " with reason '" + why
+ "'\n";
443 string
doClearNTA(T begin
, T end
)
445 if(checkDNSSECDisabled())
446 return "DNSSEC is disabled in the configuration, not removing a Negative Trust Anchor\n";
449 return "No Negative Trust Anchor specified, doing nothing.\n";
451 if (begin
+ 1 == end
&& *begin
== "*"){
452 L
<<Logger::Warning
<<"Clearing all Negative Trust Anchors, requested via control channel"<<endl
;
453 g_luaconfs
.modify([](LuaConfigItems
& lci
) {
454 lci
.negAnchors
.clear();
456 return "Cleared all Negative Trust Anchors.\n";
459 vector
<DNSName
> toRemove
;
461 while (begin
!= end
) {
463 return "Don't mix all Negative Trust Anchor removal with multiple Negative Trust Anchor removal. Nothing removed\n";
465 who
= DNSName(*begin
);
467 catch(std::exception
&e
) {
468 string
ret("Error: ");
470 ret
+= ". No Negative Anchors removed\n";
473 toRemove
.push_back(who
);
479 for (auto const &entry
: toRemove
) {
480 L
<<Logger::Warning
<<"Clearing Negative Trust Anchor for "<<entry
<<", requested via control channel"<<endl
;
481 g_luaconfs
.modify([entry
](LuaConfigItems
& lci
) {
482 lci
.negAnchors
.erase(entry
);
484 broadcastAccFunction
<uint64_t>(boost::bind(pleaseWipePacketCache
, entry
, true));
489 removed
+= " " + entry
.toStringRootDot();
491 return "Removed Negative Trust Anchors for " + removed
+ "\n";
494 static string
getNTAs()
496 if(checkDNSSECDisabled())
497 return "DNSSEC is disabled in the configuration\n";
499 string
ret("Configured Negative Trust Anchors:\n");
500 auto luaconf
= g_luaconfs
.getLocal();
501 for (auto negAnchor
: luaconf
->negAnchors
)
502 ret
+= negAnchor
.first
.toLogString() + "\t" + negAnchor
.second
+ "\n";
507 string
doAddTA(T begin
, T end
)
509 if(checkDNSSECDisabled())
510 return "DNSSEC is disabled in the configuration, not adding a Trust Anchor\n";
513 return "No TA specified, doing nothing\n";
517 who
= DNSName(*begin
);
519 catch(std::exception
&e
) {
520 string
ret("Can't add Trust Anchor: ");
528 while (begin
!= end
) {
529 what
+= *begin
+ " ";
534 L
<<Logger::Warning
<<"Adding Trust Anchor for "<<who
<<" with data '"<<what
<<"', requested via control channel";
535 g_luaconfs
.modify([who
, what
](LuaConfigItems
& lci
) {
536 auto ds
= unique_ptr
<DSRecordContent
>(dynamic_cast<DSRecordContent
*>(DSRecordContent::make(what
)));
537 lci
.dsAnchors
[who
].insert(*ds
);
539 broadcastAccFunction
<uint64_t>(boost::bind(pleaseWipePacketCache
, who
, true));
540 L
<<Logger::Warning
<<endl
;
541 return "Added Trust Anchor for " + who
.toStringRootDot() + " with data " + what
+ "\n";
543 catch(std::exception
&e
) {
544 L
<<Logger::Warning
<<", failed: "<<e
.what()<<endl
;
545 return "Unable to add Trust Anchor for " + who
.toStringRootDot() + ": " + e
.what() + "\n";
550 string
doClearTA(T begin
, T end
)
552 if(checkDNSSECDisabled())
553 return "DNSSEC is disabled in the configuration, not removing a Trust Anchor\n";
556 return "No Trust Anchor to clear\n";
558 vector
<DNSName
> toRemove
;
560 while (begin
!= end
) {
562 who
= DNSName(*begin
);
564 catch(std::exception
&e
) {
565 string
ret("Error: ");
567 ret
+= ". No Anchors removed\n";
571 return "Refusing to remove root Trust Anchor, no Anchors removed\n";
572 toRemove
.push_back(who
);
578 for (auto const &entry
: toRemove
) {
579 L
<<Logger::Warning
<<"Removing Trust Anchor for "<<entry
<<", requested via control channel"<<endl
;
580 g_luaconfs
.modify([entry
](LuaConfigItems
& lci
) {
581 lci
.dsAnchors
.erase(entry
);
583 broadcastAccFunction
<uint64_t>(boost::bind(pleaseWipePacketCache
, entry
, true));
588 removed
+= " " + entry
.toStringRootDot();
590 return "Removed Trust Anchor(s) for" + removed
+ "\n";
593 static string
getTAs()
595 if(checkDNSSECDisabled())
596 return "DNSSEC is disabled in the configuration\n";
598 string
ret("Configured Trust Anchors:\n");
599 auto luaconf
= g_luaconfs
.getLocal();
600 for (auto anchor
: luaconf
->dsAnchors
) {
601 ret
+= anchor
.first
.toLogString() + "\n";
602 for (auto e
: anchor
.second
) {
603 ret
+="\t\t"+e
.getZoneRepresentation() + "\n";
611 string
setMinimumTTL(T begin
, T end
)
614 return "Need to supply new minimum TTL number\n";
615 SyncRes::s_minimumTTL
= pdns_stou(*begin
);
616 return "New minimum TTL: " + std::to_string(SyncRes::s_minimumTTL
) + "\n";
620 string
setMaxCacheEntries(T begin
, T end
)
623 return "Need to supply new cache size\n";
624 g_maxCacheEntries
= pdns_stou(*begin
);
625 return "New max cache entries: " + std::to_string(g_maxCacheEntries
) + "\n";
629 string
setMaxPacketCacheEntries(T begin
, T end
)
632 return "Need to supply new packet cache size\n";
633 g_maxPacketCacheEntries
= pdns_stou(*begin
);
634 return "New max packetcache entries: " + std::to_string(g_maxPacketCacheEntries
) + "\n";
638 static uint64_t getSysTimeMsec()
641 getrusage(RUSAGE_SELF
, &ru
);
642 return (ru
.ru_stime
.tv_sec
*1000ULL + ru
.ru_stime
.tv_usec
/1000);
645 static uint64_t getUserTimeMsec()
648 getrusage(RUSAGE_SELF
, &ru
);
649 return (ru
.ru_utime
.tv_sec
*1000ULL + ru
.ru_utime
.tv_usec
/1000);
652 static uint64_t calculateUptime()
654 return time(0) - g_stats
.startupTime
;
657 static string
* pleaseGetCurrentQueries()
661 ostr
<< getMT()->d_waiters
.size() <<" currently outstanding questions\n";
663 boost::format
fmt("%1% %|40t|%2% %|47t|%3% %|63t|%4% %|68t|%5%\n");
665 ostr
<< (fmt
% "qname" % "qtype" % "remote" % "tcp" % "chained");
667 for(const auto& mthread
: getMT()->d_waiters
) {
668 const PacketID
& pident
= mthread
.key
;
670 % pident
.domain
.toLogString() /* ?? */ % DNSRecordContent::NumberToType(pident
.type
)
671 % pident
.remote
.toString() % (pident
.sock
? 'Y' : 'n')
672 % (pident
.fd
== -1 ? 'Y' : 'n')
679 return new string(ostr
.str());
682 static string
doCurrentQueries()
684 return broadcastAccFunction
<string
>(pleaseGetCurrentQueries
);
687 uint64_t* pleaseGetThrottleSize()
689 return new uint64_t(SyncRes::getThrottledServersSize());
692 static uint64_t getThrottleSize()
694 return broadcastAccFunction
<uint64_t>(pleaseGetThrottleSize
);
697 uint64_t* pleaseGetNegCacheSize()
699 uint64_t tmp
=(SyncRes::getNegCacheSize());
700 return new uint64_t(tmp
);
703 uint64_t getNegCacheSize()
705 return broadcastAccFunction
<uint64_t>(pleaseGetNegCacheSize
);
708 uint64_t* pleaseGetFailedHostsSize()
710 uint64_t tmp
=(SyncRes::getThrottledServersSize());
711 return new uint64_t(tmp
);
713 uint64_t getFailedHostsSize()
715 return broadcastAccFunction
<uint64_t>(pleaseGetFailedHostsSize
);
718 uint64_t* pleaseGetNsSpeedsSize()
720 return new uint64_t(SyncRes::getNSSpeedsSize());
723 uint64_t getNsSpeedsSize()
725 return broadcastAccFunction
<uint64_t>(pleaseGetNsSpeedsSize
);
728 uint64_t* pleaseGetConcurrentQueries()
730 return new uint64_t(getMT() ? getMT()->numProcesses() : 0);
733 static uint64_t getConcurrentQueries()
735 return broadcastAccFunction
<uint64_t>(pleaseGetConcurrentQueries
);
738 uint64_t* pleaseGetCacheSize()
740 return new uint64_t(t_RC
? t_RC
->size() : 0);
743 uint64_t* pleaseGetCacheBytes()
745 return new uint64_t(t_RC
? t_RC
->bytes() : 0);
749 uint64_t doGetCacheSize()
751 return broadcastAccFunction
<uint64_t>(pleaseGetCacheSize
);
754 uint64_t doGetAvgLatencyUsec()
756 return (uint64_t) g_stats
.avgLatencyUsec
;
760 uint64_t doGetCacheBytes()
762 return broadcastAccFunction
<uint64_t>(pleaseGetCacheBytes
);
765 uint64_t* pleaseGetCacheHits()
767 return new uint64_t(t_RC
? t_RC
->cacheHits
: 0);
770 uint64_t doGetCacheHits()
772 return broadcastAccFunction
<uint64_t>(pleaseGetCacheHits
);
775 uint64_t* pleaseGetCacheMisses()
777 return new uint64_t(t_RC
? t_RC
->cacheMisses
: 0);
780 uint64_t doGetCacheMisses()
782 return broadcastAccFunction
<uint64_t>(pleaseGetCacheMisses
);
786 uint64_t* pleaseGetPacketCacheSize()
788 return new uint64_t(t_packetCache
? t_packetCache
->size() : 0);
791 uint64_t* pleaseGetPacketCacheBytes()
793 return new uint64_t(t_packetCache
? t_packetCache
->bytes() : 0);
797 uint64_t doGetPacketCacheSize()
799 return broadcastAccFunction
<uint64_t>(pleaseGetPacketCacheSize
);
802 uint64_t doGetPacketCacheBytes()
804 return broadcastAccFunction
<uint64_t>(pleaseGetPacketCacheBytes
);
808 uint64_t* pleaseGetPacketCacheHits()
810 return new uint64_t(t_packetCache
? t_packetCache
->d_hits
: 0);
813 uint64_t doGetPacketCacheHits()
815 return broadcastAccFunction
<uint64_t>(pleaseGetPacketCacheHits
);
818 uint64_t* pleaseGetPacketCacheMisses()
820 return new uint64_t(t_packetCache
? t_packetCache
->d_misses
: 0);
823 uint64_t doGetPacketCacheMisses()
825 return broadcastAccFunction
<uint64_t>(pleaseGetPacketCacheMisses
);
828 uint64_t doGetMallocated()
830 // this turned out to be broken
831 /* struct mallinfo mi = mallinfo();
832 return mi.uordblks; */
836 extern ResponseStats g_rs
;
838 void registerAllStats()
840 static std::atomic_flag s_init
= ATOMIC_FLAG_INIT
;
841 if(s_init
.test_and_set())
844 addGetStat("questions", &g_stats
.qcounter
);
845 addGetStat("ipv6-questions", &g_stats
.ipv6qcounter
);
846 addGetStat("tcp-questions", &g_stats
.tcpqcounter
);
848 addGetStat("cache-hits", doGetCacheHits
);
849 addGetStat("cache-misses", doGetCacheMisses
);
850 addGetStat("cache-entries", doGetCacheSize
);
851 addGetStat("max-cache-entries", []() { return g_maxCacheEntries
.load(); });
852 addGetStat("max-packetcache-entries", []() { return g_maxPacketCacheEntries
.load();});
853 addGetStat("cache-bytes", doGetCacheBytes
);
855 addGetStat("packetcache-hits", doGetPacketCacheHits
);
856 addGetStat("packetcache-misses", doGetPacketCacheMisses
);
857 addGetStat("packetcache-entries", doGetPacketCacheSize
);
858 addGetStat("packetcache-bytes", doGetPacketCacheBytes
);
860 addGetStat("malloc-bytes", doGetMallocated
);
862 addGetStat("servfail-answers", &g_stats
.servFails
);
863 addGetStat("nxdomain-answers", &g_stats
.nxDomains
);
864 addGetStat("noerror-answers", &g_stats
.noErrors
);
866 addGetStat("unauthorized-udp", &g_stats
.unauthorizedUDP
);
867 addGetStat("unauthorized-tcp", &g_stats
.unauthorizedTCP
);
868 addGetStat("tcp-client-overflow", &g_stats
.tcpClientOverflow
);
870 addGetStat("client-parse-errors", &g_stats
.clientParseError
);
871 addGetStat("server-parse-errors", &g_stats
.serverParseError
);
872 addGetStat("too-old-drops", &g_stats
.tooOldDrops
);
873 addGetStat("query-pipe-full-drops", &g_stats
.queryPipeFullDrops
);
875 addGetStat("answers0-1", &g_stats
.answers0_1
);
876 addGetStat("answers1-10", &g_stats
.answers1_10
);
877 addGetStat("answers10-100", &g_stats
.answers10_100
);
878 addGetStat("answers100-1000", &g_stats
.answers100_1000
);
879 addGetStat("answers-slow", &g_stats
.answersSlow
);
881 addGetStat("x-ourtime0-1", &g_stats
.ourtime0_1
);
882 addGetStat("x-ourtime1-2", &g_stats
.ourtime1_2
);
883 addGetStat("x-ourtime2-4", &g_stats
.ourtime2_4
);
884 addGetStat("x-ourtime4-8", &g_stats
.ourtime4_8
);
885 addGetStat("x-ourtime8-16", &g_stats
.ourtime8_16
);
886 addGetStat("x-ourtime16-32", &g_stats
.ourtime16_32
);
887 addGetStat("x-ourtime-slow", &g_stats
.ourtimeSlow
);
889 addGetStat("auth4-answers0-1", &g_stats
.auth4Answers0_1
);
890 addGetStat("auth4-answers1-10", &g_stats
.auth4Answers1_10
);
891 addGetStat("auth4-answers10-100", &g_stats
.auth4Answers10_100
);
892 addGetStat("auth4-answers100-1000", &g_stats
.auth4Answers100_1000
);
893 addGetStat("auth4-answers-slow", &g_stats
.auth4AnswersSlow
);
895 addGetStat("auth6-answers0-1", &g_stats
.auth6Answers0_1
);
896 addGetStat("auth6-answers1-10", &g_stats
.auth6Answers1_10
);
897 addGetStat("auth6-answers10-100", &g_stats
.auth6Answers10_100
);
898 addGetStat("auth6-answers100-1000", &g_stats
.auth6Answers100_1000
);
899 addGetStat("auth6-answers-slow", &g_stats
.auth6AnswersSlow
);
902 addGetStat("qa-latency", doGetAvgLatencyUsec
);
903 addGetStat("x-our-latency", []() { return g_stats
.avgLatencyOursUsec
; });
904 addGetStat("unexpected-packets", &g_stats
.unexpectedCount
);
905 addGetStat("case-mismatches", &g_stats
.caseMismatchCount
);
906 addGetStat("spoof-prevents", &g_stats
.spoofCount
);
908 addGetStat("nsset-invalidations", &g_stats
.nsSetInvalidations
);
910 addGetStat("resource-limits", &g_stats
.resourceLimits
);
911 addGetStat("over-capacity-drops", &g_stats
.overCapacityDrops
);
912 addGetStat("policy-drops", &g_stats
.policyDrops
);
913 addGetStat("no-packet-error", &g_stats
.noPacketError
);
914 addGetStat("dlg-only-drops", &SyncRes::s_nodelegated
);
915 addGetStat("ignored-packets", &g_stats
.ignoredCount
);
916 addGetStat("max-mthread-stack", &g_stats
.maxMThreadStackUsage
);
918 addGetStat("negcache-entries", boost::bind(getNegCacheSize
));
919 addGetStat("throttle-entries", boost::bind(getThrottleSize
));
921 addGetStat("nsspeeds-entries", boost::bind(getNsSpeedsSize
));
922 addGetStat("failed-host-entries", boost::bind(getFailedHostsSize
));
924 addGetStat("concurrent-queries", boost::bind(getConcurrentQueries
));
925 addGetStat("security-status", &g_security_status
);
926 addGetStat("outgoing-timeouts", &SyncRes::s_outgoingtimeouts
);
927 addGetStat("outgoing4-timeouts", &SyncRes::s_outgoing4timeouts
);
928 addGetStat("outgoing6-timeouts", &SyncRes::s_outgoing6timeouts
);
929 addGetStat("auth-zone-queries", &SyncRes::s_authzonequeries
);
930 addGetStat("tcp-outqueries", &SyncRes::s_tcpoutqueries
);
931 addGetStat("all-outqueries", &SyncRes::s_outqueries
);
932 addGetStat("ipv6-outqueries", &g_stats
.ipv6queries
);
933 addGetStat("throttled-outqueries", &SyncRes::s_throttledqueries
);
934 addGetStat("dont-outqueries", &SyncRes::s_dontqueries
);
935 addGetStat("throttled-out", &SyncRes::s_throttledqueries
);
936 addGetStat("unreachables", &SyncRes::s_unreachables
);
937 addGetStat("ecs-queries", &SyncRes::s_ecsqueries
);
938 addGetStat("ecs-responses", &SyncRes::s_ecsresponses
);
939 addGetStat("chain-resends", &g_stats
.chainResends
);
940 addGetStat("tcp-clients", boost::bind(TCPConnection::getCurrentConnections
));
943 addGetStat("udp-recvbuf-errors", boost::bind(udpErrorStats
, "udp-recvbuf-errors"));
944 addGetStat("udp-sndbuf-errors", boost::bind(udpErrorStats
, "udp-sndbuf-errors"));
945 addGetStat("udp-noport-errors", boost::bind(udpErrorStats
, "udp-noport-errors"));
946 addGetStat("udp-in-errors", boost::bind(udpErrorStats
, "udp-in-errors"));
949 addGetStat("edns-ping-matches", &g_stats
.ednsPingMatches
);
950 addGetStat("edns-ping-mismatches", &g_stats
.ednsPingMismatches
);
951 addGetStat("dnssec-queries", &g_stats
.dnssecQueries
);
953 addGetStat("noping-outqueries", &g_stats
.noPingOutQueries
);
954 addGetStat("noedns-outqueries", &g_stats
.noEdnsOutQueries
);
956 addGetStat("uptime", calculateUptime
);
957 addGetStat("real-memory-usage", boost::bind(getRealMemoryUsage
, string()));
958 addGetStat("fd-usage", boost::bind(getOpenFileDescriptors
, string()));
960 // addGetStat("query-rate", getQueryRate);
961 addGetStat("user-msec", getUserTimeMsec
);
962 addGetStat("sys-msec", getSysTimeMsec
);
965 addGetStat("memory-allocs", boost::bind(&MallocTracer::getAllocs
, g_mtracer
, string()));
966 addGetStat("memory-alloc-flux", boost::bind(&MallocTracer::getAllocFlux
, g_mtracer
, string()));
967 addGetStat("memory-allocated", boost::bind(&MallocTracer::getTotAllocated
, g_mtracer
, string()));
970 addGetStat("dnssec-validations", &g_stats
.dnssecValidations
);
971 addGetStat("dnssec-result-insecure", &g_stats
.dnssecResults
[Insecure
]);
972 addGetStat("dnssec-result-secure", &g_stats
.dnssecResults
[Secure
]);
973 addGetStat("dnssec-result-bogus", &g_stats
.dnssecResults
[Bogus
]);
974 addGetStat("dnssec-result-indeterminate", &g_stats
.dnssecResults
[Indeterminate
]);
975 addGetStat("dnssec-result-nta", &g_stats
.dnssecResults
[NTA
]);
977 addGetStat("policy-result-noaction", &g_stats
.policyResults
[DNSFilterEngine::PolicyKind::NoAction
]);
978 addGetStat("policy-result-drop", &g_stats
.policyResults
[DNSFilterEngine::PolicyKind::Drop
]);
979 addGetStat("policy-result-nxdomain", &g_stats
.policyResults
[DNSFilterEngine::PolicyKind::NXDOMAIN
]);
980 addGetStat("policy-result-nodata", &g_stats
.policyResults
[DNSFilterEngine::PolicyKind::NODATA
]);
981 addGetStat("policy-result-truncate", &g_stats
.policyResults
[DNSFilterEngine::PolicyKind::Truncate
]);
982 addGetStat("policy-result-custom", &g_stats
.policyResults
[DNSFilterEngine::PolicyKind::Custom
]);
985 static void doExitGeneric(bool nicely
)
987 L
<<Logger::Error
<<"Exiting on user request"<<endl
;
988 extern RecursorControlChannel s_rcc
;
989 s_rcc
.~RecursorControlChannel();
991 extern string s_pidfname
;
992 if(!s_pidfname
.empty())
993 unlink(s_pidfname
.c_str()); // we can at least try..
1000 static void doExit()
1002 doExitGeneric(false);
1005 static void doExitNicely()
1007 doExitGeneric(true);
1010 vector
<pair
<DNSName
, uint16_t> >* pleaseGetQueryRing()
1012 typedef pair
<DNSName
,uint16_t> query_t
;
1013 vector
<query_t
>* ret
= new vector
<query_t
>();
1016 ret
->reserve(t_queryring
->size());
1018 for(const query_t
& q
: *t_queryring
) {
1023 vector
<pair
<DNSName
,uint16_t> >* pleaseGetServfailQueryRing()
1025 typedef pair
<DNSName
,uint16_t> query_t
;
1026 vector
<query_t
>* ret
= new vector
<query_t
>();
1027 if(!t_servfailqueryring
)
1029 ret
->reserve(t_servfailqueryring
->size());
1030 for(const query_t
& q
: *t_servfailqueryring
) {
1038 typedef boost::function
<vector
<ComboAddress
>*()> pleaseremotefunc_t
;
1039 typedef boost::function
<vector
<pair
<DNSName
,uint16_t> >*()> pleasequeryfunc_t
;
1041 vector
<ComboAddress
>* pleaseGetRemotes()
1043 vector
<ComboAddress
>* ret
= new vector
<ComboAddress
>();
1047 ret
->reserve(t_remotes
->size());
1048 for(const ComboAddress
& ca
: *t_remotes
) {
1054 vector
<ComboAddress
>* pleaseGetServfailRemotes()
1056 vector
<ComboAddress
>* ret
= new vector
<ComboAddress
>();
1057 if(!t_servfailremotes
)
1059 ret
->reserve(t_servfailremotes
->size());
1060 for(const ComboAddress
& ca
: *t_servfailremotes
) {
1066 vector
<ComboAddress
>* pleaseGetLargeAnswerRemotes()
1068 vector
<ComboAddress
>* ret
= new vector
<ComboAddress
>();
1069 if(!t_largeanswerremotes
)
1071 ret
->reserve(t_largeanswerremotes
->size());
1072 for(const ComboAddress
& ca
: *t_largeanswerremotes
) {
1078 string
doGenericTopRemotes(pleaseremotefunc_t func
)
1080 typedef map
<ComboAddress
, int, ComboAddress::addressOnlyLessThan
> counts_t
;
1083 vector
<ComboAddress
> remotes
=broadcastAccFunction
<vector
<ComboAddress
> >(func
);
1085 unsigned int total
=0;
1086 for(const ComboAddress
& ca
: remotes
) {
1091 typedef std::multimap
<int, ComboAddress
> rcounts_t
;
1094 for(counts_t::const_iterator i
=counts
.begin(); i
!= counts
.end(); ++i
)
1095 rcounts
.insert(make_pair(-i
->second
, i
->first
));
1098 ret
<<"Over last "<<total
<<" entries:\n";
1099 format
fmt("%.02f%%\t%s\n");
1100 int limit
=0, accounted
=0;
1102 for(rcounts_t::const_iterator i
=rcounts
.begin(); i
!= rcounts
.end() && limit
< 20; ++i
, ++limit
) {
1103 ret
<< fmt
% (-100.0*i
->first
/total
) % i
->second
.toString();
1104 accounted
+= -i
->first
;
1106 ret
<< '\n' << fmt
% (100.0*(total
-accounted
)/total
) % "rest";
1112 typedef vector
<vector
<string
> > pubs_t
;
1116 void sortPublicSuffixList()
1118 for(const char** p
=g_pubsuffix
; *p
; ++p
) {
1119 string low
=toLower(*p
);
1121 vector
<string
> parts
;
1122 stringtok(parts
, low
, ".");
1123 reverse(parts
.begin(), parts
.end());
1124 g_pubs
.push_back(parts
);
1126 sort(g_pubs
.begin(), g_pubs
.end());
1129 // XXX DNSName Pain - this function should benefit from native DNSName methods
1130 DNSName
getRegisteredName(const DNSName
& dom
)
1132 auto parts
=dom
.getRawLabels();
1135 reverse(parts
.begin(), parts
.end());
1136 for(string
& str
: parts
) { str
=toLower(str
); };
1140 while(!parts
.empty()) {
1141 if(parts
.size()==1 || binary_search(g_pubs
.begin(), g_pubs
.end(), parts
)) {
1147 for(auto p
= parts
.crbegin(); p
!= parts
.crend(); ++p
) {
1150 return DNSName(ret
);
1153 last
=parts
[parts
.size()-1];
1154 parts
.resize(parts
.size()-1);
1156 return DNSName("??");
1159 static DNSName
nopFilter(const DNSName
& name
)
1164 string
doGenericTopQueries(pleasequeryfunc_t func
, boost::function
<DNSName(const DNSName
&)> filter
=nopFilter
)
1166 typedef pair
<DNSName
,uint16_t> query_t
;
1167 typedef map
<query_t
, int> counts_t
;
1169 vector
<query_t
> queries
=broadcastAccFunction
<vector
<query_t
> >(func
);
1171 unsigned int total
=0;
1172 for(const query_t
& q
: queries
) {
1174 counts
[make_pair(filter(q
.first
),q
.second
)]++;
1177 typedef std::multimap
<int, query_t
> rcounts_t
;
1180 for(counts_t::const_iterator i
=counts
.begin(); i
!= counts
.end(); ++i
)
1181 rcounts
.insert(make_pair(-i
->second
, i
->first
));
1184 ret
<<"Over last "<<total
<<" entries:\n";
1185 format
fmt("%.02f%%\t%s\n");
1186 int limit
=0, accounted
=0;
1188 for(rcounts_t::const_iterator i
=rcounts
.begin(); i
!= rcounts
.end() && limit
< 20; ++i
, ++limit
) {
1189 ret
<< fmt
% (-100.0*i
->first
/total
) % (i
->second
.first
.toString()+"|"+DNSRecordContent::NumberToType(i
->second
.second
));
1190 accounted
+= -i
->first
;
1192 ret
<< '\n' << fmt
% (100.0*(total
-accounted
)/total
) % "rest";
1199 static string
* nopFunction()
1201 return new string("pong\n");
1204 string
RecursorControlParser::getAnswer(const string
& question
, RecursorControlParser::func_t
** command
)
1207 vector
<string
> words
;
1208 stringtok(words
, question
);
1211 return "invalid command\n";
1213 string cmd
=toLower(words
[0]);
1214 vector
<string
>::const_iterator begin
=words
.begin()+1, end
=words
.end();
1216 // should probably have a smart dispatcher here, like auth has
1219 "add-nta DOMAIN [REASON] add a Negative Trust Anchor for DOMAIN with the comment REASON\n"
1220 "add-ta DOMAIN DSRECORD add a Trust Anchor for DOMAIN with data DSRECORD\n"
1221 "current-queries show currently active queries\n"
1222 "clear-nta [DOMAIN]... Clear the Negative Trust Anchor for DOMAINs, if no DOMAIN is specified, remove all\n"
1223 "clear-ta [DOMAIN]... Clear the Trust Anchor for DOMAINs\n"
1224 "dump-cache <filename> dump cache contents to the named file\n"
1225 "dump-edns [status] <filename> dump EDNS status to the named file\n"
1226 "dump-nsspeeds <filename> dump nsspeeds statistics to the named file\n"
1227 "dump-rpz <zone name> <filename> dump the content of a RPZ zone to the named file\n"
1228 "get [key1] [key2] .. get specific statistics\n"
1229 "get-all get all statistics\n"
1230 "get-ntas get all configured Negative Trust Anchors\n"
1231 "get-tas get all configured Trust Anchors\n"
1232 "get-parameter [key1] [key2] .. get configuration parameters\n"
1233 "get-qtypelist get QType statistics\n"
1234 " notice: queries from cache aren't being counted yet\n"
1235 "help get this list\n"
1236 "ping check that all threads are alive\n"
1237 "quit stop the recursor daemon\n"
1238 "quit-nicely stop the recursor daemon nicely\n"
1239 "reload-acls reload ACLS\n"
1240 "reload-lua-script [filename] (re)load Lua script\n"
1241 "reload-lua-config [filename] (re)load Lua configuration file\n"
1242 "reload-zones reload all auth and forward zones\n"
1243 "set-max-cache-entries value set new maximum cache size\n"
1244 "set-max-packetcache-entries val set new maximum packet cache size\n"
1245 "set-minimum-ttl value set minimum-ttl-override\n"
1246 "set-carbon-server set a carbon server for telemetry\n"
1247 "set-dnssec-log-bogus SETTING enable (SETTING=yes) or disable (SETTING=no) logging of DNSSEC validation failures\n"
1248 "trace-regex [regex] emit resolution trace for matching queries (empty regex to clear trace)\n"
1249 "top-largeanswer-remotes show top remotes receiving large answers\n"
1250 "top-queries show top queries\n"
1251 "top-pub-queries show top queries grouped by public suffix list\n"
1252 "top-remotes show top remotes\n"
1253 "top-servfail-queries show top queries receiving servfail answers\n"
1254 "top-pub-servfail-queries show top queries receiving servfail answers grouped by public suffix list\n"
1255 "top-servfail-remotes show top remotes receiving servfail answers\n"
1256 "unload-lua-script unload Lua script\n"
1257 "version return Recursor version number\n"
1258 "wipe-cache domain0 [domain1] .. wipe domain data from cache\n";
1261 return getAllStats();
1264 return doGet(begin
, end
);
1266 if(cmd
=="get-parameter")
1267 return doGetParameter(begin
, end
);
1274 if(cmd
=="version") {
1275 return getPDNSVersion()+"\n";
1278 if(cmd
=="quit-nicely") {
1279 *command
=&doExitNicely
;
1280 return "bye nicely\n";
1283 if(cmd
=="dump-cache")
1284 return doDumpCache(begin
, end
);
1286 if(cmd
=="dump-ednsstatus" || cmd
=="dump-edns")
1287 return doDumpEDNSStatus(begin
, end
);
1289 if(cmd
=="dump-nsspeeds")
1290 return doDumpNSSpeeds(begin
, end
);
1292 if(cmd
=="dump-rpz") {
1293 return doDumpRPZ(begin
, end
);
1296 if(cmd
=="wipe-cache" || cmd
=="flushname")
1297 return doWipeCache(begin
, end
);
1299 if(cmd
=="reload-lua-script")
1300 return doQueueReloadLuaScript(begin
, end
);
1302 if(cmd
=="reload-lua-config") {
1304 ::arg().set("lua-config-file") = *begin
;
1307 loadRecursorLuaConfig(::arg()["lua-config-file"], false);
1308 L
<<Logger::Warning
<<"Reloaded Lua configuration file '"<<::arg()["lua-config-file"]<<"', requested via control channel"<<endl
;
1309 return "Reloaded Lua configuration file '"+::arg()["lua-config-file"]+"'\n";
1311 catch(std::exception
& e
) {
1312 return "Unable to load Lua script from '"+::arg()["lua-config-file"]+"': "+e
.what()+"\n";
1314 catch(const PDNSException
& e
) {
1315 return "Unable to load Lua script from '"+::arg()["lua-config-file"]+"': "+e
.reason
+"\n";
1319 if(cmd
=="set-carbon-server")
1320 return doSetCarbonServer(begin
, end
);
1322 if(cmd
=="trace-regex")
1323 return doTraceRegex(begin
, end
);
1325 if(cmd
=="unload-lua-script") {
1326 vector
<string
> empty
;
1327 empty
.push_back(string());
1328 return doQueueReloadLuaScript(empty
.begin(), empty
.end());
1331 if(cmd
=="reload-acls") {
1332 if(!::arg()["chroot"].empty()) {
1333 L
<<Logger::Error
<<"Unable to reload ACL when chroot()'ed, requested via control channel"<<endl
;
1334 return "Unable to reload ACL when chroot()'ed, please restart\n";
1340 catch(std::exception
& e
)
1342 L
<<Logger::Error
<<"Reloading ACLs failed (Exception: "<<e
.what()<<")"<<endl
;
1343 return e
.what() + string("\n");
1345 catch(PDNSException
& ae
)
1347 L
<<Logger::Error
<<"Reloading ACLs failed (PDNSException: "<<ae
.reason
<<")"<<endl
;
1348 return ae
.reason
+ string("\n");
1354 if(cmd
=="top-remotes")
1355 return doGenericTopRemotes(pleaseGetRemotes
);
1357 if(cmd
=="top-queries")
1358 return doGenericTopQueries(pleaseGetQueryRing
);
1360 if(cmd
=="top-pub-queries")
1361 return doGenericTopQueries(pleaseGetQueryRing
, getRegisteredName
);
1363 if(cmd
=="top-servfail-queries")
1364 return doGenericTopQueries(pleaseGetServfailQueryRing
);
1366 if(cmd
=="top-pub-servfail-queries")
1367 return doGenericTopQueries(pleaseGetServfailQueryRing
, getRegisteredName
);
1370 if(cmd
=="top-servfail-remotes")
1371 return doGenericTopRemotes(pleaseGetServfailRemotes
);
1373 if(cmd
=="top-largeanswer-remotes")
1374 return doGenericTopRemotes(pleaseGetLargeAnswerRemotes
);
1377 if(cmd
=="current-queries")
1378 return doCurrentQueries();
1381 return broadcastAccFunction
<string
>(nopFunction
);
1384 if(cmd
=="reload-zones") {
1385 if(!::arg()["chroot"].empty()) {
1386 L
<<Logger::Error
<<"Unable to reload zones and forwards when chroot()'ed, requested via control channel"<<endl
;
1387 return "Unable to reload zones and forwards when chroot()'ed, please restart\n";
1389 return reloadAuthAndForwards();
1392 if(cmd
=="set-max-cache-entries") {
1393 return setMaxCacheEntries(begin
, end
);
1395 if(cmd
=="set-max-packetcache-entries") {
1396 return setMaxPacketCacheEntries(begin
, end
);
1399 if(cmd
=="set-minimum-ttl") {
1400 return setMinimumTTL(begin
, end
);
1403 if(cmd
=="get-qtypelist") {
1404 return g_rs
.getQTypeReport();
1407 if(cmd
=="add-nta") {
1408 return doAddNTA(begin
, end
);
1411 if(cmd
=="clear-nta") {
1412 return doClearNTA(begin
, end
);
1415 if(cmd
=="get-ntas") {
1420 return doAddTA(begin
, end
);
1423 if(cmd
=="clear-ta") {
1424 return doClearTA(begin
, end
);
1427 if(cmd
=="get-tas") {
1431 if (cmd
=="set-dnssec-log-bogus")
1432 return doSetDnssecLogBogus(begin
, end
);
1434 return "Unknown command '"+cmd
+"', try 'help'\n";