]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/rec_channel_rec.cc
Merge pull request #8777 from omoerbeek/rec-wip-qname-vs-ds
[thirdparty/pdns.git] / pdns / rec_channel_rec.cc
CommitLineData
870a0fe4
AT
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
705f31ae 4#include "utility.hh"
1d5b3ce6 5#include "rec_channel.hh"
1d5b3ce6
BH
6#include <boost/bind.hpp>
7#include <vector>
8f7473d7 8#ifdef MALLOC_TRACE
9#include "malloctrace.hh"
10#endif
1d5b3ce6
BH
11#include "misc.hh"
12#include "recursor_cache.hh"
13#include "syncres.hh"
39ce10b2 14#include "negcache.hh"
1d5b3ce6
BH
15#include <boost/function.hpp>
16#include <boost/optional.hpp>
c9e9e5e0 17#include <boost/tuple/tuple.hpp>
a9af3782 18#include <boost/format.hpp>
f6ef9d7b 19#include <boost/algorithm/string.hpp>
fa8fd4d2 20
77b9f5ff 21#include "version.hh"
748eff9f
BH
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <fcntl.h>
aaacf7f2 25#include "logger.hh"
d2392145 26#include "dnsparser.hh"
f6ef9d7b 27#include "arguments.hh"
a254e9b6 28#include <sys/resource.h>
705f31ae 29#include <sys/time.h>
5f0a7007 30#include "lock.hh"
79332bff 31#include "responsestats.hh"
a38ab818 32#include "rec-lua-conf.hh"
77b9f5ff 33
c87e1876 34#include "validate-recursor.hh"
7a25883a 35#include "filterpo.hh"
c87e1876 36
d67620e4 37#include "secpoll-recursor.hh"
92011b8f 38#include "pubsuffix.hh"
10f4eea8 39#include "namespaces.hh"
77a6fa66 40pthread_mutex_t g_carbon_config_lock=PTHREAD_MUTEX_INITIALIZER;
76473b92 41
e9a628a2 42static map<string, const uint32_t*> d_get32bitpointers;
e9a628a2
RG
43static map<string, const std::atomic<uint64_t>*> d_getatomics;
44static map<string, function< uint64_t() > > d_get64bitmembers;
45static pthread_mutex_t d_dynmetricslock = PTHREAD_MUTEX_INITIALIZER;
46static map<string, std::atomic<unsigned long>* > d_dynmetrics;
47
72259676 48static std::map<StatComponent, std::set<std::string>> s_blacklistedStats;
c9783016 49
72259676 50bool isStatBlacklisted(StatComponent component, const string& name)
5e08df89 51{
72259676 52 return s_blacklistedStats[component].count(name) != 0;
c9783016
RG
53}
54
72259676 55void blacklistStat(StatComponent component, const string& name)
c9783016 56{
72259676
RG
57 s_blacklistedStats[component].insert(name);
58}
59
60void blacklistStats(StatComponent component, const string& stats)
61{
62 std::vector<std::string> blacklistedStats;
63 stringtok(blacklistedStats, stats, ", ");
64 auto& map = s_blacklistedStats[component];
65 for (const auto &st : blacklistedStats) {
66 map.insert(st);
67 }
5e08df89
RG
68}
69
e9a628a2 70static void addGetStat(const string& name, const uint32_t* place)
1d5b3ce6
BH
71{
72 d_get32bitpointers[name]=place;
73}
51e63251 74
e9a628a2 75static void addGetStat(const string& name, const std::atomic<uint64_t>* place)
aebb81e4 76{
77 d_getatomics[name]=place;
78}
79
e9a628a2 80static void addGetStat(const string& name, function<uint64_t ()> f )
1d5b3ce6 81{
51e63251 82 d_get64bitmembers[name]=f;
1d5b3ce6
BH
83}
84
9f89a5f1 85std::atomic<unsigned long>* getDynMetric(const std::string& str)
86{
87 Lock l(&d_dynmetricslock);
88 auto f = d_dynmetrics.find(str);
89 if(f != d_dynmetrics.end())
90 return f->second;
91
92 auto ret = new std::atomic<unsigned long>();
93 d_dynmetrics[str]= ret;
94 return ret;
95}
96
b0b37121 97static optional<uint64_t> get(const string& name)
1d5b3ce6
BH
98{
99 optional<uint64_t> ret;
100
101 if(d_get32bitpointers.count(name))
102 return *d_get32bitpointers.find(name)->second;
aebb81e4 103 if(d_getatomics.count(name))
104 return d_getatomics.find(name)->second->load();
51e63251 105 if(d_get64bitmembers.count(name))
106 return d_get64bitmembers.find(name)->second();
1d5b3ce6 107
9f89a5f1 108 Lock l(&d_dynmetricslock);
109 auto f =rplookup(d_dynmetrics, name);
110 if(f)
111 return (*f)->load();
112
1d5b3ce6
BH
113 return ret;
114}
115
d705aad9
RG
116optional<uint64_t> getStatByName(const std::string& name)
117{
118 return get(name);
119}
120
72259676 121map<string,string> getAllStatsMap(StatComponent component)
aadbe056 122{
97f42439 123 map<string,string> ret;
72259676
RG
124 const auto& blacklistMap = s_blacklistedStats.at(component);
125
cbd05f37 126 for(const auto& the32bits : d_get32bitpointers) {
72259676 127 if (blacklistMap.count(the32bits.first) == 0) {
5e08df89
RG
128 ret.insert(make_pair(the32bits.first, std::to_string(*the32bits.second)));
129 }
aadbe056 130 }
aebb81e4 131 for(const auto& atomic : d_getatomics) {
72259676 132 if (blacklistMap.count(atomic.first) == 0) {
5e08df89
RG
133 ret.insert(make_pair(atomic.first, std::to_string(atomic.second->load())));
134 }
aebb81e4 135 }
136
72259676
RG
137 for(const auto& the64bitmembers : d_get64bitmembers) {
138 if (blacklistMap.count(the64bitmembers.first) == 0) {
5e08df89
RG
139 ret.insert(make_pair(the64bitmembers.first, std::to_string(the64bitmembers.second())));
140 }
97f42439 141 }
5e08df89 142
72259676
RG
143 {
144 Lock l(&d_dynmetricslock);
145 for(const auto& a : d_dynmetrics) {
146 if (blacklistMap.count(a.first) == 0) {
147 ret.insert({a.first, std::to_string(*a.second)});
148 }
149 }
150 }
151
97f42439
BH
152 return ret;
153}
154
72259676 155static string getAllStats()
97f42439
BH
156{
157 typedef map<string, string> varmap_t;
72259676 158 varmap_t varmap = getAllStatsMap(StatComponent::RecControl);
97f42439 159 string ret;
ff05fd12 160 for(varmap_t::value_type& tup : varmap) {
97f42439 161 ret += tup.first + "\t" + tup.second +"\n";
aadbe056
BH
162 }
163 return ret;
164}
1d5b3ce6
BH
165
166template<typename T>
ea7bc6d8 167static string doGet(T begin, T end)
1d5b3ce6
BH
168{
169 string ret;
170
171 for(T i=begin; i != end; ++i) {
172 optional<uint64_t> num=get(*i);
173 if(num)
335da0ba 174 ret+=std::to_string(*num)+"\n";
1d5b3ce6
BH
175 else
176 ret+="UNKNOWN\n";
177 }
178 return ret;
179}
180
f6ef9d7b 181template<typename T>
ea7bc6d8 182string static doGetParameter(T begin, T end)
f6ef9d7b
BH
183{
184 string ret;
185 string parm;
eb4e3090 186 using boost::replace_all;
f6ef9d7b
BH
187 for(T i=begin; i != end; ++i) {
188 if(::arg().parmIsset(*i)) {
189 parm=::arg()[*i];
190 replace_all(parm, "\\", "\\\\");
191 replace_all(parm, "\"", "\\\"");
192 replace_all(parm, "\n", "\\n");
193 ret += *i +"=\""+ parm +"\"\n";
194 }
195 else
196 ret += *i +" not known\n";
197 }
198 return ret;
199}
200
201
39ce10b2 202static uint64_t dumpNegCache(NegCache& negcache, int fd)
fd2d69bb 203{
5e1f23ca 204 auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fdopen(dup(fd), "w"), fclose);
fd2d69bb
BH
205 if(!fp) { // dup probably failed
206 return 0;
207 }
39ce10b2 208 uint64_t ret;
5e1f23ca
RG
209 fprintf(fp.get(), "; negcache dump from thread follows\n;\n");
210 ret = negcache.dumpToFile(fp.get());
39ce10b2 211 return ret;
fd2d69bb
BH
212}
213
d7948528
BH
214static uint64_t* pleaseDump(int fd)
215{
a712cb56 216 return new uint64_t(t_RC->doDump(fd) + dumpNegCache(SyncRes::t_sstorage.negcache, fd) + t_packetCache->doDump(fd));
d7948528
BH
217}
218
addde5c1 219static uint64_t* pleaseDumpEDNSMap(int fd)
220{
221 return new uint64_t(SyncRes::doEDNSDump(fd));
222}
223
a82ce718
PD
224static uint64_t* pleaseDumpNSSpeeds(int fd)
225{
9065eb05 226 return new uint64_t(SyncRes::doDumpNSSpeeds(fd));
a82ce718
PD
227}
228
c1e20fba 229static uint64_t* pleaseDumpThrottleMap(int fd)
230{
231 return new uint64_t(SyncRes::doDumpThrottleMap(fd));
232}
233
60e5208a
OM
234static uint64_t* pleaseDumpFailedServers(int fd)
235{
236 return new uint64_t(SyncRes::doDumpFailedServers(fd));
237}
238
a82ce718 239template<typename T>
ea7bc6d8 240static string doDumpNSSpeeds(T begin, T end)
a82ce718
PD
241{
242 T i=begin;
243 string fname;
244
245 if(i!=end)
246 fname=*i;
247
248 int fd=open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660);
249 if(fd < 0)
a2a81d42 250 return "Error opening dump file for writing: "+stringerror()+"\n";
a82ce718
PD
251 uint64_t total = 0;
252 try {
253 total = broadcastAccFunction<uint64_t>(boost::bind(pleaseDumpNSSpeeds, fd));
254 }
a2d65f83 255 catch(std::exception& e)
256 {
257 close(fd);
258 return "error dumping NS speeds: "+string(e.what())+"\n";
259 }
260 catch(PDNSException& e)
261 {
262 close(fd);
263 return "error dumping NS speeds: "+e.reason+"\n";
264 }
a82ce718
PD
265
266 close(fd);
335da0ba 267 return "dumped "+std::to_string(total)+" records\n";
a82ce718
PD
268}
269
748eff9f 270template<typename T>
ea7bc6d8 271static string doDumpCache(T begin, T end)
748eff9f
BH
272{
273 T i=begin;
274 string fname;
275
276 if(i!=end)
277 fname=*i;
278
b80ea858 279 int fd=open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660);
748eff9f 280 if(fd < 0)
a2a81d42 281 return "Error opening dump file for writing: "+stringerror()+"\n";
d7948528
BH
282 uint64_t total = 0;
283 try {
284 total = broadcastAccFunction<uint64_t>(boost::bind(pleaseDump, fd));
285 }
286 catch(...){}
287
288 close(fd);
335da0ba 289 return "dumped "+std::to_string(total)+" records\n";
748eff9f
BH
290}
291
ff1872cf 292template<typename T>
ea7bc6d8 293static string doDumpEDNSStatus(T begin, T end)
ff1872cf
BH
294{
295 T i=begin;
296 string fname;
297
298 if(i!=end)
299 fname=*i;
300
301 int fd=open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660);
302 if(fd < 0)
a2a81d42 303 return "Error opening dump file for writing: "+stringerror()+"\n";
addde5c1 304 uint64_t total = 0;
305 try {
306 total = broadcastAccFunction<uint64_t>(boost::bind(pleaseDumpEDNSMap, fd));
307 }
308 catch(...){}
ff1872cf 309
addde5c1 310 close(fd);
311 return "dumped "+std::to_string(total)+" records\n";
ff1872cf
BH
312}
313
6791663c 314template<typename T>
ea7bc6d8 315static string doDumpRPZ(T begin, T end)
6791663c
RG
316{
317 T i=begin;
318
319 if (i == end) {
320 return "No zone name specified\n";
321 }
322 string zoneName = *i;
323 i++;
324
325 if (i == end) {
326 return "No file name specified\n";
327 }
328 string fname = *i;
329
330 auto luaconf = g_luaconfs.getLocal();
331 const auto zone = luaconf->dfe.getZone(zoneName);
332 if (!zone) {
333 return "No RPZ zone named "+zoneName+"\n";
334 }
335
336 int fd = open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660);
337
338 if(fd < 0) {
a2a81d42 339 return "Error opening dump file for writing: "+stringerror()+"\n";
6791663c
RG
340 }
341
5e1f23ca 342 auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fdopen(fd, "w"), fclose);
6791663c
RG
343 if (!fp) {
344 close(fd);
a2a81d42 345 return "Error converting file descriptor: "+stringerror()+"\n";
6791663c
RG
346 }
347
5e1f23ca 348 zone->dump(fp.get());
6791663c
RG
349
350 return "done\n";
351}
352
c1e20fba 353template<typename T>
ea7bc6d8 354static string doDumpThrottleMap(T begin, T end)
c1e20fba 355{
356 T i=begin;
357 string fname;
358
359 if(i!=end)
360 fname=*i;
361
362 int fd=open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660);
363 if(fd < 0)
a2a81d42 364 return "Error opening dump file for writing: "+stringerror()+"\n";
c1e20fba 365 uint64_t total = 0;
366 try {
367 total = broadcastAccFunction<uint64_t>(boost::bind(pleaseDumpThrottleMap, fd));
368 }
369 catch(...){}
370
371 close(fd);
372 return "dumped "+std::to_string(total)+" records\n";
373}
374
60e5208a
OM
375template<typename T>
376static string doDumpFailedServers(T begin, T end)
377{
378 T i=begin;
379 string fname;
380
381 if(i!=end)
382 fname=*i;
383
384 int fd=open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660);
385 if(fd < 0)
386 return "Error opening dump file for writing: "+stringerror()+"\n";
387 uint64_t total = 0;
388 try {
389 total = broadcastAccFunction<uint64_t>(boost::bind(pleaseDumpFailedServers, fd));
390 }
391 catch(...){}
392
393 close(fd);
394 return "dumped "+std::to_string(total)+" records\n";
395}
396
2087df40 397uint64_t* pleaseWipeCache(const DNSName& canon, bool subtree, uint16_t qtype)
3427fa8a 398{
2087df40 399 return new uint64_t(t_RC->doWipeCache(canon, subtree, qtype));
3427fa8a
BH
400}
401
2087df40 402uint64_t* pleaseWipePacketCache(const DNSName& canon, bool subtree, uint16_t qtype)
65a60c2c 403{
2087df40 404 return new uint64_t(t_packetCache->doWipePacketCache(canon, qtype, subtree));
65a60c2c 405}
3427fa8a 406
65a60c2c 407
408uint64_t* pleaseWipeAndCountNegCache(const DNSName& canon, bool subtree)
3427fa8a 409{
a712cb56 410 uint64_t ret = SyncRes::wipeNegCache(canon, subtree);
39ce10b2 411 return new uint64_t(ret);
3427fa8a
BH
412}
413
39ce10b2 414
748eff9f 415template<typename T>
2087df40 416static string doWipeCache(T begin, T end, uint16_t qtype)
748eff9f 417{
74e5a8d4 418 vector<pair<DNSName, bool> > toWipe;
400ca6db 419 for(T i=begin; i != end; ++i) {
65a60c2c 420 DNSName canon;
421 bool subtree=false;
74e5a8d4
PL
422
423 try {
424 if(boost::ends_with(*i, "$")) {
425 canon=DNSName(i->substr(0, i->size()-1));
426 subtree=true;
427 } else {
428 canon=DNSName(*i);
429 }
430 } catch (std::exception &e) {
431 return "Error: " + std::string(e.what()) + ", nothing wiped\n";
65a60c2c 432 }
74e5a8d4
PL
433 toWipe.push_back({canon, subtree});
434 }
435
436 int count=0, pcount=0, countNeg=0;
437 for (auto wipe : toWipe) {
2087df40
OM
438 count+= broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, wipe.first, wipe.second, qtype));
439 pcount+= broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, wipe.first, wipe.second, qtype));
74e5a8d4 440 countNeg+=broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, wipe.first, wipe.second));
400ca6db 441 }
748eff9f 442
65a60c2c 443 return "wiped "+std::to_string(count)+" records, "+std::to_string(countNeg)+" negative records, "+std::to_string(pcount)+" packets\n";
748eff9f
BH
444}
445
77a6fa66 446template<typename T>
ea7bc6d8 447static string doSetCarbonServer(T begin, T end)
77a6fa66 448{
449 Lock l(&g_carbon_config_lock);
450 if(begin==end) {
451 ::arg().set("carbon-server").clear();
452 return "cleared carbon-server setting\n";
453 }
454 string ret;
455 ::arg().set("carbon-server")=*begin;
456 ret="set carbon-server to '"+::arg()["carbon-server"]+"'\n";
03408d08 457 ++begin;
77a6fa66 458 if(begin != end) {
77a6fa66 459 ::arg().set("carbon-ourname")=*begin;
460 ret+="set carbon-ourname to '"+*begin+"'\n";
874e379c
G
461 } else {
462 return ret;
463 }
464 ++begin;
465 if(begin != end) {
466 ::arg().set("carbon-namespace")=*begin;
467 ret+="set carbon-namespace to '"+*begin+"'\n";
468 } else {
469 return ret;
470 }
471 ++begin;
472 if(begin != end) {
473 ::arg().set("carbon-instance")=*begin;
474 ret+="set carbon-instance to '"+*begin+"'\n";
77a6fa66 475 }
476 return ret;
477}
478
c87e1876 479template<typename T>
ea7bc6d8 480static string doSetDnssecLogBogus(T begin, T end)
c87e1876 481{
4865b6cb
PL
482 if(checkDNSSECDisabled())
483 return "DNSSEC is disabled in the configuration, not changing the Bogus logging setting\n";
484
c87e1876
PL
485 if (begin == end)
486 return "No DNSSEC Bogus logging setting specified\n";
487
488 if (pdns_iequals(*begin, "on") || pdns_iequals(*begin, "yes")) {
489 if (!g_dnssecLogBogus) {
e6a9dde5 490 g_log<<Logger::Warning<<"Enabling DNSSEC Bogus logging, requested via control channel"<<endl;
c87e1876
PL
491 g_dnssecLogBogus = true;
492 return "DNSSEC Bogus logging enabled\n";
493 }
494 return "DNSSEC Bogus logging was already enabled\n";
495 }
496
497 if (pdns_iequals(*begin, "off") || pdns_iequals(*begin, "no")) {
498 if (g_dnssecLogBogus) {
e6a9dde5 499 g_log<<Logger::Warning<<"Disabling DNSSEC Bogus logging, requested via control channel"<<endl;
c87e1876
PL
500 g_dnssecLogBogus = false;
501 return "DNSSEC Bogus logging disabled\n";
502 }
503 return "DNSSEC Bogus logging was already disabled\n";
504 }
505
506 return "Unknown DNSSEC Bogus setting: '" + *begin +"'\n";
507}
508
a38ab818 509template<typename T>
ea7bc6d8 510static string doAddNTA(T begin, T end)
a38ab818 511{
4865b6cb
PL
512 if(checkDNSSECDisabled())
513 return "DNSSEC is disabled in the configuration, not adding a Negative Trust Anchor\n";
514
a38ab818
PL
515 if(begin == end)
516 return "No NTA specified, doing nothing\n";
517
518 DNSName who;
519 try {
520 who = DNSName(*begin);
521 }
522 catch(std::exception &e) {
523 string ret("Can't add Negative Trust Anchor: ");
524 ret += e.what();
525 ret += "\n";
526 return ret;
527 }
528 begin++;
529
530 string why("");
531 while (begin != end) {
532 why += *begin;
533 begin++;
534 if (begin != end)
535 why += " ";
536 }
e6a9dde5 537 g_log<<Logger::Warning<<"Adding Negative Trust Anchor for "<<who<<" with reason '"<<why<<"', requested via control channel"<<endl;
a38ab818
PL
538 g_luaconfs.modify([who, why](LuaConfigItems& lci) {
539 lci.negAnchors[who] = why;
540 });
2087df40
OM
541 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, who, true, 0xffff));
542 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, who, true, 0xffff));
8302d4cb 543 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, who, true));
a38ab818
PL
544 return "Added Negative Trust Anchor for " + who.toLogString() + " with reason '" + why + "'\n";
545}
546
547template<typename T>
ea7bc6d8 548static string doClearNTA(T begin, T end)
a38ab818 549{
4865b6cb
PL
550 if(checkDNSSECDisabled())
551 return "DNSSEC is disabled in the configuration, not removing a Negative Trust Anchor\n";
552
a38ab818
PL
553 if(begin == end)
554 return "No Negative Trust Anchor specified, doing nothing.\n";
555
556 if (begin + 1 == end && *begin == "*"){
e6a9dde5 557 g_log<<Logger::Warning<<"Clearing all Negative Trust Anchors, requested via control channel"<<endl;
a38ab818
PL
558 g_luaconfs.modify([](LuaConfigItems& lci) {
559 lci.negAnchors.clear();
560 });
561 return "Cleared all Negative Trust Anchors.\n";
562 }
563
564 vector<DNSName> toRemove;
565 DNSName who;
566 while (begin != end) {
567 if (*begin == "*")
568 return "Don't mix all Negative Trust Anchor removal with multiple Negative Trust Anchor removal. Nothing removed\n";
569 try {
570 who = DNSName(*begin);
571 }
572 catch(std::exception &e) {
573 string ret("Error: ");
574 ret += e.what();
575 ret += ". No Negative Anchors removed\n";
576 return ret;
577 }
578 toRemove.push_back(who);
579 begin++;
580 }
581
582 string removed("");
583 bool first(true);
dd079764 584 for (auto const &entry : toRemove) {
e6a9dde5 585 g_log<<Logger::Warning<<"Clearing Negative Trust Anchor for "<<entry<<", requested via control channel"<<endl;
dd079764
RG
586 g_luaconfs.modify([entry](LuaConfigItems& lci) {
587 lci.negAnchors.erase(entry);
a38ab818 588 });
2087df40
OM
589 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, entry, true, 0xffff));
590 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, entry, true, 0xffff));
8302d4cb 591 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, entry, true));
a38ab818
PL
592 if (!first) {
593 first = false;
594 removed += ",";
595 }
dd079764 596 removed += " " + entry.toStringRootDot();
a38ab818
PL
597 }
598 return "Removed Negative Trust Anchors for " + removed + "\n";
599}
600
601static string getNTAs()
602{
4865b6cb
PL
603 if(checkDNSSECDisabled())
604 return "DNSSEC is disabled in the configuration\n";
605
a38ab818
PL
606 string ret("Configured Negative Trust Anchors:\n");
607 auto luaconf = g_luaconfs.getLocal();
608 for (auto negAnchor : luaconf->negAnchors)
609 ret += negAnchor.first.toLogString() + "\t" + negAnchor.second + "\n";
610 return ret;
611}
77a6fa66 612
331bcdd5 613template<typename T>
ea7bc6d8 614static string doAddTA(T begin, T end)
331bcdd5 615{
4865b6cb
PL
616 if(checkDNSSECDisabled())
617 return "DNSSEC is disabled in the configuration, not adding a Trust Anchor\n";
618
331bcdd5
PL
619 if(begin == end)
620 return "No TA specified, doing nothing\n";
621
622 DNSName who;
623 try {
624 who = DNSName(*begin);
625 }
626 catch(std::exception &e) {
627 string ret("Can't add Trust Anchor: ");
628 ret += e.what();
629 ret += "\n";
630 return ret;
631 }
632 begin++;
633
634 string what("");
635 while (begin != end) {
636 what += *begin + " ";
637 begin++;
638 }
639
640 try {
e6a9dde5 641 g_log<<Logger::Warning<<"Adding Trust Anchor for "<<who<<" with data '"<<what<<"', requested via control channel";
331bcdd5 642 g_luaconfs.modify([who, what](LuaConfigItems& lci) {
32122aab 643 auto ds=std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(what));
64a4a928 644 lci.dsAnchors[who].insert(*ds);
331bcdd5 645 });
2087df40
OM
646 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, who, true, 0xffff));
647 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, who, true, 0xffff));
8302d4cb 648 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, who, true));
e6a9dde5 649 g_log<<Logger::Warning<<endl;
331bcdd5
PL
650 return "Added Trust Anchor for " + who.toStringRootDot() + " with data " + what + "\n";
651 }
652 catch(std::exception &e) {
e6a9dde5 653 g_log<<Logger::Warning<<", failed: "<<e.what()<<endl;
331bcdd5
PL
654 return "Unable to add Trust Anchor for " + who.toStringRootDot() + ": " + e.what() + "\n";
655 }
656}
657
658template<typename T>
ea7bc6d8 659static string doClearTA(T begin, T end)
331bcdd5 660{
4865b6cb
PL
661 if(checkDNSSECDisabled())
662 return "DNSSEC is disabled in the configuration, not removing a Trust Anchor\n";
663
331bcdd5
PL
664 if(begin == end)
665 return "No Trust Anchor to clear\n";
666
667 vector<DNSName> toRemove;
668 DNSName who;
669 while (begin != end) {
670 try {
671 who = DNSName(*begin);
672 }
673 catch(std::exception &e) {
674 string ret("Error: ");
675 ret += e.what();
676 ret += ". No Anchors removed\n";
677 return ret;
678 }
679 if (who.isRoot())
680 return "Refusing to remove root Trust Anchor, no Anchors removed\n";
681 toRemove.push_back(who);
682 begin++;
683 }
684
685 string removed("");
686 bool first(true);
dd079764 687 for (auto const &entry : toRemove) {
e6a9dde5 688 g_log<<Logger::Warning<<"Removing Trust Anchor for "<<entry<<", requested via control channel"<<endl;
dd079764
RG
689 g_luaconfs.modify([entry](LuaConfigItems& lci) {
690 lci.dsAnchors.erase(entry);
331bcdd5 691 });
2087df40
OM
692 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, entry, true, 0xffff));
693 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, entry, true, 0xffff));
8302d4cb 694 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, entry, true));
331bcdd5
PL
695 if (!first) {
696 first = false;
697 removed += ",";
698 }
dd079764 699 removed += " " + entry.toStringRootDot();
331bcdd5
PL
700 }
701 return "Removed Trust Anchor(s) for" + removed + "\n";
702}
703
704static string getTAs()
705{
4865b6cb
PL
706 if(checkDNSSECDisabled())
707 return "DNSSEC is disabled in the configuration\n";
708
331bcdd5
PL
709 string ret("Configured Trust Anchors:\n");
710 auto luaconf = g_luaconfs.getLocal();
52ad9eea
PL
711 for (auto anchor : luaconf->dsAnchors) {
712 ret += anchor.first.toLogString() + "\n";
713 for (auto e : anchor.second) {
64a4a928 714 ret+="\t\t"+e.getZoneRepresentation() + "\n";
52ad9eea
PL
715 }
716 }
717
331bcdd5
PL
718 return ret;
719}
720
aadceba8 721template<typename T>
ea7bc6d8 722static string setMinimumTTL(T begin, T end)
aadceba8 723{
5cf4b2e7 724 if(end-begin != 1)
aadceba8 725 return "Need to supply new minimum TTL number\n";
56fddb46
RG
726 try {
727 SyncRes::s_minimumTTL = pdns_stou(*begin);
728 return "New minimum TTL: " + std::to_string(SyncRes::s_minimumTTL) + "\n";
729 }
730 catch (const std::exception& e) {
731 return "Error parsing the new minimum TTL number: " + std::string(e.what()) + "\n";
732 }
aadceba8 733}
734
5cf4b2e7
RG
735template<typename T>
736static string setMinimumECSTTL(T begin, T end)
737{
738 if(end-begin != 1)
739 return "Need to supply new ECS minimum TTL number\n";
56fddb46
RG
740 try {
741 SyncRes::s_minimumECSTTL = pdns_stou(*begin);
742 return "New minimum ECS TTL: " + std::to_string(SyncRes::s_minimumECSTTL) + "\n";
743 }
744 catch (const std::exception& e) {
745 return "Error parsing the new ECS minimum TTL number: " + std::string(e.what()) + "\n";
746 }
5cf4b2e7
RG
747}
748
a6f7f5fe 749template<typename T>
ea7bc6d8 750static string setMaxCacheEntries(T begin, T end)
a6f7f5fe 751{
752 if(end-begin != 1)
753 return "Need to supply new cache size\n";
56fddb46
RG
754 try {
755 g_maxCacheEntries = pdns_stou(*begin);
756 return "New max cache entries: " + std::to_string(g_maxCacheEntries) + "\n";
757 }
758 catch (const std::exception& e) {
759 return "Error parsing the new cache size: " + std::string(e.what()) + "\n";
760 }
a6f7f5fe 761}
762
763template<typename T>
ea7bc6d8 764static string setMaxPacketCacheEntries(T begin, T end)
a6f7f5fe 765{
766 if(end-begin != 1)
767 return "Need to supply new packet cache size\n";
56fddb46
RG
768 try {
769 g_maxPacketCacheEntries = pdns_stou(*begin);
770 return "New max packetcache entries: " + std::to_string(g_maxPacketCacheEntries) + "\n";
771 }
772 catch (const std::exception& e) {
773 return "Error parsing the new packet cache size: " + std::string(e.what()) + "\n";
774 }
a6f7f5fe 775}
776
aadceba8 777
a19fb8e8
BH
778static uint64_t getSysTimeMsec()
779{
780 struct rusage ru;
781 getrusage(RUSAGE_SELF, &ru);
15ea0ff9 782 return (ru.ru_stime.tv_sec*1000ULL + ru.ru_stime.tv_usec/1000);
a19fb8e8
BH
783}
784
785static uint64_t getUserTimeMsec()
786{
787 struct rusage ru;
788 getrusage(RUSAGE_SELF, &ru);
15ea0ff9 789 return (ru.ru_utime.tv_sec*1000ULL + ru.ru_utime.tv_usec/1000);
a19fb8e8 790}
a19fb8e8 791
5ac6d761 792/* This is a pretty weird set of functions. To get per-thread cpu usage numbers,
793 we have to ask a thread over a pipe. We could do so surgically, so if you want to know about
794 thread 3, we pick pipe 3, but we lack that infrastructure.
795
796 We can however ask "execute this function on all threads and add up the results".
797 This is what the first function does using a custom object ThreadTimes, which if you add
798 to each other keeps filling the first one with CPU usage numbers
799*/
800
801static ThreadTimes* pleaseGetThreadCPUMsec()
802{
803 uint64_t ret=0;
804#ifdef RUSAGE_THREAD
805 struct rusage ru;
806 getrusage(RUSAGE_THREAD, &ru);
807 ret = (ru.ru_utime.tv_sec*1000ULL + ru.ru_utime.tv_usec/1000);
808 ret += (ru.ru_stime.tv_sec*1000ULL + ru.ru_stime.tv_usec/1000);
809#endif
690b86b7 810 return new ThreadTimes{ret, vector<uint64_t>()};
5ac6d761 811}
812
813/* Next up, when you want msec data for a specific thread, we check
814 if we recently executed pleaseGetThreadCPUMsec. If we didn't we do so
815 now and consult all threads.
816
817 We then answer you from the (re)fresh(ed) ThreadTimes.
818*/
819static uint64_t doGetThreadCPUMsec(int n)
820{
821 static std::mutex s_mut;
822 static time_t last = 0;
823 static ThreadTimes tt;
824
825 std::lock_guard<std::mutex> l(s_mut);
826 if(last != time(nullptr)) {
827 tt = broadcastAccFunction<ThreadTimes>(pleaseGetThreadCPUMsec);
828 last = time(nullptr);
829 }
830
831 return tt.times.at(n);
832}
833
5e3de507
BH
834static uint64_t calculateUptime()
835{
ea7bc6d8 836 return time(nullptr) - g_stats.startupTime;
5e3de507
BH
837}
838
13034931 839static string* pleaseGetCurrentQueries()
d2392145
BH
840{
841 ostringstream ostr;
a512e3d1 842 struct timeval now;
843 gettimeofday(&now, 0);
d2392145 844
f165a1f4 845 ostr << getMT()->d_waiters.size() <<" currently outstanding questions\n";
d2392145 846
a512e3d1 847 boost::format fmt("%1% %|40t|%2% %|47t|%3% %|63t|%4% %|68t|%5% %|78t|%6%\n");
d2392145 848
a512e3d1 849 ostr << (fmt % "qname" % "qtype" % "remote" % "tcp" % "chained" % "spent(ms)");
06857845
RG
850 unsigned int n=0;
851 for(const auto& mthread : getMT()->d_waiters) {
852 const PacketID& pident = mthread.key;
a512e3d1 853 const double spent = g_networkTimeoutMsec - (DiffTime(now, mthread.ttd) * 1000);
d2392145 854 ostr << (fmt
93fe642d 855 % pident.domain.toLogString() /* ?? */ % DNSRecordContent::NumberToType(pident.type)
4957a608
BH
856 % pident.remote.toString() % (pident.sock ? 'Y' : 'n')
857 % (pident.fd == -1 ? 'Y' : 'n')
a512e3d1 858 % (spent > 0 ? spent : '0')
4957a608 859 );
06857845
RG
860 ++n;
861 if (n >= 100)
862 break;
d2392145
BH
863 }
864 ostr <<" - done\n";
3427fa8a
BH
865 return new string(ostr.str());
866}
867
868static string doCurrentQueries()
869{
870 return broadcastAccFunction<string>(pleaseGetCurrentQueries);
871}
872
13034931 873uint64_t* pleaseGetThrottleSize()
3427fa8a 874{
a712cb56 875 return new uint64_t(SyncRes::getThrottledServersSize());
3427fa8a
BH
876}
877
878static uint64_t getThrottleSize()
879{
880 return broadcastAccFunction<uint64_t>(pleaseGetThrottleSize);
881}
882
13034931 883uint64_t* pleaseGetNegCacheSize()
3427fa8a 884{
a712cb56 885 uint64_t tmp=(SyncRes::getNegCacheSize());
3427fa8a 886 return new uint64_t(tmp);
d2392145
BH
887}
888
ea7bc6d8 889static uint64_t getNegCacheSize()
bb4bdbaf 890{
3427fa8a
BH
891 return broadcastAccFunction<uint64_t>(pleaseGetNegCacheSize);
892}
893
ea7bc6d8 894static uint64_t* pleaseGetFailedHostsSize()
406f46f9 895{
a712cb56 896 uint64_t tmp=(SyncRes::getThrottledServersSize());
406f46f9 897 return new uint64_t(tmp);
898}
ea7bc6d8
RG
899
900static uint64_t getFailedHostsSize()
406f46f9 901{
902 return broadcastAccFunction<uint64_t>(pleaseGetFailedHostsSize);
903}
904
13034931 905uint64_t* pleaseGetNsSpeedsSize()
3427fa8a 906{
a712cb56 907 return new uint64_t(SyncRes::getNSSpeedsSize());
bb4bdbaf
BH
908}
909
ea7bc6d8 910static uint64_t getNsSpeedsSize()
bb4bdbaf 911{
3427fa8a
BH
912 return broadcastAccFunction<uint64_t>(pleaseGetNsSpeedsSize);
913}
914
60e5208a
OM
915uint64_t* pleaseGetFailedServersSize()
916{
917 return new uint64_t(SyncRes::getFailedServersSize());
918}
919
bbc7101c
OM
920uint64_t* pleaseGetEDNSStatusesSize()
921{
922 return new uint64_t(SyncRes::getEDNSStatusesSize());
923}
924
13034931 925uint64_t* pleaseGetConcurrentQueries()
3427fa8a 926{
f165a1f4 927 return new uint64_t(getMT() ? getMT()->numProcesses() : 0);
3427fa8a
BH
928}
929
930static uint64_t getConcurrentQueries()
931{
932 return broadcastAccFunction<uint64_t>(pleaseGetConcurrentQueries);
933}
934
13034931 935uint64_t* pleaseGetCacheSize()
3427fa8a 936{
d705aad9 937 return new uint64_t(t_RC ? t_RC->size() : 0);
3427fa8a
BH
938}
939
ea7bc6d8 940static uint64_t* pleaseGetCacheBytes()
0bbf7d0a 941{
d705aad9 942 return new uint64_t(t_RC ? t_RC->bytes() : 0);
0bbf7d0a
BH
943}
944
ea7bc6d8 945static uint64_t doGetCacheSize()
3427fa8a
BH
946{
947 return broadcastAccFunction<uint64_t>(pleaseGetCacheSize);
948}
949
ea7bc6d8 950static uint64_t doGetAvgLatencyUsec()
08f3f638 951{
952 return (uint64_t) g_stats.avgLatencyUsec;
953}
954
ea7bc6d8 955static uint64_t doGetCacheBytes()
0bbf7d0a
BH
956{
957 return broadcastAccFunction<uint64_t>(pleaseGetCacheBytes);
958}
959
13034931 960uint64_t* pleaseGetCacheHits()
3427fa8a 961{
d705aad9 962 return new uint64_t(t_RC ? t_RC->cacheHits : 0);
3427fa8a
BH
963}
964
ea7bc6d8 965static uint64_t doGetCacheHits()
3427fa8a
BH
966{
967 return broadcastAccFunction<uint64_t>(pleaseGetCacheHits);
968}
969
13034931 970uint64_t* pleaseGetCacheMisses()
3427fa8a 971{
d705aad9 972 return new uint64_t(t_RC ? t_RC->cacheMisses : 0);
3427fa8a
BH
973}
974
ea7bc6d8 975static uint64_t doGetCacheMisses()
3427fa8a
BH
976{
977 return broadcastAccFunction<uint64_t>(pleaseGetCacheMisses);
bb4bdbaf
BH
978}
979
16beeaa4
BH
980uint64_t* pleaseGetPacketCacheSize()
981{
d705aad9 982 return new uint64_t(t_packetCache ? t_packetCache->size() : 0);
16beeaa4
BH
983}
984
ea7bc6d8 985static uint64_t* pleaseGetPacketCacheBytes()
0bbf7d0a 986{
d705aad9 987 return new uint64_t(t_packetCache ? t_packetCache->bytes() : 0);
0bbf7d0a
BH
988}
989
ea7bc6d8 990static uint64_t doGetPacketCacheSize()
16beeaa4
BH
991{
992 return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheSize);
993}
994
ea7bc6d8 995static uint64_t doGetPacketCacheBytes()
0bbf7d0a
BH
996{
997 return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheBytes);
998}
999
16beeaa4
BH
1000uint64_t* pleaseGetPacketCacheHits()
1001{
d705aad9 1002 return new uint64_t(t_packetCache ? t_packetCache->d_hits : 0);
16beeaa4
BH
1003}
1004
ea7bc6d8 1005static uint64_t doGetPacketCacheHits()
16beeaa4
BH
1006{
1007 return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheHits);
1008}
1009
ea7bc6d8 1010static uint64_t* pleaseGetPacketCacheMisses()
16beeaa4 1011{
d705aad9 1012 return new uint64_t(t_packetCache ? t_packetCache->d_misses : 0);
16beeaa4
BH
1013}
1014
ea7bc6d8 1015static uint64_t doGetPacketCacheMisses()
16beeaa4
BH
1016{
1017 return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheMisses);
1018}
1019
ea7bc6d8 1020static uint64_t doGetMallocated()
0bbf7d0a
BH
1021{
1022 // this turned out to be broken
1023/* struct mallinfo mi = mallinfo();
1024 return mi.uordblks; */
1025 return 0;
1026}
16beeaa4 1027
79332bff
F
1028extern ResponseStats g_rs;
1029
b0b37121 1030void registerAllStats()
1d5b3ce6 1031{
c25e045e
RG
1032 static std::atomic_flag s_init = ATOMIC_FLAG_INIT;
1033 if(s_init.test_and_set())
5d088f1f 1034 return;
5d088f1f 1035
aaacf7f2 1036 addGetStat("questions", &g_stats.qcounter);
d7f10541 1037 addGetStat("ipv6-questions", &g_stats.ipv6qcounter);
aaacf7f2 1038 addGetStat("tcp-questions", &g_stats.tcpqcounter);
1d5b3ce6 1039
3427fa8a
BH
1040 addGetStat("cache-hits", doGetCacheHits);
1041 addGetStat("cache-misses", doGetCacheMisses);
cf5dcae9 1042 addGetStat("cache-entries", doGetCacheSize);
1043 addGetStat("max-cache-entries", []() { return g_maxCacheEntries.load(); });
1044 addGetStat("max-packetcache-entries", []() { return g_maxPacketCacheEntries.load();});
0bbf7d0a 1045 addGetStat("cache-bytes", doGetCacheBytes);
16beeaa4
BH
1046
1047 addGetStat("packetcache-hits", doGetPacketCacheHits);
1048 addGetStat("packetcache-misses", doGetPacketCacheMisses);
1049 addGetStat("packetcache-entries", doGetPacketCacheSize);
0bbf7d0a 1050 addGetStat("packetcache-bytes", doGetPacketCacheBytes);
16beeaa4 1051
0bbf7d0a 1052 addGetStat("malloc-bytes", doGetMallocated);
16beeaa4 1053
1d5b3ce6
BH
1054 addGetStat("servfail-answers", &g_stats.servFails);
1055 addGetStat("nxdomain-answers", &g_stats.nxDomains);
1056 addGetStat("noerror-answers", &g_stats.noErrors);
fe213470 1057
c8ddb7c2
BH
1058 addGetStat("unauthorized-udp", &g_stats.unauthorizedUDP);
1059 addGetStat("unauthorized-tcp", &g_stats.unauthorizedTCP);
4e120339 1060 addGetStat("tcp-client-overflow", &g_stats.tcpClientOverflow);
c8ddb7c2 1061
0e9d9ce2
BH
1062 addGetStat("client-parse-errors", &g_stats.clientParseError);
1063 addGetStat("server-parse-errors", &g_stats.serverParseError);
b71b60ee 1064 addGetStat("too-old-drops", &g_stats.tooOldDrops);
ba892c7f 1065 addGetStat("truncated-drops", &g_stats.truncatedDrops);
cf8cda18 1066 addGetStat("query-pipe-full-drops", &g_stats.queryPipeFullDrops);
0e9d9ce2 1067
fe213470
BH
1068 addGetStat("answers0-1", &g_stats.answers0_1);
1069 addGetStat("answers1-10", &g_stats.answers1_10);
1070 addGetStat("answers10-100", &g_stats.answers10_100);
1071 addGetStat("answers100-1000", &g_stats.answers100_1000);
1072 addGetStat("answers-slow", &g_stats.answersSlow);
1073
19178da9 1074 addGetStat("x-ourtime0-1", &g_stats.ourtime0_1);
1075 addGetStat("x-ourtime1-2", &g_stats.ourtime1_2);
1076 addGetStat("x-ourtime2-4", &g_stats.ourtime2_4);
1077 addGetStat("x-ourtime4-8", &g_stats.ourtime4_8);
1078 addGetStat("x-ourtime8-16", &g_stats.ourtime8_16);
1079 addGetStat("x-ourtime16-32", &g_stats.ourtime16_32);
1080 addGetStat("x-ourtime-slow", &g_stats.ourtimeSlow);
40c3d660 1081
7b75810e 1082 addGetStat("auth4-answers0-1", &g_stats.auth4Answers0_1);
1083 addGetStat("auth4-answers1-10", &g_stats.auth4Answers1_10);
1084 addGetStat("auth4-answers10-100", &g_stats.auth4Answers10_100);
1085 addGetStat("auth4-answers100-1000", &g_stats.auth4Answers100_1000);
1086 addGetStat("auth4-answers-slow", &g_stats.auth4AnswersSlow);
1087
1088 addGetStat("auth6-answers0-1", &g_stats.auth6Answers0_1);
1089 addGetStat("auth6-answers1-10", &g_stats.auth6Answers1_10);
1090 addGetStat("auth6-answers10-100", &g_stats.auth6Answers10_100);
1091 addGetStat("auth6-answers100-1000", &g_stats.auth6Answers100_1000);
1092 addGetStat("auth6-answers-slow", &g_stats.auth6AnswersSlow);
1093
11adfdd3 1094
08f3f638 1095 addGetStat("qa-latency", doGetAvgLatencyUsec);
19178da9 1096 addGetStat("x-our-latency", []() { return g_stats.avgLatencyOursUsec; });
0d5f0a9f 1097 addGetStat("unexpected-packets", &g_stats.unexpectedCount);
7a132082 1098 addGetStat("case-mismatches", &g_stats.caseMismatchCount);
0d5f0a9f 1099 addGetStat("spoof-prevents", &g_stats.spoofCount);
574af7ea 1100
1ef00ba1
BH
1101 addGetStat("nsset-invalidations", &g_stats.nsSetInvalidations);
1102
998a4334 1103 addGetStat("resource-limits", &g_stats.resourceLimits);
01b36509 1104 addGetStat("over-capacity-drops", &g_stats.overCapacityDrops);
e9c2ad3a 1105 addGetStat("policy-drops", &g_stats.policyDrops);
9326cae1 1106 addGetStat("no-packet-error", &g_stats.noPacketError);
3074f130 1107 addGetStat("dlg-only-drops", &SyncRes::s_nodelegated);
048f5db6 1108 addGetStat("ignored-packets", &g_stats.ignoredCount);
c0f9be19 1109 addGetStat("empty-queries", &g_stats.emptyQueriesCount);
ec6eacbc 1110 addGetStat("max-mthread-stack", &g_stats.maxMThreadStackUsage);
60911a71 1111
ea7bc6d8
RG
1112 addGetStat("negcache-entries", getNegCacheSize);
1113 addGetStat("throttle-entries", getThrottleSize);
bb4bdbaf 1114
ea7bc6d8
RG
1115 addGetStat("nsspeeds-entries", getNsSpeedsSize);
1116 addGetStat("failed-host-entries", getFailedHostsSize);
1d5b3ce6 1117
ea7bc6d8 1118 addGetStat("concurrent-queries", getConcurrentQueries);
d67620e4 1119 addGetStat("security-status", &g_security_status);
1d5b3ce6 1120 addGetStat("outgoing-timeouts", &SyncRes::s_outgoingtimeouts);
7b75810e 1121 addGetStat("outgoing4-timeouts", &SyncRes::s_outgoing4timeouts);
1122 addGetStat("outgoing6-timeouts", &SyncRes::s_outgoing6timeouts);
e9a628a2 1123 addGetStat("auth-zone-queries", &SyncRes::s_authzonequeries);
1d5b3ce6
BH
1124 addGetStat("tcp-outqueries", &SyncRes::s_tcpoutqueries);
1125 addGetStat("all-outqueries", &SyncRes::s_outqueries);
996c89cc 1126 addGetStat("ipv6-outqueries", &g_stats.ipv6queries);
1d5b3ce6 1127 addGetStat("throttled-outqueries", &SyncRes::s_throttledqueries);
66e0b6ea 1128 addGetStat("dont-outqueries", &SyncRes::s_dontqueries);
c701672a 1129 addGetStat("qname-min-fallback-success", &SyncRes::s_qnameminfallbacksuccess);
efc7c786 1130 addGetStat("throttled-out", &SyncRes::s_throttledqueries);
c571588b 1131 addGetStat("unreachables", &SyncRes::s_unreachables);
d6923beb 1132 addGetStat("ecs-queries", &SyncRes::s_ecsqueries);
1133 addGetStat("ecs-responses", &SyncRes::s_ecsresponses);
34801ab1 1134 addGetStat("chain-resends", &g_stats.chainResends);
50a5ef72 1135 addGetStat("tcp-clients", boost::bind(TCPConnection::getCurrentConnections));
1d5b3ce6 1136
8290ad9f 1137#ifdef __linux__
1138 addGetStat("udp-recvbuf-errors", boost::bind(udpErrorStats, "udp-recvbuf-errors"));
1139 addGetStat("udp-sndbuf-errors", boost::bind(udpErrorStats, "udp-sndbuf-errors"));
1140 addGetStat("udp-noport-errors", boost::bind(udpErrorStats, "udp-noport-errors"));
1141 addGetStat("udp-in-errors", boost::bind(udpErrorStats, "udp-in-errors"));
1142#endif
1143
c0ea6e55
BH
1144 addGetStat("edns-ping-matches", &g_stats.ednsPingMatches);
1145 addGetStat("edns-ping-mismatches", &g_stats.ednsPingMismatches);
5b9853c9 1146 addGetStat("dnssec-queries", &g_stats.dnssecQueries);
49dc532e 1147
88c33dca
RG
1148 addGetStat("dnssec-authentic-data-queries", &g_stats.dnssecAuthenticDataQueries);
1149 addGetStat("dnssec-check-disabled-queries", &g_stats.dnssecCheckDisabledQueries);
c0ea6e55 1150
49dc532e 1151 addGetStat("variable-responses", &g_stats.variableResponses);
1152
c0ea6e55
BH
1153 addGetStat("noping-outqueries", &g_stats.noPingOutQueries);
1154 addGetStat("noedns-outqueries", &g_stats.noEdnsOutQueries);
1155
5e3de507 1156 addGetStat("uptime", calculateUptime);
5a812f5a 1157 addGetStat("real-memory-usage", boost::bind(getRealMemoryUsage, string()));
330dcb5c
OM
1158 addGetStat("special-memory-usage", boost::bind(getSpecialMemoryUsage, string()));
1159 addGetStat("fd-usage", boost::bind(getOpenFileDescriptors, string()));
5e3de507 1160
a254e9b6 1161 // addGetStat("query-rate", getQueryRate);
a19fb8e8
BH
1162 addGetStat("user-msec", getUserTimeMsec);
1163 addGetStat("sys-msec", getSysTimeMsec);
8f7473d7 1164
2e27f874
RG
1165#ifdef __linux__
1166 addGetStat("cpu-iowait", boost::bind(getCPUIOWait, string()));
1167 addGetStat("cpu-steal", boost::bind(getCPUSteal, string()));
1168#endif
1169
5ac6d761 1170 for(unsigned int n=0; n < g_numThreads; ++n)
1171 addGetStat("cpu-msec-thread-"+std::to_string(n), boost::bind(&doGetThreadCPUMsec, n));
1172
8f7473d7 1173#ifdef MALLOC_TRACE
1174 addGetStat("memory-allocs", boost::bind(&MallocTracer::getAllocs, g_mtracer, string()));
1175 addGetStat("memory-alloc-flux", boost::bind(&MallocTracer::getAllocFlux, g_mtracer, string()));
1176 addGetStat("memory-allocated", boost::bind(&MallocTracer::getTotAllocated, g_mtracer, string()));
1177#endif
849fe8d2
PL
1178
1179 addGetStat("dnssec-validations", &g_stats.dnssecValidations);
1180 addGetStat("dnssec-result-insecure", &g_stats.dnssecResults[Insecure]);
1181 addGetStat("dnssec-result-secure", &g_stats.dnssecResults[Secure]);
1182 addGetStat("dnssec-result-bogus", &g_stats.dnssecResults[Bogus]);
1183 addGetStat("dnssec-result-indeterminate", &g_stats.dnssecResults[Indeterminate]);
1184 addGetStat("dnssec-result-nta", &g_stats.dnssecResults[NTA]);
7a25883a
PL
1185
1186 addGetStat("policy-result-noaction", &g_stats.policyResults[DNSFilterEngine::PolicyKind::NoAction]);
1187 addGetStat("policy-result-drop", &g_stats.policyResults[DNSFilterEngine::PolicyKind::Drop]);
1188 addGetStat("policy-result-nxdomain", &g_stats.policyResults[DNSFilterEngine::PolicyKind::NXDOMAIN]);
1189 addGetStat("policy-result-nodata", &g_stats.policyResults[DNSFilterEngine::PolicyKind::NODATA]);
1190 addGetStat("policy-result-truncate", &g_stats.policyResults[DNSFilterEngine::PolicyKind::Truncate]);
1191 addGetStat("policy-result-custom", &g_stats.policyResults[DNSFilterEngine::PolicyKind::Custom]);
c9783016 1192
596bf482
RG
1193 addGetStat("rebalanced-queries", &g_stats.rebalancedQueries);
1194
c9783016
RG
1195 /* make sure that the ECS stats are properly initialized */
1196 SyncRes::clearECSStats();
1197 for (size_t idx = 0; idx < SyncRes::s_ecsResponsesBySubnetSize4.size(); idx++) {
1198 const std::string name = "ecs-v4-response-bits-" + std::to_string(idx + 1);
1199 addGetStat(name, &(SyncRes::s_ecsResponsesBySubnetSize4.at(idx)));
c9783016
RG
1200 }
1201 for (size_t idx = 0; idx < SyncRes::s_ecsResponsesBySubnetSize6.size(); idx++) {
1202 const std::string name = "ecs-v6-response-bits-" + std::to_string(idx + 1);
1203 addGetStat(name, &(SyncRes::s_ecsResponsesBySubnetSize6.at(idx)));
c9783016 1204 }
1d5b3ce6
BH
1205}
1206
9f374187 1207void doExitGeneric(bool nicely)
1d5b3ce6 1208{
e6a9dde5 1209 g_log<<Logger::Error<<"Exiting on user request"<<endl;
87a5ea63 1210 extern RecursorControlChannel s_rcc;
8657c2af 1211 s_rcc.~RecursorControlChannel();
87a5ea63
BH
1212
1213 extern string s_pidfname;
8657c2af 1214 if(!s_pidfname.empty())
87a5ea63 1215 unlink(s_pidfname.c_str()); // we can at least try..
8657c2af
OM
1216 if(nicely) {
1217 RecursorControlChannel::stop = 1;
1218 } else {
bb4bdbaf 1219 _exit(1);
8657c2af 1220 }
aaacf7f2
BH
1221}
1222
9f374187 1223void doExit()
bb4bdbaf
BH
1224{
1225 doExitGeneric(false);
1226}
1227
9f374187 1228void doExitNicely()
bb4bdbaf
BH
1229{
1230 doExitGeneric(true);
1231}
1232
c5c066bf 1233vector<pair<DNSName, uint16_t> >* pleaseGetQueryRing()
92011b8f 1234{
c5c066bf 1235 typedef pair<DNSName,uint16_t> query_t;
92011b8f 1236 vector<query_t >* ret = new vector<query_t>();
1237 if(!t_queryring)
1238 return ret;
1239 ret->reserve(t_queryring->size());
1240
ff05fd12 1241 for(const query_t& q : *t_queryring) {
92011b8f 1242 ret->push_back(q);
1243 }
1244 return ret;
1245}
c5c066bf 1246vector<pair<DNSName,uint16_t> >* pleaseGetServfailQueryRing()
92011b8f 1247{
c5c066bf 1248 typedef pair<DNSName,uint16_t> query_t;
92011b8f 1249 vector<query_t>* ret = new vector<query_t>();
1250 if(!t_servfailqueryring)
1251 return ret;
5af86fdc 1252 ret->reserve(t_servfailqueryring->size());
ff05fd12 1253 for(const query_t& q : *t_servfailqueryring) {
92011b8f 1254 ret->push_back(q);
1255 }
1256 return ret;
1257}
66f2e6ad
KM
1258vector<pair<DNSName,uint16_t> >* pleaseGetBogusQueryRing()
1259{
1260 typedef pair<DNSName,uint16_t> query_t;
1261 vector<query_t>* ret = new vector<query_t>();
1262 if(!t_bogusqueryring)
1263 return ret;
1264 ret->reserve(t_bogusqueryring->size());
1265 for(const query_t& q : *t_bogusqueryring) {
1266 ret->push_back(q);
1267 }
1268 return ret;
1269}
92011b8f 1270
1271
1272
1273typedef boost::function<vector<ComboAddress>*()> pleaseremotefunc_t;
c5c066bf 1274typedef boost::function<vector<pair<DNSName,uint16_t> >*()> pleasequeryfunc_t;
92011b8f 1275
b3b5459d
BH
1276vector<ComboAddress>* pleaseGetRemotes()
1277{
92011b8f 1278 vector<ComboAddress>* ret = new vector<ComboAddress>();
1279 if(!t_remotes)
1280 return ret;
1281
1282 ret->reserve(t_remotes->size());
ff05fd12 1283 for(const ComboAddress& ca : *t_remotes) {
92011b8f 1284 ret->push_back(ca);
1285 }
1286 return ret;
b3b5459d 1287}
bb4bdbaf 1288
92011b8f 1289vector<ComboAddress>* pleaseGetServfailRemotes()
1290{
1291 vector<ComboAddress>* ret = new vector<ComboAddress>();
1292 if(!t_servfailremotes)
1293 return ret;
f8f243b0 1294 ret->reserve(t_servfailremotes->size());
ff05fd12 1295 for(const ComboAddress& ca : *t_servfailremotes) {
92011b8f 1296 ret->push_back(ca);
1297 }
1298 return ret;
1299}
1300
66f2e6ad
KM
1301vector<ComboAddress>* pleaseGetBogusRemotes()
1302{
1303 vector<ComboAddress>* ret = new vector<ComboAddress>();
1304 if(!t_bogusremotes)
1305 return ret;
1306 ret->reserve(t_bogusremotes->size());
1307 for(const ComboAddress& ca : *t_bogusremotes) {
1308 ret->push_back(ca);
1309 }
1310 return ret;
1311}
1312
92011b8f 1313vector<ComboAddress>* pleaseGetLargeAnswerRemotes()
1314{
1315 vector<ComboAddress>* ret = new vector<ComboAddress>();
1316 if(!t_largeanswerremotes)
1317 return ret;
f8f243b0 1318 ret->reserve(t_largeanswerremotes->size());
ff05fd12 1319 for(const ComboAddress& ca : *t_largeanswerremotes) {
92011b8f 1320 ret->push_back(ca);
1321 }
1322 return ret;
1323}
1324
621ccf89 1325vector<ComboAddress>* pleaseGetTimeouts()
1326{
1327 vector<ComboAddress>* ret = new vector<ComboAddress>();
1328 if(!t_timeouts)
1329 return ret;
1330 ret->reserve(t_timeouts->size());
1331 for(const ComboAddress& ca : *t_timeouts) {
1332 ret->push_back(ca);
1333 }
1334 return ret;
1335}
1336
92011b8f 1337string doGenericTopRemotes(pleaseremotefunc_t func)
a9af3782 1338{
11a7242f 1339 typedef map<ComboAddress, int, ComboAddress::addressOnlyLessThan> counts_t;
a9af3782 1340 counts_t counts;
b3b5459d 1341
92011b8f 1342 vector<ComboAddress> remotes=broadcastAccFunction<vector<ComboAddress> >(func);
b3b5459d 1343
a9af3782 1344 unsigned int total=0;
ff05fd12 1345 for(const ComboAddress& ca : remotes) {
92011b8f 1346 total++;
1347 counts[ca]++;
1348 }
1349
18e7758c 1350 typedef std::multimap<int, ComboAddress> rcounts_t;
a9af3782
BH
1351 rcounts_t rcounts;
1352
1353 for(counts_t::const_iterator i=counts.begin(); i != counts.end(); ++i)
1354 rcounts.insert(make_pair(-i->second, i->first));
1355
1356 ostringstream ret;
92011b8f 1357 ret<<"Over last "<<total<<" entries:\n";
a9af3782 1358 format fmt("%.02f%%\t%s\n");
92011b8f 1359 int limit=0, accounted=0;
1360 if(total) {
1361 for(rcounts_t::const_iterator i=rcounts.begin(); i != rcounts.end() && limit < 20; ++i, ++limit) {
a9af3782 1362 ret<< fmt % (-100.0*i->first/total) % i->second.toString();
92011b8f 1363 accounted+= -i->first;
1364 }
1365 ret<< '\n' << fmt % (100.0*(total-accounted)/total) % "rest";
1366 }
1367 return ret.str();
1368}
1369
8171ab83 1370// XXX DNSName Pain - this function should benefit from native DNSName methods
c5c066bf 1371DNSName getRegisteredName(const DNSName& dom)
92011b8f 1372{
c5c066bf 1373 auto parts=dom.getRawLabels();
92011b8f 1374 if(parts.size()<=2)
1375 return dom;
1376 reverse(parts.begin(), parts.end());
ff05fd12 1377 for(string& str : parts) { str=toLower(str); };
92011b8f 1378
f468a3a1 1379 // uk co migweb
1380 string last;
1381 while(!parts.empty()) {
1382 if(parts.size()==1 || binary_search(g_pubs.begin(), g_pubs.end(), parts)) {
1383
1384 string ret=last;
1385 if(!ret.empty())
1386 ret+=".";
1387
3c05acf8 1388 for(auto p = parts.crbegin(); p != parts.crend(); ++p) {
1389 ret+=(*p)+".";
f468a3a1 1390 }
8171ab83 1391 return DNSName(ret);
92011b8f 1392 }
f468a3a1 1393
1394 last=parts[parts.size()-1];
1395 parts.resize(parts.size()-1);
92011b8f 1396 }
8171ab83 1397 return DNSName("??");
92011b8f 1398}
1399
c5c066bf 1400static DNSName nopFilter(const DNSName& name)
92011b8f 1401{
c5c066bf 1402 return name;
92011b8f 1403}
1404
c5c066bf 1405string doGenericTopQueries(pleasequeryfunc_t func, boost::function<DNSName(const DNSName&)> filter=nopFilter)
92011b8f 1406{
c5c066bf 1407 typedef pair<DNSName,uint16_t> query_t;
92011b8f 1408 typedef map<query_t, int> counts_t;
1409 counts_t counts;
1410 vector<query_t> queries=broadcastAccFunction<vector<query_t> >(func);
1411
1412 unsigned int total=0;
ff05fd12 1413 for(const query_t& q : queries) {
92011b8f 1414 total++;
c5c066bf 1415 counts[make_pair(filter(q.first),q.second)]++;
92011b8f 1416 }
1417
1418 typedef std::multimap<int, query_t> rcounts_t;
1419 rcounts_t rcounts;
1420
1421 for(counts_t::const_iterator i=counts.begin(); i != counts.end(); ++i)
1422 rcounts.insert(make_pair(-i->second, i->first));
1423
1424 ostringstream ret;
1425 ret<<"Over last "<<total<<" entries:\n";
1426 format fmt("%.02f%%\t%s\n");
1427 int limit=0, accounted=0;
1428 if(total) {
1429 for(rcounts_t::const_iterator i=rcounts.begin(); i != rcounts.end() && limit < 20; ++i, ++limit) {
d3ca14b2 1430 ret<< fmt % (-100.0*i->first/total) % (i->second.first.toLogString()+"|"+DNSRecordContent::NumberToType(i->second.second));
92011b8f 1431 accounted+= -i->first;
1432 }
1433 ret<< '\n' << fmt % (100.0*(total-accounted)/total) % "rest";
1434 }
1435
1436
a9af3782
BH
1437 return ret.str();
1438}
1439
13034931 1440static string* nopFunction()
3427fa8a
BH
1441{
1442 return new string("pong\n");
1443}
49a699c4 1444
5d75d3d9 1445static string getDontThrottleNames() {
0c366a8e
PL
1446 auto dtn = g_dontThrottleNames.getLocal();
1447 return dtn->toString() + "\n";
1448}
1449
5d75d3d9 1450static string getDontThrottleNetmasks() {
0c366a8e
PL
1451 auto dtn = g_dontThrottleNetmasks.getLocal();
1452 return dtn->toString() + "\n";
1453}
1454
c4ce5418 1455template<typename T>
5d75d3d9 1456static string addDontThrottleNames(T begin, T end) {
c4ce5418
PL
1457 if (begin == end) {
1458 return "No names specified, keeping existing list\n";
1459 }
1460 vector<DNSName> toAdd;
1461 while (begin != end) {
1462 try {
1463 auto d = DNSName(*begin);
1464 toAdd.push_back(d);
1465 }
1466 catch(const std::exception &e) {
1467 return "Problem parsing '" + *begin + "': "+ e.what() + ", nothing added\n";
1468 }
1469 begin++;
1470 }
1471
1472 string ret = "Added";
1473 auto dnt = g_dontThrottleNames.getCopy();
1474 bool first = true;
1475 for (auto const &d : toAdd) {
1476 if (!first) {
1477 ret += ",";
1478 }
1479 first = false;
1480 ret += " " + d.toLogString();
1481 dnt.add(d);
1482 }
1483
d514bd03 1484 g_dontThrottleNames.setState(std::move(dnt));
c4ce5418
PL
1485
1486 ret += " to the list of nameservers that may not be throttled";
1487 g_log<<Logger::Info<<ret<<", requested via control channel"<<endl;
1488 return ret + "\n";
1489}
1490
1491template<typename T>
5d75d3d9 1492static string addDontThrottleNetmasks(T begin, T end) {
c4ce5418
PL
1493 if (begin == end) {
1494 return "No netmasks specified, keeping existing list\n";
1495 }
1496 vector<Netmask> toAdd;
1497 while (begin != end) {
1498 try {
1499 auto n = Netmask(*begin);
1500 toAdd.push_back(n);
1501 }
1502 catch(const std::exception &e) {
1503 return "Problem parsing '" + *begin + "': "+ e.what() + ", nothing added\n";
1504 }
1505 catch(const PDNSException &e) {
1506 return "Problem parsing '" + *begin + "': "+ e.reason + ", nothing added\n";
1507 }
1508 begin++;
1509 }
1510
1511 string ret = "Added";
1512 auto dnt = g_dontThrottleNetmasks.getCopy();
1513 bool first = true;
1514 for (auto const &t : toAdd) {
1515 if (!first) {
1516 ret += ",";
1517 }
1518 first = false;
1519 ret += " " + t.toString();
1520 dnt.addMask(t);
1521 }
1522
d514bd03 1523 g_dontThrottleNetmasks.setState(std::move(dnt));
c4ce5418
PL
1524
1525 ret += " to the list of nameserver netmasks that may not be throttled";
1526 g_log<<Logger::Info<<ret<<", requested via control channel"<<endl;
1527 return ret + "\n";
1528}
1529
fa7cc8af 1530template<typename T>
5d75d3d9 1531static string clearDontThrottleNames(T begin, T end) {
fa7cc8af
PL
1532 if(begin == end)
1533 return "No names specified, doing nothing.\n";
1534
1535 if (begin + 1 == end && *begin == "*"){
1536 SuffixMatchNode smn;
d514bd03 1537 g_dontThrottleNames.setState(std::move(smn));
fa7cc8af
PL
1538 string ret = "Cleared list of nameserver names that may not be throttled";
1539 g_log<<Logger::Warning<<ret<<", requested via control channel"<<endl;
1540 return ret + "\n";
1541 }
1542
1543 vector<DNSName> toRemove;
1544 while (begin != end) {
1545 try {
1546 if (*begin == "*") {
1547 return "Please don't mix '*' with other names, nothing removed\n";
1548 }
1549 toRemove.push_back(DNSName(*begin));
1550 }
1551 catch (const std::exception &e) {
1552 return "Problem parsing '" + *begin + "': "+ e.what() + ", nothing removed\n";
1553 }
1554 begin++;
1555 }
1556
1557 string ret = "Removed";
1558 bool first = true;
1559 auto dnt = g_dontThrottleNames.getCopy();
1560 for (const auto &name : toRemove) {
1561 if (!first) {
1562 ret += ",";
1563 }
1564 first = false;
1565 ret += " " + name.toLogString();
1566 dnt.remove(name);
1567 }
1568
d514bd03 1569 g_dontThrottleNames.setState(std::move(dnt));
fa7cc8af
PL
1570
1571 ret += " from the list of nameservers that may not be throttled";
1572 g_log<<Logger::Info<<ret<<", requested via control channel"<<endl;
1573 return ret + "\n";
1574}
1575
1576template<typename T>
5d75d3d9 1577static string clearDontThrottleNetmasks(T begin, T end) {
fa7cc8af
PL
1578 if(begin == end)
1579 return "No netmasks specified, doing nothing.\n";
1580
1581 if (begin + 1 == end && *begin == "*"){
1582 auto nmg = g_dontThrottleNetmasks.getCopy();
1583 nmg.clear();
d514bd03 1584 g_dontThrottleNetmasks.setState(std::move(nmg));
fa7cc8af
PL
1585
1586 string ret = "Cleared list of nameserver addresses that may not be throttled";
1587 g_log<<Logger::Warning<<ret<<", requested via control channel"<<endl;
1588 return ret + "\n";
1589 }
1590
1591 std::vector<Netmask> toRemove;
1592 while (begin != end) {
1593 try {
1594 if (*begin == "*") {
1595 return "Please don't mix '*' with other netmasks, nothing removed\n";
1596 }
1597 auto n = Netmask(*begin);
1598 toRemove.push_back(n);
1599 }
1600 catch(const std::exception &e) {
1601 return "Problem parsing '" + *begin + "': "+ e.what() + ", nothing added\n";
1602 }
1603 catch(const PDNSException &e) {
1604 return "Problem parsing '" + *begin + "': "+ e.reason + ", nothing added\n";
1605 }
1606 begin++;
1607 }
1608
1609 string ret = "Removed";
1610 bool first = true;
1611 auto dnt = g_dontThrottleNetmasks.getCopy();
1612 for (const auto &mask : toRemove) {
1613 if (!first) {
1614 ret += ",";
1615 }
1616 first = false;
1617 ret += " " + mask.toString();
1618 dnt.deleteMask(mask);
1619 }
1620
d514bd03 1621 g_dontThrottleNetmasks.setState(std::move(dnt));
fa7cc8af
PL
1622
1623 ret += " from the list of nameservers that may not be throttled";
1624 g_log<<Logger::Info<<ret<<", requested via control channel"<<endl;
1625 return ret + "\n";
1626}
1627
1628
aaacf7f2
BH
1629string RecursorControlParser::getAnswer(const string& question, RecursorControlParser::func_t** command)
1630{
1631 *command=nop;
1d5b3ce6
BH
1632 vector<string> words;
1633 stringtok(words, question);
1634
1635 if(words.empty())
aaacf7f2 1636 return "invalid command\n";
1d5b3ce6 1637
748eff9f 1638 string cmd=toLower(words[0]);
1d5b3ce6
BH
1639 vector<string>::const_iterator begin=words.begin()+1, end=words.end();
1640
8e139df6
PD
1641 // should probably have a smart dispatcher here, like auth has
1642 if(cmd=="help")
1643 return
c4ce5418
PL
1644"add-dont-throttle-names [N...] add names that are not allowed to be throttled\n"
1645"add-dont-throttle-netmasks [N...]\n"
1646" add netmasks that are not allowed to be throttled\n"
a38ab818 1647"add-nta DOMAIN [REASON] add a Negative Trust Anchor for DOMAIN with the comment REASON\n"
331bcdd5 1648"add-ta DOMAIN DSRECORD add a Trust Anchor for DOMAIN with data DSRECORD\n"
8e139df6 1649"current-queries show currently active queries\n"
fa7cc8af
PL
1650"clear-dont-throttle-names [N...] remove names that are not allowed to be throttled. If N is '*', remove all\n"
1651"clear-dont-throttle-netmasks [N...]\n"
1652" remove netmasks that are not allowed to be throttled. If N is '*', remove all\n"
a38ab818 1653"clear-nta [DOMAIN]... Clear the Negative Trust Anchor for DOMAINs, if no DOMAIN is specified, remove all\n"
331bcdd5 1654"clear-ta [DOMAIN]... Clear the Trust Anchor for DOMAINs\n"
8e139df6 1655"dump-cache <filename> dump cache contents to the named file\n"
7194cb64 1656"dump-edns [status] <filename> dump EDNS status to the named file\n"
a82ce718 1657"dump-nsspeeds <filename> dump nsspeeds statistics to the named file\n"
6791663c 1658"dump-rpz <zone name> <filename> dump the content of a RPZ zone to the named file\n"
60e5208a
OM
1659"dump-throttlemap <filename> dump the contents of the throttle map to the named file\n"
1660"dump-failedservers <filename> dump the failed servers to the named file\n"
8e139df6
PD
1661"get [key1] [key2] .. get specific statistics\n"
1662"get-all get all statistics\n"
0c366a8e
PL
1663"get-dont-throttle-names get the list of names that are not allowed to be throttled\n"
1664"get-dont-throttle-netmasks get the list of netmasks that are not allowed to be throttled\n"
a38ab818 1665"get-ntas get all configured Negative Trust Anchors\n"
331bcdd5 1666"get-tas get all configured Trust Anchors\n"
8e139df6 1667"get-parameter [key1] [key2] .. get configuration parameters\n"
09425ce1
F
1668"get-qtypelist get QType statistics\n"
1669" notice: queries from cache aren't being counted yet\n"
8e139df6
PD
1670"help get this list\n"
1671"ping check that all threads are alive\n"
1672"quit stop the recursor daemon\n"
1673"quit-nicely stop the recursor daemon nicely\n"
1674"reload-acls reload ACLS\n"
1675"reload-lua-script [filename] (re)load Lua script\n"
6566fdfb 1676"reload-lua-config [filename] (re)load Lua configuration file\n"
8e139df6 1677"reload-zones reload all auth and forward zones\n"
5cf4b2e7 1678"set-ecs-minimum-ttl value set ecs-minimum-ttl-override\n"
5c626f00 1679"set-max-cache-entries value set new maximum cache size\n"
1680"set-max-packetcache-entries val set new maximum packet cache size\n"
2d2ee81e 1681"set-minimum-ttl value set minimum-ttl-override\n"
77a6fa66 1682"set-carbon-server set a carbon server for telemetry\n"
c87e1876 1683"set-dnssec-log-bogus SETTING enable (SETTING=yes) or disable (SETTING=no) logging of DNSSEC validation failures\n"
f76254e8 1684"trace-regex [regex] emit resolution trace for matching queries (empty regex to clear trace)\n"
92011b8f 1685"top-largeanswer-remotes show top remotes receiving large answers\n"
1686"top-queries show top queries\n"
331e84ec 1687"top-pub-queries show top queries grouped by public suffix list\n"
8e139df6 1688"top-remotes show top remotes\n"
6bc69980 1689"top-timeouts show top downstream timeouts\n"
92011b8f 1690"top-servfail-queries show top queries receiving servfail answers\n"
66f2e6ad 1691"top-bogus-queries show top queries validating as bogus\n"
331e84ec 1692"top-pub-servfail-queries show top queries receiving servfail answers grouped by public suffix list\n"
66f2e6ad 1693"top-pub-bogus-queries show top queries validating as bogus grouped by public suffix list\n"
92011b8f 1694"top-servfail-remotes show top remotes receiving servfail answers\n"
66f2e6ad 1695"top-bogus-remotes show top remotes receiving bogus answers\n"
8e139df6 1696"unload-lua-script unload Lua script\n"
6121a2ee 1697"version return Recursor version number\n"
2087df40
OM
1698"wipe-cache domain0 [domain1] .. wipe domain data from cache\n"
1699"wipe-cache-typed type domain0 [domain1] .. wipe domain data with qtype from cache\n";
8e139df6 1700
aadbe056
BH
1701 if(cmd=="get-all")
1702 return getAllStats();
1703
6791663c 1704 if(cmd=="get")
1d5b3ce6 1705 return doGet(begin, end);
6791663c
RG
1706
1707 if(cmd=="get-parameter")
f6ef9d7b
BH
1708 return doGetParameter(begin, end);
1709
aaacf7f2
BH
1710 if(cmd=="quit") {
1711 *command=&doExit;
1712 return "bye\n";
1713 }
6121a2ee 1714
1715 if(cmd=="version") {
77b9f5ff 1716 return getPDNSVersion()+"\n";
6121a2ee 1717 }
6791663c 1718
bb4bdbaf
BH
1719 if(cmd=="quit-nicely") {
1720 *command=&doExitNicely;
1721 return "bye nicely\n";
6791663c 1722 }
748eff9f 1723
6791663c 1724 if(cmd=="dump-cache")
748eff9f
BH
1725 return doDumpCache(begin, end);
1726
6791663c 1727 if(cmd=="dump-ednsstatus" || cmd=="dump-edns")
ff1872cf
BH
1728 return doDumpEDNSStatus(begin, end);
1729
a82ce718
PD
1730 if(cmd=="dump-nsspeeds")
1731 return doDumpNSSpeeds(begin, end);
1732
60e5208a
OM
1733 if(cmd=="dump-failedservers")
1734 return doDumpFailedServers(begin, end);
1735
6791663c
RG
1736 if(cmd=="dump-rpz") {
1737 return doDumpRPZ(begin, end);
1738 }
1739
c1e20fba 1740 if(cmd=="dump-throttlemap")
1741 return doDumpThrottleMap(begin, end);
1742
6791663c 1743 if(cmd=="wipe-cache" || cmd=="flushname")
2087df40
OM
1744 return doWipeCache(begin, end, 0xffff);
1745
1746 if(cmd=="wipe-cache-typed") {
1747 uint16_t qtype = QType::chartocode(begin->c_str());
1748 ++begin;
1749 return doWipeCache(begin, end, qtype);
1750 }
a9af3782 1751
6791663c 1752 if(cmd=="reload-lua-script")
674cf0f6 1753 return doQueueReloadLuaScript(begin, end);
4485aa35 1754
6566fdfb
PL
1755 if(cmd=="reload-lua-config") {
1756 if(begin != end)
1757 ::arg().set("lua-config-file") = *begin;
1758
1759 try {
e6ec15bf
RG
1760 luaConfigDelayedThreads delayedLuaThreads;
1761 loadRecursorLuaConfig(::arg()["lua-config-file"], delayedLuaThreads);
1762 startLuaConfigDelayedThreads(delayedLuaThreads, g_luaconfs.getCopy().generation);
e6a9dde5 1763 g_log<<Logger::Warning<<"Reloaded Lua configuration file '"<<::arg()["lua-config-file"]<<"', requested via control channel"<<endl;
6566fdfb
PL
1764 return "Reloaded Lua configuration file '"+::arg()["lua-config-file"]+"'\n";
1765 }
1766 catch(std::exception& e) {
1767 return "Unable to load Lua script from '"+::arg()["lua-config-file"]+"': "+e.what()+"\n";
1768 }
1769 catch(const PDNSException& e) {
1770 return "Unable to load Lua script from '"+::arg()["lua-config-file"]+"': "+e.reason+"\n";
1771 }
1772 }
1773
6791663c 1774 if(cmd=="set-carbon-server")
77a6fa66 1775 return doSetCarbonServer(begin, end);
1776
6791663c 1777 if(cmd=="trace-regex")
77499b05
BH
1778 return doTraceRegex(begin, end);
1779
4485aa35
BH
1780 if(cmd=="unload-lua-script") {
1781 vector<string> empty;
1782 empty.push_back(string());
674cf0f6 1783 return doQueueReloadLuaScript(empty.begin(), empty.end());
4485aa35
BH
1784 }
1785
18af64a8 1786 if(cmd=="reload-acls") {
f0f3f0b0 1787 if(!::arg()["chroot"].empty()) {
e6a9dde5 1788 g_log<<Logger::Error<<"Unable to reload ACL when chroot()'ed, requested via control channel"<<endl;
f0f3f0b0
PL
1789 return "Unable to reload ACL when chroot()'ed, please restart\n";
1790 }
1791
18af64a8
BH
1792 try {
1793 parseACLs();
1794 }
18e7758c 1795 catch(std::exception& e)
18af64a8 1796 {
e6a9dde5 1797 g_log<<Logger::Error<<"Reloading ACLs failed (Exception: "<<e.what()<<")"<<endl;
18af64a8
BH
1798 return e.what() + string("\n");
1799 }
3f81d239 1800 catch(PDNSException& ae)
a97395cd 1801 {
e6a9dde5 1802 g_log<<Logger::Error<<"Reloading ACLs failed (PDNSException: "<<ae.reason<<")"<<endl;
a97395cd
PD
1803 return ae.reason + string("\n");
1804 }
18af64a8
BH
1805 return "ok\n";
1806 }
1807
4485aa35 1808
a9af3782 1809 if(cmd=="top-remotes")
92011b8f 1810 return doGenericTopRemotes(pleaseGetRemotes);
1811
1812 if(cmd=="top-queries")
1813 return doGenericTopQueries(pleaseGetQueryRing);
1814
1815 if(cmd=="top-pub-queries")
1816 return doGenericTopQueries(pleaseGetQueryRing, getRegisteredName);
1817
92011b8f 1818 if(cmd=="top-servfail-queries")
1819 return doGenericTopQueries(pleaseGetServfailQueryRing);
1820
1821 if(cmd=="top-pub-servfail-queries")
1822 return doGenericTopQueries(pleaseGetServfailQueryRing, getRegisteredName);
1823
66f2e6ad
KM
1824 if(cmd=="top-bogus-queries")
1825 return doGenericTopQueries(pleaseGetBogusQueryRing);
1826
1827 if(cmd=="top-pub-bogus-queries")
1828 return doGenericTopQueries(pleaseGetBogusQueryRing, getRegisteredName);
1829
92011b8f 1830
1831 if(cmd=="top-servfail-remotes")
1832 return doGenericTopRemotes(pleaseGetServfailRemotes);
1833
66f2e6ad
KM
1834 if(cmd=="top-bogus-remotes")
1835 return doGenericTopRemotes(pleaseGetBogusRemotes);
1836
92011b8f 1837 if(cmd=="top-largeanswer-remotes")
1838 return doGenericTopRemotes(pleaseGetLargeAnswerRemotes);
1839
621ccf89 1840 if(cmd=="top-timeouts")
1841 return doGenericTopRemotes(pleaseGetTimeouts);
1842
ffb584a9 1843
d2392145
BH
1844 if(cmd=="current-queries")
1845 return doCurrentQueries();
1846
bb4bdbaf 1847 if(cmd=="ping") {
3427fa8a 1848 return broadcastAccFunction<string>(nopFunction);
bb4bdbaf 1849 }
1d5b3ce6 1850
ee1ada80 1851 if(cmd=="reload-zones") {
f0f3f0b0 1852 if(!::arg()["chroot"].empty()) {
e6a9dde5 1853 g_log<<Logger::Error<<"Unable to reload zones and forwards when chroot()'ed, requested via control channel"<<endl;
f0f3f0b0
PL
1854 return "Unable to reload zones and forwards when chroot()'ed, please restart\n";
1855 }
ee1ada80
BH
1856 return reloadAuthAndForwards();
1857 }
aadceba8 1858
5cf4b2e7
RG
1859 if(cmd=="set-ecs-minimum-ttl") {
1860 return setMinimumECSTTL(begin, end);
1861 }
1862
a6f7f5fe 1863 if(cmd=="set-max-cache-entries") {
1864 return setMaxCacheEntries(begin, end);
1865 }
1866 if(cmd=="set-max-packetcache-entries") {
1867 return setMaxPacketCacheEntries(begin, end);
1868 }
1869
aadceba8 1870 if(cmd=="set-minimum-ttl") {
1871 return setMinimumTTL(begin, end);
1872 }
0bbf7d0a 1873
79332bff 1874 if(cmd=="get-qtypelist") {
09425ce1 1875 return g_rs.getQTypeReport();
79332bff 1876 }
a38ab818
PL
1877
1878 if(cmd=="add-nta") {
1879 return doAddNTA(begin, end);
1880 }
1881
1882 if(cmd=="clear-nta") {
1883 return doClearNTA(begin, end);
1884 }
1885
1886 if(cmd=="get-ntas") {
1887 return getNTAs();
1888 }
331bcdd5
PL
1889
1890 if(cmd=="add-ta") {
1891 return doAddTA(begin, end);
1892 }
1893
1894 if(cmd=="clear-ta") {
1895 return doClearTA(begin, end);
1896 }
1897
1898 if(cmd=="get-tas") {
1899 return getTAs();
1900 }
c87e1876
PL
1901
1902 if (cmd=="set-dnssec-log-bogus")
1903 return doSetDnssecLogBogus(begin, end);
1904
0c366a8e
PL
1905 if (cmd == "get-dont-throttle-names") {
1906 return getDontThrottleNames();
1907 }
1908
1909 if (cmd == "get-dont-throttle-netmasks") {
1910 return getDontThrottleNetmasks();
1911 }
1912
c4ce5418
PL
1913 if (cmd == "add-dont-throttle-names") {
1914 return addDontThrottleNames(begin, end);
1915 }
1916
1917 if (cmd == "add-dont-throttle-netmasks") {
1918 return addDontThrottleNetmasks(begin, end);
1919 }
1920
fa7cc8af
PL
1921 if (cmd == "clear-dont-throttle-names") {
1922 return clearDontThrottleNames(begin, end);
1923 }
1924
1925 if (cmd == "clear-dont-throttle-netmasks") {
1926 return clearDontThrottleNetmasks(begin, end);
1927 }
1928
8e139df6 1929 return "Unknown command '"+cmd+"', try 'help'\n";
1d5b3ce6 1930}