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 map
<string
, const uint32_t*> d_get32bitpointers
;
43 map
<string
, const uint64_t*> d_get64bitpointers
;
44 map
<string
, const std::atomic
<uint64_t>*> d_getatomics
;
45 map
<string
, function
< uint64_t() > > d_get64bitmembers
;
46 pthread_mutex_t d_dynmetricslock
= PTHREAD_MUTEX_INITIALIZER
;
47 map
<string
, std::atomic
<unsigned long>* > d_dynmetrics
;
48 void addGetStat(const string
& name
, const uint32_t* place
)
50 d_get32bitpointers
[name
]=place
;
52 void addGetStat(const string
& name
, const uint64_t* place
)
54 d_get64bitpointers
[name
]=place
;
57 void addGetStat(const string
& name
, const std::atomic
<uint64_t>* place
)
59 d_getatomics
[name
]=place
;
63 void addGetStat(const string
& name
, function
<uint64_t ()> f
)
65 d_get64bitmembers
[name
]=f
;
69 std::atomic
<unsigned long>* getDynMetric(const std::string
& str
)
71 Lock
l(&d_dynmetricslock
);
72 auto f
= d_dynmetrics
.find(str
);
73 if(f
!= d_dynmetrics
.end())
76 auto ret
= new std::atomic
<unsigned long>();
77 d_dynmetrics
[str
]= ret
;
81 static optional
<uint64_t> get(const string
& name
)
83 optional
<uint64_t> ret
;
85 if(d_get32bitpointers
.count(name
))
86 return *d_get32bitpointers
.find(name
)->second
;
87 if(d_get64bitpointers
.count(name
))
88 return *d_get64bitpointers
.find(name
)->second
;
89 if(d_getatomics
.count(name
))
90 return d_getatomics
.find(name
)->second
->load();
91 if(d_get64bitmembers
.count(name
))
92 return d_get64bitmembers
.find(name
)->second();
94 Lock
l(&d_dynmetricslock
);
95 auto f
=rplookup(d_dynmetrics
, name
);
102 optional
<uint64_t> getStatByName(const std::string
& name
)
107 map
<string
,string
> getAllStatsMap()
109 map
<string
,string
> ret
;
111 for(const auto& the32bits
: d_get32bitpointers
) {
112 ret
.insert(make_pair(the32bits
.first
, std::to_string(*the32bits
.second
)));
114 for(const auto& the64bits
: d_get64bitpointers
) {
115 ret
.insert(make_pair(the64bits
.first
, std::to_string(*the64bits
.second
)));
117 for(const auto& atomic
: d_getatomics
) {
118 ret
.insert(make_pair(atomic
.first
, std::to_string(atomic
.second
->load())));
121 for(const auto& the64bitmembers
: d_get64bitmembers
) {
122 if(the64bitmembers
.first
== "cache-bytes" || the64bitmembers
.first
=="packetcache-bytes")
123 continue; // too slow for 'get-all'
124 ret
.insert(make_pair(the64bitmembers
.first
, std::to_string(the64bitmembers
.second())));
126 Lock
l(&d_dynmetricslock
);
127 for(const auto& a
: d_dynmetrics
)
128 ret
.insert({a
.first
, std::to_string(*a
.second
)});
134 typedef map
<string
, string
> varmap_t
;
135 varmap_t varmap
= getAllStatsMap();
137 for(varmap_t::value_type
& tup
: varmap
) {
138 ret
+= tup
.first
+ "\t" + tup
.second
+"\n";
144 string
doGet(T begin
, T end
)
148 for(T i
=begin
; i
!= end
; ++i
) {
149 optional
<uint64_t> num
=get(*i
);
151 ret
+=std::to_string(*num
)+"\n";
159 string
doGetParameter(T begin
, T end
)
163 using boost::replace_all
;
164 for(T i
=begin
; i
!= end
; ++i
) {
165 if(::arg().parmIsset(*i
)) {
167 replace_all(parm
, "\\", "\\\\");
168 replace_all(parm
, "\"", "\\\"");
169 replace_all(parm
, "\n", "\\n");
170 ret
+= *i
+"=\""+ parm
+"\"\n";
173 ret
+= *i
+" not known\n";
179 static uint64_t dumpNegCache(NegCache
& negcache
, int fd
)
181 FILE* fp
=fdopen(dup(fd
), "w");
182 if(!fp
) { // dup probably failed
186 fprintf(fp
, "; negcache dump from thread follows\n;\n");
187 ret
= negcache
.dumpToFile(fp
);
192 static uint64_t* pleaseDump(int fd
)
194 return new uint64_t(t_RC
->doDump(fd
) + dumpNegCache(SyncRes::t_sstorage
.negcache
, fd
) + t_packetCache
->doDump(fd
));
197 static uint64_t* pleaseDumpNSSpeeds(int fd
)
199 return new uint64_t(SyncRes::doDumpNSSpeeds(fd
));
203 string
doDumpNSSpeeds(T begin
, T end
)
211 int fd
=open(fname
.c_str(), O_CREAT
| O_EXCL
| O_WRONLY
, 0660);
213 return "Error opening dump file for writing: "+string(strerror(errno
))+"\n";
216 total
= broadcastAccFunction
<uint64_t>(boost::bind(pleaseDumpNSSpeeds
, fd
));
221 return "dumped "+std::to_string(total
)+" records\n";
225 string
doDumpCache(T begin
, T end
)
233 int fd
=open(fname
.c_str(), O_CREAT
| O_EXCL
| O_WRONLY
, 0660);
235 return "Error opening dump file for writing: "+string(strerror(errno
))+"\n";
238 total
= broadcastAccFunction
<uint64_t>(boost::bind(pleaseDump
, fd
));
243 return "dumped "+std::to_string(total
)+" records\n";
247 string
doDumpEDNSStatus(T begin
, T end
)
255 int fd
=open(fname
.c_str(), O_CREAT
| O_EXCL
| O_WRONLY
, 0660);
257 return "Error opening dump file for writing: "+string(strerror(errno
))+"\n";
259 SyncRes::doEDNSDumpAndClose(fd
);
264 uint64_t* pleaseWipeCache(const DNSName
& canon
, bool subtree
)
266 return new uint64_t(t_RC
->doWipeCache(canon
, subtree
));
269 uint64_t* pleaseWipePacketCache(const DNSName
& canon
, bool subtree
)
271 return new uint64_t(t_packetCache
->doWipePacketCache(canon
,0xffff, subtree
));
275 uint64_t* pleaseWipeAndCountNegCache(const DNSName
& canon
, bool subtree
)
277 uint64_t ret
= SyncRes::wipeNegCache(canon
, subtree
);
278 return new uint64_t(ret
);
283 string
doWipeCache(T begin
, T end
)
285 vector
<pair
<DNSName
, bool> > toWipe
;
286 for(T i
=begin
; i
!= end
; ++i
) {
291 if(boost::ends_with(*i
, "$")) {
292 canon
=DNSName(i
->substr(0, i
->size()-1));
297 } catch (std::exception
&e
) {
298 return "Error: " + std::string(e
.what()) + ", nothing wiped\n";
300 toWipe
.push_back({canon
, subtree
});
303 int count
=0, pcount
=0, countNeg
=0;
304 for (auto wipe
: toWipe
) {
305 count
+= broadcastAccFunction
<uint64_t>(boost::bind(pleaseWipeCache
, wipe
.first
, wipe
.second
));
306 pcount
+= broadcastAccFunction
<uint64_t>(boost::bind(pleaseWipePacketCache
, wipe
.first
, wipe
.second
));
307 countNeg
+=broadcastAccFunction
<uint64_t>(boost::bind(pleaseWipeAndCountNegCache
, wipe
.first
, wipe
.second
));
310 return "wiped "+std::to_string(count
)+" records, "+std::to_string(countNeg
)+" negative records, "+std::to_string(pcount
)+" packets\n";
314 string
doSetCarbonServer(T begin
, T end
)
316 Lock
l(&g_carbon_config_lock
);
318 ::arg().set("carbon-server").clear();
319 return "cleared carbon-server setting\n";
322 ::arg().set("carbon-server")=*begin
;
323 ret
="set carbon-server to '"+::arg()["carbon-server"]+"'\n";
326 ::arg().set("carbon-ourname")=*begin
;
327 ret
+="set carbon-ourname to '"+*begin
+"'\n";
333 string
doSetDnssecLogBogus(T begin
, T end
)
335 if(checkDNSSECDisabled())
336 return "DNSSEC is disabled in the configuration, not changing the Bogus logging setting\n";
339 return "No DNSSEC Bogus logging setting specified\n";
341 if (pdns_iequals(*begin
, "on") || pdns_iequals(*begin
, "yes")) {
342 if (!g_dnssecLogBogus
) {
343 L
<<Logger::Warning
<<"Enabling DNSSEC Bogus logging, requested via control channel"<<endl
;
344 g_dnssecLogBogus
= true;
345 return "DNSSEC Bogus logging enabled\n";
347 return "DNSSEC Bogus logging was already enabled\n";
350 if (pdns_iequals(*begin
, "off") || pdns_iequals(*begin
, "no")) {
351 if (g_dnssecLogBogus
) {
352 L
<<Logger::Warning
<<"Disabling DNSSEC Bogus logging, requested via control channel"<<endl
;
353 g_dnssecLogBogus
= false;
354 return "DNSSEC Bogus logging disabled\n";
356 return "DNSSEC Bogus logging was already disabled\n";
359 return "Unknown DNSSEC Bogus setting: '" + *begin
+"'\n";
363 string
doAddNTA(T begin
, T end
)
365 if(checkDNSSECDisabled())
366 return "DNSSEC is disabled in the configuration, not adding a Negative Trust Anchor\n";
369 return "No NTA specified, doing nothing\n";
373 who
= DNSName(*begin
);
375 catch(std::exception
&e
) {
376 string
ret("Can't add Negative Trust Anchor: ");
384 while (begin
!= end
) {
390 L
<<Logger::Warning
<<"Adding Negative Trust Anchor for "<<who
<<" with reason '"<<why
<<"', requested via control channel"<<endl
;
391 g_luaconfs
.modify([who
, why
](LuaConfigItems
& lci
) {
392 lci
.negAnchors
[who
] = why
;
394 broadcastAccFunction
<uint64_t>(boost::bind(pleaseWipePacketCache
, who
, true));
395 return "Added Negative Trust Anchor for " + who
.toLogString() + " with reason '" + why
+ "'\n";
399 string
doClearNTA(T begin
, T end
)
401 if(checkDNSSECDisabled())
402 return "DNSSEC is disabled in the configuration, not removing a Negative Trust Anchor\n";
405 return "No Negative Trust Anchor specified, doing nothing.\n";
407 if (begin
+ 1 == end
&& *begin
== "*"){
408 L
<<Logger::Warning
<<"Clearing all Negative Trust Anchors, requested via control channel"<<endl
;
409 g_luaconfs
.modify([](LuaConfigItems
& lci
) {
410 lci
.negAnchors
.clear();
412 return "Cleared all Negative Trust Anchors.\n";
415 vector
<DNSName
> toRemove
;
417 while (begin
!= end
) {
419 return "Don't mix all Negative Trust Anchor removal with multiple Negative Trust Anchor removal. Nothing removed\n";
421 who
= DNSName(*begin
);
423 catch(std::exception
&e
) {
424 string
ret("Error: ");
426 ret
+= ". No Negative Anchors removed\n";
429 toRemove
.push_back(who
);
435 for (auto const &entry
: toRemove
) {
436 L
<<Logger::Warning
<<"Clearing Negative Trust Anchor for "<<entry
<<", requested via control channel"<<endl
;
437 g_luaconfs
.modify([entry
](LuaConfigItems
& lci
) {
438 lci
.negAnchors
.erase(entry
);
440 broadcastAccFunction
<uint64_t>(boost::bind(pleaseWipePacketCache
, entry
, true));
445 removed
+= " " + entry
.toStringRootDot();
447 return "Removed Negative Trust Anchors for " + removed
+ "\n";
450 static string
getNTAs()
452 if(checkDNSSECDisabled())
453 return "DNSSEC is disabled in the configuration\n";
455 string
ret("Configured Negative Trust Anchors:\n");
456 auto luaconf
= g_luaconfs
.getLocal();
457 for (auto negAnchor
: luaconf
->negAnchors
)
458 ret
+= negAnchor
.first
.toLogString() + "\t" + negAnchor
.second
+ "\n";
463 string
doAddTA(T begin
, T end
)
465 if(checkDNSSECDisabled())
466 return "DNSSEC is disabled in the configuration, not adding a Trust Anchor\n";
469 return "No TA specified, doing nothing\n";
473 who
= DNSName(*begin
);
475 catch(std::exception
&e
) {
476 string
ret("Can't add Trust Anchor: ");
484 while (begin
!= end
) {
485 what
+= *begin
+ " ";
490 L
<<Logger::Warning
<<"Adding Trust Anchor for "<<who
<<" with data '"<<what
<<"', requested via control channel";
491 g_luaconfs
.modify([who
, what
](LuaConfigItems
& lci
) {
492 auto ds
= unique_ptr
<DSRecordContent
>(dynamic_cast<DSRecordContent
*>(DSRecordContent::make(what
)));
493 lci
.dsAnchors
[who
].insert(*ds
);
495 broadcastAccFunction
<uint64_t>(boost::bind(pleaseWipePacketCache
, who
, true));
496 L
<<Logger::Warning
<<endl
;
497 return "Added Trust Anchor for " + who
.toStringRootDot() + " with data " + what
+ "\n";
499 catch(std::exception
&e
) {
500 L
<<Logger::Warning
<<", failed: "<<e
.what()<<endl
;
501 return "Unable to add Trust Anchor for " + who
.toStringRootDot() + ": " + e
.what() + "\n";
506 string
doClearTA(T begin
, T end
)
508 if(checkDNSSECDisabled())
509 return "DNSSEC is disabled in the configuration, not removing a Trust Anchor\n";
512 return "No Trust Anchor to clear\n";
514 vector
<DNSName
> toRemove
;
516 while (begin
!= end
) {
518 who
= DNSName(*begin
);
520 catch(std::exception
&e
) {
521 string
ret("Error: ");
523 ret
+= ". No Anchors removed\n";
527 return "Refusing to remove root Trust Anchor, no Anchors removed\n";
528 toRemove
.push_back(who
);
534 for (auto const &entry
: toRemove
) {
535 L
<<Logger::Warning
<<"Removing Trust Anchor for "<<entry
<<", requested via control channel"<<endl
;
536 g_luaconfs
.modify([entry
](LuaConfigItems
& lci
) {
537 lci
.dsAnchors
.erase(entry
);
539 broadcastAccFunction
<uint64_t>(boost::bind(pleaseWipePacketCache
, entry
, true));
544 removed
+= " " + entry
.toStringRootDot();
546 return "Removed Trust Anchor(s) for" + removed
+ "\n";
549 static string
getTAs()
551 if(checkDNSSECDisabled())
552 return "DNSSEC is disabled in the configuration\n";
554 string
ret("Configured Trust Anchors:\n");
555 auto luaconf
= g_luaconfs
.getLocal();
556 for (auto anchor
: luaconf
->dsAnchors
) {
557 ret
+= anchor
.first
.toLogString() + "\n";
558 for (auto e
: anchor
.second
) {
559 ret
+="\t\t"+e
.getZoneRepresentation() + "\n";
567 string
setMinimumTTL(T begin
, T end
)
570 return "Need to supply new minimum TTL number\n";
571 SyncRes::s_minimumTTL
= pdns_stou(*begin
);
572 return "New minimum TTL: " + std::to_string(SyncRes::s_minimumTTL
) + "\n";
576 static uint64_t getSysTimeMsec()
579 getrusage(RUSAGE_SELF
, &ru
);
580 return (ru
.ru_stime
.tv_sec
*1000ULL + ru
.ru_stime
.tv_usec
/1000);
583 static uint64_t getUserTimeMsec()
586 getrusage(RUSAGE_SELF
, &ru
);
587 return (ru
.ru_utime
.tv_sec
*1000ULL + ru
.ru_utime
.tv_usec
/1000);
590 static uint64_t calculateUptime()
592 return time(0) - g_stats
.startupTime
;
595 static string
* pleaseGetCurrentQueries()
599 ostr
<< getMT()->d_waiters
.size() <<" currently outstanding questions\n";
601 boost::format
fmt("%1% %|40t|%2% %|47t|%3% %|63t|%4% %|68t|%5%\n");
603 ostr
<< (fmt
% "qname" % "qtype" % "remote" % "tcp" % "chained");
605 for(const auto& mthread
: getMT()->d_waiters
) {
606 const PacketID
& pident
= mthread
.key
;
608 % pident
.domain
.toLogString() /* ?? */ % DNSRecordContent::NumberToType(pident
.type
)
609 % pident
.remote
.toString() % (pident
.sock
? 'Y' : 'n')
610 % (pident
.fd
== -1 ? 'Y' : 'n')
617 return new string(ostr
.str());
620 static string
doCurrentQueries()
622 return broadcastAccFunction
<string
>(pleaseGetCurrentQueries
);
625 uint64_t* pleaseGetThrottleSize()
627 return new uint64_t(SyncRes::getThrottledServersSize());
630 static uint64_t getThrottleSize()
632 return broadcastAccFunction
<uint64_t>(pleaseGetThrottleSize
);
635 uint64_t* pleaseGetNegCacheSize()
637 uint64_t tmp
=(SyncRes::getNegCacheSize());
638 return new uint64_t(tmp
);
641 uint64_t getNegCacheSize()
643 return broadcastAccFunction
<uint64_t>(pleaseGetNegCacheSize
);
646 uint64_t* pleaseGetFailedHostsSize()
648 uint64_t tmp
=(SyncRes::getThrottledServersSize());
649 return new uint64_t(tmp
);
651 uint64_t getFailedHostsSize()
653 return broadcastAccFunction
<uint64_t>(pleaseGetFailedHostsSize
);
656 uint64_t* pleaseGetNsSpeedsSize()
658 return new uint64_t(SyncRes::getNSSpeedsSize());
661 uint64_t getNsSpeedsSize()
663 return broadcastAccFunction
<uint64_t>(pleaseGetNsSpeedsSize
);
666 uint64_t* pleaseGetConcurrentQueries()
668 return new uint64_t(getMT() ? getMT()->numProcesses() : 0);
671 static uint64_t getConcurrentQueries()
673 return broadcastAccFunction
<uint64_t>(pleaseGetConcurrentQueries
);
676 uint64_t* pleaseGetCacheSize()
678 return new uint64_t(t_RC
? t_RC
->size() : 0);
681 uint64_t* pleaseGetCacheBytes()
683 return new uint64_t(t_RC
? t_RC
->bytes() : 0);
687 uint64_t doGetCacheSize()
689 return broadcastAccFunction
<uint64_t>(pleaseGetCacheSize
);
692 uint64_t doGetAvgLatencyUsec()
694 return (uint64_t) g_stats
.avgLatencyUsec
;
698 uint64_t doGetCacheBytes()
700 return broadcastAccFunction
<uint64_t>(pleaseGetCacheBytes
);
703 uint64_t* pleaseGetCacheHits()
705 return new uint64_t(t_RC
? t_RC
->cacheHits
: 0);
708 uint64_t doGetCacheHits()
710 return broadcastAccFunction
<uint64_t>(pleaseGetCacheHits
);
713 uint64_t* pleaseGetCacheMisses()
715 return new uint64_t(t_RC
? t_RC
->cacheMisses
: 0);
718 uint64_t doGetCacheMisses()
720 return broadcastAccFunction
<uint64_t>(pleaseGetCacheMisses
);
724 uint64_t* pleaseGetPacketCacheSize()
726 return new uint64_t(t_packetCache
? t_packetCache
->size() : 0);
729 uint64_t* pleaseGetPacketCacheBytes()
731 return new uint64_t(t_packetCache
? t_packetCache
->bytes() : 0);
735 uint64_t doGetPacketCacheSize()
737 return broadcastAccFunction
<uint64_t>(pleaseGetPacketCacheSize
);
740 uint64_t doGetPacketCacheBytes()
742 return broadcastAccFunction
<uint64_t>(pleaseGetPacketCacheBytes
);
746 uint64_t* pleaseGetPacketCacheHits()
748 return new uint64_t(t_packetCache
? t_packetCache
->d_hits
: 0);
751 uint64_t doGetPacketCacheHits()
753 return broadcastAccFunction
<uint64_t>(pleaseGetPacketCacheHits
);
756 uint64_t* pleaseGetPacketCacheMisses()
758 return new uint64_t(t_packetCache
? t_packetCache
->d_misses
: 0);
761 uint64_t doGetPacketCacheMisses()
763 return broadcastAccFunction
<uint64_t>(pleaseGetPacketCacheMisses
);
766 uint64_t doGetMallocated()
768 // this turned out to be broken
769 /* struct mallinfo mi = mallinfo();
770 return mi.uordblks; */
774 extern ResponseStats g_rs
;
776 void registerAllStats()
778 static bool s_init
= false;
783 addGetStat("questions", &g_stats
.qcounter
);
784 addGetStat("ipv6-questions", &g_stats
.ipv6qcounter
);
785 addGetStat("tcp-questions", &g_stats
.tcpqcounter
);
787 addGetStat("cache-hits", doGetCacheHits
);
788 addGetStat("cache-misses", doGetCacheMisses
);
789 addGetStat("cache-entries", doGetCacheSize
);
790 addGetStat("cache-bytes", doGetCacheBytes
);
792 addGetStat("packetcache-hits", doGetPacketCacheHits
);
793 addGetStat("packetcache-misses", doGetPacketCacheMisses
);
794 addGetStat("packetcache-entries", doGetPacketCacheSize
);
795 addGetStat("packetcache-bytes", doGetPacketCacheBytes
);
797 addGetStat("malloc-bytes", doGetMallocated
);
799 addGetStat("servfail-answers", &g_stats
.servFails
);
800 addGetStat("nxdomain-answers", &g_stats
.nxDomains
);
801 addGetStat("noerror-answers", &g_stats
.noErrors
);
803 addGetStat("unauthorized-udp", &g_stats
.unauthorizedUDP
);
804 addGetStat("unauthorized-tcp", &g_stats
.unauthorizedTCP
);
805 addGetStat("tcp-client-overflow", &g_stats
.tcpClientOverflow
);
807 addGetStat("client-parse-errors", &g_stats
.clientParseError
);
808 addGetStat("server-parse-errors", &g_stats
.serverParseError
);
809 addGetStat("too-old-drops", &g_stats
.tooOldDrops
);
811 addGetStat("answers0-1", &g_stats
.answers0_1
);
812 addGetStat("answers1-10", &g_stats
.answers1_10
);
813 addGetStat("answers10-100", &g_stats
.answers10_100
);
814 addGetStat("answers100-1000", &g_stats
.answers100_1000
);
815 addGetStat("answers-slow", &g_stats
.answersSlow
);
817 addGetStat("auth4-answers0-1", &g_stats
.auth4Answers0_1
);
818 addGetStat("auth4-answers1-10", &g_stats
.auth4Answers1_10
);
819 addGetStat("auth4-answers10-100", &g_stats
.auth4Answers10_100
);
820 addGetStat("auth4-answers100-1000", &g_stats
.auth4Answers100_1000
);
821 addGetStat("auth4-answers-slow", &g_stats
.auth4AnswersSlow
);
823 addGetStat("auth6-answers0-1", &g_stats
.auth6Answers0_1
);
824 addGetStat("auth6-answers1-10", &g_stats
.auth6Answers1_10
);
825 addGetStat("auth6-answers10-100", &g_stats
.auth6Answers10_100
);
826 addGetStat("auth6-answers100-1000", &g_stats
.auth6Answers100_1000
);
827 addGetStat("auth6-answers-slow", &g_stats
.auth6AnswersSlow
);
830 addGetStat("qa-latency", doGetAvgLatencyUsec
);
831 addGetStat("unexpected-packets", &g_stats
.unexpectedCount
);
832 addGetStat("case-mismatches", &g_stats
.caseMismatchCount
);
833 addGetStat("spoof-prevents", &g_stats
.spoofCount
);
835 addGetStat("nsset-invalidations", &g_stats
.nsSetInvalidations
);
837 addGetStat("resource-limits", &g_stats
.resourceLimits
);
838 addGetStat("over-capacity-drops", &g_stats
.overCapacityDrops
);
839 addGetStat("policy-drops", &g_stats
.policyDrops
);
840 addGetStat("no-packet-error", &g_stats
.noPacketError
);
841 addGetStat("dlg-only-drops", &SyncRes::s_nodelegated
);
842 addGetStat("ignored-packets", &g_stats
.ignoredCount
);
843 addGetStat("max-mthread-stack", &g_stats
.maxMThreadStackUsage
);
845 addGetStat("negcache-entries", boost::bind(getNegCacheSize
));
846 addGetStat("throttle-entries", boost::bind(getThrottleSize
));
848 addGetStat("nsspeeds-entries", boost::bind(getNsSpeedsSize
));
849 addGetStat("failed-host-entries", boost::bind(getFailedHostsSize
));
851 addGetStat("concurrent-queries", boost::bind(getConcurrentQueries
));
852 addGetStat("security-status", &g_security_status
);
853 addGetStat("outgoing-timeouts", &SyncRes::s_outgoingtimeouts
);
854 addGetStat("outgoing4-timeouts", &SyncRes::s_outgoing4timeouts
);
855 addGetStat("outgoing6-timeouts", &SyncRes::s_outgoing6timeouts
);
856 addGetStat("tcp-outqueries", &SyncRes::s_tcpoutqueries
);
857 addGetStat("all-outqueries", &SyncRes::s_outqueries
);
858 addGetStat("ipv6-outqueries", &g_stats
.ipv6queries
);
859 addGetStat("throttled-outqueries", &SyncRes::s_throttledqueries
);
860 addGetStat("dont-outqueries", &SyncRes::s_dontqueries
);
861 addGetStat("throttled-out", &SyncRes::s_throttledqueries
);
862 addGetStat("unreachables", &SyncRes::s_unreachables
);
863 addGetStat("ecs-queries", &SyncRes::s_ecsqueries
);
864 addGetStat("ecs-responses", &SyncRes::s_ecsresponses
);
865 addGetStat("chain-resends", &g_stats
.chainResends
);
866 addGetStat("tcp-clients", boost::bind(TCPConnection::getCurrentConnections
));
869 addGetStat("udp-recvbuf-errors", boost::bind(udpErrorStats
, "udp-recvbuf-errors"));
870 addGetStat("udp-sndbuf-errors", boost::bind(udpErrorStats
, "udp-sndbuf-errors"));
871 addGetStat("udp-noport-errors", boost::bind(udpErrorStats
, "udp-noport-errors"));
872 addGetStat("udp-in-errors", boost::bind(udpErrorStats
, "udp-in-errors"));
875 addGetStat("edns-ping-matches", &g_stats
.ednsPingMatches
);
876 addGetStat("edns-ping-mismatches", &g_stats
.ednsPingMismatches
);
877 addGetStat("dnssec-queries", &g_stats
.dnssecQueries
);
879 addGetStat("noping-outqueries", &g_stats
.noPingOutQueries
);
880 addGetStat("noedns-outqueries", &g_stats
.noEdnsOutQueries
);
882 addGetStat("uptime", calculateUptime
);
883 addGetStat("real-memory-usage", boost::bind(getRealMemoryUsage
, string()));
884 addGetStat("fd-usage", boost::bind(getOpenFileDescriptors
, string()));
886 // addGetStat("query-rate", getQueryRate);
887 addGetStat("user-msec", getUserTimeMsec
);
888 addGetStat("sys-msec", getSysTimeMsec
);
891 addGetStat("memory-allocs", boost::bind(&MallocTracer::getAllocs
, g_mtracer
, string()));
892 addGetStat("memory-alloc-flux", boost::bind(&MallocTracer::getAllocFlux
, g_mtracer
, string()));
893 addGetStat("memory-allocated", boost::bind(&MallocTracer::getTotAllocated
, g_mtracer
, string()));
896 addGetStat("dnssec-validations", &g_stats
.dnssecValidations
);
897 addGetStat("dnssec-result-insecure", &g_stats
.dnssecResults
[Insecure
]);
898 addGetStat("dnssec-result-secure", &g_stats
.dnssecResults
[Secure
]);
899 addGetStat("dnssec-result-bogus", &g_stats
.dnssecResults
[Bogus
]);
900 addGetStat("dnssec-result-indeterminate", &g_stats
.dnssecResults
[Indeterminate
]);
901 addGetStat("dnssec-result-nta", &g_stats
.dnssecResults
[NTA
]);
903 addGetStat("policy-result-noaction", &g_stats
.policyResults
[DNSFilterEngine::PolicyKind::NoAction
]);
904 addGetStat("policy-result-drop", &g_stats
.policyResults
[DNSFilterEngine::PolicyKind::Drop
]);
905 addGetStat("policy-result-nxdomain", &g_stats
.policyResults
[DNSFilterEngine::PolicyKind::NXDOMAIN
]);
906 addGetStat("policy-result-nodata", &g_stats
.policyResults
[DNSFilterEngine::PolicyKind::NODATA
]);
907 addGetStat("policy-result-truncate", &g_stats
.policyResults
[DNSFilterEngine::PolicyKind::Truncate
]);
908 addGetStat("policy-result-custom", &g_stats
.policyResults
[DNSFilterEngine::PolicyKind::Custom
]);
911 static void doExitGeneric(bool nicely
)
913 L
<<Logger::Error
<<"Exiting on user request"<<endl
;
914 extern RecursorControlChannel s_rcc
;
915 s_rcc
.~RecursorControlChannel();
917 extern string s_pidfname
;
918 if(!s_pidfname
.empty())
919 unlink(s_pidfname
.c_str()); // we can at least try..
928 doExitGeneric(false);
931 static void doExitNicely()
936 vector
<pair
<DNSName
, uint16_t> >* pleaseGetQueryRing()
938 typedef pair
<DNSName
,uint16_t> query_t
;
939 vector
<query_t
>* ret
= new vector
<query_t
>();
942 ret
->reserve(t_queryring
->size());
944 for(const query_t
& q
: *t_queryring
) {
949 vector
<pair
<DNSName
,uint16_t> >* pleaseGetServfailQueryRing()
951 typedef pair
<DNSName
,uint16_t> query_t
;
952 vector
<query_t
>* ret
= new vector
<query_t
>();
953 if(!t_servfailqueryring
)
955 ret
->reserve(t_servfailqueryring
->size());
956 for(const query_t
& q
: *t_servfailqueryring
) {
964 typedef boost::function
<vector
<ComboAddress
>*()> pleaseremotefunc_t
;
965 typedef boost::function
<vector
<pair
<DNSName
,uint16_t> >*()> pleasequeryfunc_t
;
967 vector
<ComboAddress
>* pleaseGetRemotes()
969 vector
<ComboAddress
>* ret
= new vector
<ComboAddress
>();
973 ret
->reserve(t_remotes
->size());
974 for(const ComboAddress
& ca
: *t_remotes
) {
980 vector
<ComboAddress
>* pleaseGetServfailRemotes()
982 vector
<ComboAddress
>* ret
= new vector
<ComboAddress
>();
983 if(!t_servfailremotes
)
985 ret
->reserve(t_servfailremotes
->size());
986 for(const ComboAddress
& ca
: *t_servfailremotes
) {
992 vector
<ComboAddress
>* pleaseGetLargeAnswerRemotes()
994 vector
<ComboAddress
>* ret
= new vector
<ComboAddress
>();
995 if(!t_largeanswerremotes
)
997 ret
->reserve(t_largeanswerremotes
->size());
998 for(const ComboAddress
& ca
: *t_largeanswerremotes
) {
1004 string
doGenericTopRemotes(pleaseremotefunc_t func
)
1006 typedef map
<ComboAddress
, int, ComboAddress::addressOnlyLessThan
> counts_t
;
1009 vector
<ComboAddress
> remotes
=broadcastAccFunction
<vector
<ComboAddress
> >(func
);
1011 unsigned int total
=0;
1012 for(const ComboAddress
& ca
: remotes
) {
1017 typedef std::multimap
<int, ComboAddress
> rcounts_t
;
1020 for(counts_t::const_iterator i
=counts
.begin(); i
!= counts
.end(); ++i
)
1021 rcounts
.insert(make_pair(-i
->second
, i
->first
));
1024 ret
<<"Over last "<<total
<<" entries:\n";
1025 format
fmt("%.02f%%\t%s\n");
1026 int limit
=0, accounted
=0;
1028 for(rcounts_t::const_iterator i
=rcounts
.begin(); i
!= rcounts
.end() && limit
< 20; ++i
, ++limit
) {
1029 ret
<< fmt
% (-100.0*i
->first
/total
) % i
->second
.toString();
1030 accounted
+= -i
->first
;
1032 ret
<< '\n' << fmt
% (100.0*(total
-accounted
)/total
) % "rest";
1038 typedef vector
<vector
<string
> > pubs_t
;
1042 void sortPublicSuffixList()
1044 for(const char** p
=g_pubsuffix
; *p
; ++p
) {
1045 string low
=toLower(*p
);
1047 vector
<string
> parts
;
1048 stringtok(parts
, low
, ".");
1049 reverse(parts
.begin(), parts
.end());
1050 g_pubs
.push_back(parts
);
1052 sort(g_pubs
.begin(), g_pubs
.end());
1055 // XXX DNSName Pain - this function should benefit from native DNSName methods
1056 DNSName
getRegisteredName(const DNSName
& dom
)
1058 auto parts
=dom
.getRawLabels();
1061 reverse(parts
.begin(), parts
.end());
1062 for(string
& str
: parts
) { str
=toLower(str
); };
1066 while(!parts
.empty()) {
1067 if(parts
.size()==1 || binary_search(g_pubs
.begin(), g_pubs
.end(), parts
)) {
1073 for(auto p
= parts
.crbegin(); p
!= parts
.crend(); ++p
) {
1076 return DNSName(ret
);
1079 last
=parts
[parts
.size()-1];
1080 parts
.resize(parts
.size()-1);
1082 return DNSName("??");
1085 static DNSName
nopFilter(const DNSName
& name
)
1090 string
doGenericTopQueries(pleasequeryfunc_t func
, boost::function
<DNSName(const DNSName
&)> filter
=nopFilter
)
1092 typedef pair
<DNSName
,uint16_t> query_t
;
1093 typedef map
<query_t
, int> counts_t
;
1095 vector
<query_t
> queries
=broadcastAccFunction
<vector
<query_t
> >(func
);
1097 unsigned int total
=0;
1098 for(const query_t
& q
: queries
) {
1100 counts
[make_pair(filter(q
.first
),q
.second
)]++;
1103 typedef std::multimap
<int, query_t
> rcounts_t
;
1106 for(counts_t::const_iterator i
=counts
.begin(); i
!= counts
.end(); ++i
)
1107 rcounts
.insert(make_pair(-i
->second
, i
->first
));
1110 ret
<<"Over last "<<total
<<" entries:\n";
1111 format
fmt("%.02f%%\t%s\n");
1112 int limit
=0, accounted
=0;
1114 for(rcounts_t::const_iterator i
=rcounts
.begin(); i
!= rcounts
.end() && limit
< 20; ++i
, ++limit
) {
1115 ret
<< fmt
% (-100.0*i
->first
/total
) % (i
->second
.first
.toString()+"|"+DNSRecordContent::NumberToType(i
->second
.second
));
1116 accounted
+= -i
->first
;
1118 ret
<< '\n' << fmt
% (100.0*(total
-accounted
)/total
) % "rest";
1125 static string
* nopFunction()
1127 return new string("pong\n");
1130 string
RecursorControlParser::getAnswer(const string
& question
, RecursorControlParser::func_t
** command
)
1133 vector
<string
> words
;
1134 stringtok(words
, question
);
1137 return "invalid command\n";
1139 string cmd
=toLower(words
[0]);
1140 vector
<string
>::const_iterator begin
=words
.begin()+1, end
=words
.end();
1142 // should probably have a smart dispatcher here, like auth has
1145 "add-nta DOMAIN [REASON] add a Negative Trust Anchor for DOMAIN with the comment REASON\n"
1146 "add-ta DOMAIN DSRECORD add a Trust Anchor for DOMAIN with data DSRECORD\n"
1147 "current-queries show currently active queries\n"
1148 "clear-nta [DOMAIN]... Clear the Negative Trust Anchor for DOMAINs, if no DOMAIN is specified, remove all\n"
1149 "clear-ta [DOMAIN]... Clear the Trust Anchor for DOMAINs\n"
1150 "dump-cache <filename> dump cache contents to the named file\n"
1151 "dump-edns [status] <filename> dump EDNS status to the named file\n"
1152 "dump-nsspeeds <filename> dump nsspeeds statistics to the named file\n"
1153 "get [key1] [key2] .. get specific statistics\n"
1154 "get-all get all statistics\n"
1155 "get-ntas get all configured Negative Trust Anchors\n"
1156 "get-tas get all configured Trust Anchors\n"
1157 "get-parameter [key1] [key2] .. get configuration parameters\n"
1158 "get-qtypelist get QType statistics\n"
1159 " notice: queries from cache aren't being counted yet\n"
1160 "help get this list\n"
1161 "ping check that all threads are alive\n"
1162 "quit stop the recursor daemon\n"
1163 "quit-nicely stop the recursor daemon nicely\n"
1164 "reload-acls reload ACLS\n"
1165 "reload-lua-script [filename] (re)load Lua script\n"
1166 "reload-lua-config [filename] (re)load Lua configuration file\n"
1167 "reload-zones reload all auth and forward zones\n"
1168 "set-minimum-ttl value set minimum-ttl-override\n"
1169 "set-carbon-server set a carbon server for telemetry\n"
1170 "set-dnssec-log-bogus SETTING enable (SETTING=yes) or disable (SETTING=no) logging of DNSSEC validation failures\n"
1171 "trace-regex [regex] emit resolution trace for matching queries (empty regex to clear trace)\n"
1172 "top-largeanswer-remotes show top remotes receiving large answers\n"
1173 "top-queries show top queries\n"
1174 "top-pub-queries show top queries grouped by public suffix list\n"
1175 "top-remotes show top remotes\n"
1176 "top-servfail-queries show top queries receiving servfail answers\n"
1177 "top-pub-servfail-queries show top queries receiving servfail answers grouped by public suffix list\n"
1178 "top-servfail-remotes show top remotes receiving servfail answers\n"
1179 "unload-lua-script unload Lua script\n"
1180 "version return Recursor version number\n"
1181 "wipe-cache domain0 [domain1] .. wipe domain data from cache\n";
1184 return getAllStats();
1187 return doGet(begin
, end
);
1189 if(cmd
=="get-parameter")
1190 return doGetParameter(begin
, end
);
1197 if(cmd
=="version") {
1198 return getPDNSVersion()+"\n";
1201 if(cmd
=="quit-nicely") {
1202 *command
=&doExitNicely
;
1203 return "bye nicely\n";
1206 if(cmd
=="dump-cache")
1207 return doDumpCache(begin
, end
);
1209 if(cmd
=="dump-ednsstatus" || cmd
=="dump-edns")
1210 return doDumpEDNSStatus(begin
, end
);
1212 if(cmd
=="dump-nsspeeds")
1213 return doDumpNSSpeeds(begin
, end
);
1215 if(cmd
=="wipe-cache" || cmd
=="flushname")
1216 return doWipeCache(begin
, end
);
1218 if(cmd
=="reload-lua-script")
1219 return doQueueReloadLuaScript(begin
, end
);
1221 if(cmd
=="reload-lua-config") {
1223 ::arg().set("lua-config-file") = *begin
;
1226 loadRecursorLuaConfig(::arg()["lua-config-file"], false);
1227 L
<<Logger::Warning
<<"Reloaded Lua configuration file '"<<::arg()["lua-config-file"]<<"', requested via control channel"<<endl
;
1228 return "Reloaded Lua configuration file '"+::arg()["lua-config-file"]+"'\n";
1230 catch(std::exception
& e
) {
1231 return "Unable to load Lua script from '"+::arg()["lua-config-file"]+"': "+e
.what()+"\n";
1233 catch(const PDNSException
& e
) {
1234 return "Unable to load Lua script from '"+::arg()["lua-config-file"]+"': "+e
.reason
+"\n";
1238 if(cmd
=="set-carbon-server")
1239 return doSetCarbonServer(begin
, end
);
1241 if(cmd
=="trace-regex")
1242 return doTraceRegex(begin
, end
);
1244 if(cmd
=="unload-lua-script") {
1245 vector
<string
> empty
;
1246 empty
.push_back(string());
1247 return doQueueReloadLuaScript(empty
.begin(), empty
.end());
1250 if(cmd
=="reload-acls") {
1251 if(!::arg()["chroot"].empty()) {
1252 L
<<Logger::Error
<<"Unable to reload ACL when chroot()'ed, requested via control channel"<<endl
;
1253 return "Unable to reload ACL when chroot()'ed, please restart\n";
1259 catch(std::exception
& e
)
1261 L
<<Logger::Error
<<"Reloading ACLs failed (Exception: "<<e
.what()<<")"<<endl
;
1262 return e
.what() + string("\n");
1264 catch(PDNSException
& ae
)
1266 L
<<Logger::Error
<<"Reloading ACLs failed (PDNSException: "<<ae
.reason
<<")"<<endl
;
1267 return ae
.reason
+ string("\n");
1273 if(cmd
=="top-remotes")
1274 return doGenericTopRemotes(pleaseGetRemotes
);
1276 if(cmd
=="top-queries")
1277 return doGenericTopQueries(pleaseGetQueryRing
);
1279 if(cmd
=="top-pub-queries")
1280 return doGenericTopQueries(pleaseGetQueryRing
, getRegisteredName
);
1282 if(cmd
=="top-servfail-queries")
1283 return doGenericTopQueries(pleaseGetServfailQueryRing
);
1285 if(cmd
=="top-pub-servfail-queries")
1286 return doGenericTopQueries(pleaseGetServfailQueryRing
, getRegisteredName
);
1289 if(cmd
=="top-servfail-remotes")
1290 return doGenericTopRemotes(pleaseGetServfailRemotes
);
1292 if(cmd
=="top-largeanswer-remotes")
1293 return doGenericTopRemotes(pleaseGetLargeAnswerRemotes
);
1296 if(cmd
=="current-queries")
1297 return doCurrentQueries();
1300 return broadcastAccFunction
<string
>(nopFunction
);
1303 if(cmd
=="reload-zones") {
1304 if(!::arg()["chroot"].empty()) {
1305 L
<<Logger::Error
<<"Unable to reload zones and forwards when chroot()'ed, requested via control channel"<<endl
;
1306 return "Unable to reload zones and forwards when chroot()'ed, please restart\n";
1308 return reloadAuthAndForwards();
1311 if(cmd
=="set-minimum-ttl") {
1312 return setMinimumTTL(begin
, end
);
1315 if(cmd
=="get-qtypelist") {
1316 return g_rs
.getQTypeReport();
1319 if(cmd
=="add-nta") {
1320 return doAddNTA(begin
, end
);
1323 if(cmd
=="clear-nta") {
1324 return doClearNTA(begin
, end
);
1327 if(cmd
=="get-ntas") {
1332 return doAddTA(begin
, end
);
1335 if(cmd
=="clear-ta") {
1336 return doClearTA(begin
, end
);
1339 if(cmd
=="get-tas") {
1343 if (cmd
=="set-dnssec-log-bogus")
1344 return doSetDnssecLogBogus(begin
, end
);
1346 return "Unknown command '"+cmd
+"', try 'help'\n";