]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/rec_channel_rec.cc
Merge pull request #7496 from rgacogne/auth-catch-invalid-slave-soa
[thirdparty/pdns.git] / pdns / rec_channel_rec.cc
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 #include "utility.hh"
5 #include "rec_channel.hh"
6 #include <boost/bind.hpp>
7 #include <vector>
8 #ifdef MALLOC_TRACE
9 #include "malloctrace.hh"
10 #endif
11 #include "misc.hh"
12 #include "recursor_cache.hh"
13 #include "syncres.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>
20
21 #include "version.hh"
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include "logger.hh"
26 #include "dnsparser.hh"
27 #include "arguments.hh"
28 #include <sys/resource.h>
29 #include <sys/time.h>
30 #include "lock.hh"
31 #include "responsestats.hh"
32 #include "rec-lua-conf.hh"
33
34 #include "validate-recursor.hh"
35 #include "filterpo.hh"
36
37 #include "secpoll-recursor.hh"
38 #include "pubsuffix.hh"
39 #include "namespaces.hh"
40 pthread_mutex_t g_carbon_config_lock=PTHREAD_MUTEX_INITIALIZER;
41
42 static map<string, const uint32_t*> d_get32bitpointers;
43 static map<string, const uint64_t*> d_get64bitpointers;
44 static map<string, const std::atomic<uint64_t>*> d_getatomics;
45 static map<string, function< uint64_t() > > d_get64bitmembers;
46 static pthread_mutex_t d_dynmetricslock = PTHREAD_MUTEX_INITIALIZER;
47 static map<string, std::atomic<unsigned long>* > d_dynmetrics;
48
49 static void addGetStat(const string& name, const uint32_t* place)
50 {
51 d_get32bitpointers[name]=place;
52 }
53
54 static void addGetStat(const string& name, const std::atomic<uint64_t>* place)
55 {
56 d_getatomics[name]=place;
57 }
58
59 static void addGetStat(const string& name, function<uint64_t ()> f )
60 {
61 d_get64bitmembers[name]=f;
62 }
63
64 std::atomic<unsigned long>* getDynMetric(const std::string& str)
65 {
66 Lock l(&d_dynmetricslock);
67 auto f = d_dynmetrics.find(str);
68 if(f != d_dynmetrics.end())
69 return f->second;
70
71 auto ret = new std::atomic<unsigned long>();
72 d_dynmetrics[str]= ret;
73 return ret;
74 }
75
76 static optional<uint64_t> get(const string& name)
77 {
78 optional<uint64_t> ret;
79
80 if(d_get32bitpointers.count(name))
81 return *d_get32bitpointers.find(name)->second;
82 if(d_get64bitpointers.count(name))
83 return *d_get64bitpointers.find(name)->second;
84 if(d_getatomics.count(name))
85 return d_getatomics.find(name)->second->load();
86 if(d_get64bitmembers.count(name))
87 return d_get64bitmembers.find(name)->second();
88
89 Lock l(&d_dynmetricslock);
90 auto f =rplookup(d_dynmetrics, name);
91 if(f)
92 return (*f)->load();
93
94 return ret;
95 }
96
97 optional<uint64_t> getStatByName(const std::string& name)
98 {
99 return get(name);
100 }
101
102 map<string,string> getAllStatsMap()
103 {
104 map<string,string> ret;
105
106 for(const auto& the32bits : d_get32bitpointers) {
107 ret.insert(make_pair(the32bits.first, std::to_string(*the32bits.second)));
108 }
109 for(const auto& the64bits : d_get64bitpointers) {
110 ret.insert(make_pair(the64bits.first, std::to_string(*the64bits.second)));
111 }
112 for(const auto& atomic : d_getatomics) {
113 ret.insert(make_pair(atomic.first, std::to_string(atomic.second->load())));
114 }
115
116 for(const auto& the64bitmembers : d_get64bitmembers) {
117 if(the64bitmembers.first == "cache-bytes" || the64bitmembers.first=="packetcache-bytes")
118 continue; // too slow for 'get-all'
119 if(the64bitmembers.first == "special-memory-usage")
120 continue; // too slow for 'get-all'
121 ret.insert(make_pair(the64bitmembers.first, std::to_string(the64bitmembers.second())));
122 }
123 Lock l(&d_dynmetricslock);
124 for(const auto& a : d_dynmetrics)
125 ret.insert({a.first, std::to_string(*a.second)});
126 return ret;
127 }
128
129 string getAllStats()
130 {
131 typedef map<string, string> varmap_t;
132 varmap_t varmap = getAllStatsMap();
133 string ret;
134 for(varmap_t::value_type& tup : varmap) {
135 ret += tup.first + "\t" + tup.second +"\n";
136 }
137 return ret;
138 }
139
140 template<typename T>
141 string doGet(T begin, T end)
142 {
143 string ret;
144
145 for(T i=begin; i != end; ++i) {
146 optional<uint64_t> num=get(*i);
147 if(num)
148 ret+=std::to_string(*num)+"\n";
149 else
150 ret+="UNKNOWN\n";
151 }
152 return ret;
153 }
154
155 template<typename T>
156 string doGetParameter(T begin, T end)
157 {
158 string ret;
159 string parm;
160 using boost::replace_all;
161 for(T i=begin; i != end; ++i) {
162 if(::arg().parmIsset(*i)) {
163 parm=::arg()[*i];
164 replace_all(parm, "\\", "\\\\");
165 replace_all(parm, "\"", "\\\"");
166 replace_all(parm, "\n", "\\n");
167 ret += *i +"=\""+ parm +"\"\n";
168 }
169 else
170 ret += *i +" not known\n";
171 }
172 return ret;
173 }
174
175
176 static uint64_t dumpNegCache(NegCache& negcache, int fd)
177 {
178 auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fdopen(dup(fd), "w"), fclose);
179 if(!fp) { // dup probably failed
180 return 0;
181 }
182 uint64_t ret;
183 fprintf(fp.get(), "; negcache dump from thread follows\n;\n");
184 ret = negcache.dumpToFile(fp.get());
185 return ret;
186 }
187
188 static uint64_t* pleaseDump(int fd)
189 {
190 return new uint64_t(t_RC->doDump(fd) + dumpNegCache(SyncRes::t_sstorage.negcache, fd) + t_packetCache->doDump(fd));
191 }
192
193 static uint64_t* pleaseDumpEDNSMap(int fd)
194 {
195 return new uint64_t(SyncRes::doEDNSDump(fd));
196 }
197
198 static uint64_t* pleaseDumpNSSpeeds(int fd)
199 {
200 return new uint64_t(SyncRes::doDumpNSSpeeds(fd));
201 }
202
203 static uint64_t* pleaseDumpThrottleMap(int fd)
204 {
205 return new uint64_t(SyncRes::doDumpThrottleMap(fd));
206 }
207
208 template<typename T>
209 string doDumpNSSpeeds(T begin, T end)
210 {
211 T i=begin;
212 string fname;
213
214 if(i!=end)
215 fname=*i;
216
217 int fd=open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660);
218 if(fd < 0)
219 return "Error opening dump file for writing: "+string(strerror(errno))+"\n";
220 uint64_t total = 0;
221 try {
222 total = broadcastAccFunction<uint64_t>(boost::bind(pleaseDumpNSSpeeds, fd));
223 }
224 catch(std::exception& e)
225 {
226 close(fd);
227 return "error dumping NS speeds: "+string(e.what())+"\n";
228 }
229 catch(PDNSException& e)
230 {
231 close(fd);
232 return "error dumping NS speeds: "+e.reason+"\n";
233 }
234
235 close(fd);
236 return "dumped "+std::to_string(total)+" records\n";
237 }
238
239 template<typename T>
240 string doDumpCache(T begin, T end)
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)
250 return "Error opening dump file for writing: "+string(strerror(errno))+"\n";
251 uint64_t total = 0;
252 try {
253 total = broadcastAccFunction<uint64_t>(boost::bind(pleaseDump, fd));
254 }
255 catch(...){}
256
257 close(fd);
258 return "dumped "+std::to_string(total)+" records\n";
259 }
260
261 template<typename T>
262 string doDumpEDNSStatus(T begin, T end)
263 {
264 T i=begin;
265 string fname;
266
267 if(i!=end)
268 fname=*i;
269
270 int fd=open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660);
271 if(fd < 0)
272 return "Error opening dump file for writing: "+string(strerror(errno))+"\n";
273 uint64_t total = 0;
274 try {
275 total = broadcastAccFunction<uint64_t>(boost::bind(pleaseDumpEDNSMap, fd));
276 }
277 catch(...){}
278
279 close(fd);
280 return "dumped "+std::to_string(total)+" records\n";
281 }
282
283 template<typename T>
284 string doDumpRPZ(T begin, T end)
285 {
286 T i=begin;
287
288 if (i == end) {
289 return "No zone name specified\n";
290 }
291 string zoneName = *i;
292 i++;
293
294 if (i == end) {
295 return "No file name specified\n";
296 }
297 string fname = *i;
298
299 auto luaconf = g_luaconfs.getLocal();
300 const auto zone = luaconf->dfe.getZone(zoneName);
301 if (!zone) {
302 return "No RPZ zone named "+zoneName+"\n";
303 }
304
305 int fd = open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660);
306
307 if(fd < 0) {
308 return "Error opening dump file for writing: "+string(strerror(errno))+"\n";
309 }
310
311 auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fdopen(fd, "w"), fclose);
312 if (!fp) {
313 close(fd);
314 return "Error converting file descriptor: "+string(strerror(errno))+"\n";
315 }
316
317 zone->dump(fp.get());
318
319 return "done\n";
320 }
321
322 template<typename T>
323 string doDumpThrottleMap(T begin, T end)
324 {
325 T i=begin;
326 string fname;
327
328 if(i!=end)
329 fname=*i;
330
331 int fd=open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660);
332 if(fd < 0)
333 return "Error opening dump file for writing: "+string(strerror(errno))+"\n";
334 uint64_t total = 0;
335 try {
336 total = broadcastAccFunction<uint64_t>(boost::bind(pleaseDumpThrottleMap, fd));
337 }
338 catch(...){}
339
340 close(fd);
341 return "dumped "+std::to_string(total)+" records\n";
342 }
343
344 uint64_t* pleaseWipeCache(const DNSName& canon, bool subtree)
345 {
346 return new uint64_t(t_RC->doWipeCache(canon, subtree));
347 }
348
349 uint64_t* pleaseWipePacketCache(const DNSName& canon, bool subtree)
350 {
351 return new uint64_t(t_packetCache->doWipePacketCache(canon,0xffff, subtree));
352 }
353
354
355 uint64_t* pleaseWipeAndCountNegCache(const DNSName& canon, bool subtree)
356 {
357 uint64_t ret = SyncRes::wipeNegCache(canon, subtree);
358 return new uint64_t(ret);
359 }
360
361
362 template<typename T>
363 string doWipeCache(T begin, T end)
364 {
365 vector<pair<DNSName, bool> > toWipe;
366 for(T i=begin; i != end; ++i) {
367 DNSName canon;
368 bool subtree=false;
369
370 try {
371 if(boost::ends_with(*i, "$")) {
372 canon=DNSName(i->substr(0, i->size()-1));
373 subtree=true;
374 } else {
375 canon=DNSName(*i);
376 }
377 } catch (std::exception &e) {
378 return "Error: " + std::string(e.what()) + ", nothing wiped\n";
379 }
380 toWipe.push_back({canon, subtree});
381 }
382
383 int count=0, pcount=0, countNeg=0;
384 for (auto wipe : toWipe) {
385 count+= broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, wipe.first, wipe.second));
386 pcount+= broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, wipe.first, wipe.second));
387 countNeg+=broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, wipe.first, wipe.second));
388 }
389
390 return "wiped "+std::to_string(count)+" records, "+std::to_string(countNeg)+" negative records, "+std::to_string(pcount)+" packets\n";
391 }
392
393 template<typename T>
394 string doSetCarbonServer(T begin, T end)
395 {
396 Lock l(&g_carbon_config_lock);
397 if(begin==end) {
398 ::arg().set("carbon-server").clear();
399 return "cleared carbon-server setting\n";
400 }
401 string ret;
402 ::arg().set("carbon-server")=*begin;
403 ret="set carbon-server to '"+::arg()["carbon-server"]+"'\n";
404 ++begin;
405 if(begin != end) {
406 ::arg().set("carbon-ourname")=*begin;
407 ret+="set carbon-ourname to '"+*begin+"'\n";
408 } else {
409 return ret;
410 }
411 ++begin;
412 if(begin != end) {
413 ::arg().set("carbon-namespace")=*begin;
414 ret+="set carbon-namespace to '"+*begin+"'\n";
415 } else {
416 return ret;
417 }
418 ++begin;
419 if(begin != end) {
420 ::arg().set("carbon-instance")=*begin;
421 ret+="set carbon-instance to '"+*begin+"'\n";
422 }
423 return ret;
424 }
425
426 template<typename T>
427 string doSetDnssecLogBogus(T begin, T end)
428 {
429 if(checkDNSSECDisabled())
430 return "DNSSEC is disabled in the configuration, not changing the Bogus logging setting\n";
431
432 if (begin == end)
433 return "No DNSSEC Bogus logging setting specified\n";
434
435 if (pdns_iequals(*begin, "on") || pdns_iequals(*begin, "yes")) {
436 if (!g_dnssecLogBogus) {
437 g_log<<Logger::Warning<<"Enabling DNSSEC Bogus logging, requested via control channel"<<endl;
438 g_dnssecLogBogus = true;
439 return "DNSSEC Bogus logging enabled\n";
440 }
441 return "DNSSEC Bogus logging was already enabled\n";
442 }
443
444 if (pdns_iequals(*begin, "off") || pdns_iequals(*begin, "no")) {
445 if (g_dnssecLogBogus) {
446 g_log<<Logger::Warning<<"Disabling DNSSEC Bogus logging, requested via control channel"<<endl;
447 g_dnssecLogBogus = false;
448 return "DNSSEC Bogus logging disabled\n";
449 }
450 return "DNSSEC Bogus logging was already disabled\n";
451 }
452
453 return "Unknown DNSSEC Bogus setting: '" + *begin +"'\n";
454 }
455
456 template<typename T>
457 string doAddNTA(T begin, T end)
458 {
459 if(checkDNSSECDisabled())
460 return "DNSSEC is disabled in the configuration, not adding a Negative Trust Anchor\n";
461
462 if(begin == end)
463 return "No NTA specified, doing nothing\n";
464
465 DNSName who;
466 try {
467 who = DNSName(*begin);
468 }
469 catch(std::exception &e) {
470 string ret("Can't add Negative Trust Anchor: ");
471 ret += e.what();
472 ret += "\n";
473 return ret;
474 }
475 begin++;
476
477 string why("");
478 while (begin != end) {
479 why += *begin;
480 begin++;
481 if (begin != end)
482 why += " ";
483 }
484 g_log<<Logger::Warning<<"Adding Negative Trust Anchor for "<<who<<" with reason '"<<why<<"', requested via control channel"<<endl;
485 g_luaconfs.modify([who, why](LuaConfigItems& lci) {
486 lci.negAnchors[who] = why;
487 });
488 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, who, true));
489 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, who, true));
490 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, who, true));
491 return "Added Negative Trust Anchor for " + who.toLogString() + " with reason '" + why + "'\n";
492 }
493
494 template<typename T>
495 string doClearNTA(T begin, T end)
496 {
497 if(checkDNSSECDisabled())
498 return "DNSSEC is disabled in the configuration, not removing a Negative Trust Anchor\n";
499
500 if(begin == end)
501 return "No Negative Trust Anchor specified, doing nothing.\n";
502
503 if (begin + 1 == end && *begin == "*"){
504 g_log<<Logger::Warning<<"Clearing all Negative Trust Anchors, requested via control channel"<<endl;
505 g_luaconfs.modify([](LuaConfigItems& lci) {
506 lci.negAnchors.clear();
507 });
508 return "Cleared all Negative Trust Anchors.\n";
509 }
510
511 vector<DNSName> toRemove;
512 DNSName who;
513 while (begin != end) {
514 if (*begin == "*")
515 return "Don't mix all Negative Trust Anchor removal with multiple Negative Trust Anchor removal. Nothing removed\n";
516 try {
517 who = DNSName(*begin);
518 }
519 catch(std::exception &e) {
520 string ret("Error: ");
521 ret += e.what();
522 ret += ". No Negative Anchors removed\n";
523 return ret;
524 }
525 toRemove.push_back(who);
526 begin++;
527 }
528
529 string removed("");
530 bool first(true);
531 for (auto const &entry : toRemove) {
532 g_log<<Logger::Warning<<"Clearing Negative Trust Anchor for "<<entry<<", requested via control channel"<<endl;
533 g_luaconfs.modify([entry](LuaConfigItems& lci) {
534 lci.negAnchors.erase(entry);
535 });
536 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, entry, true));
537 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, entry, true));
538 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, entry, true));
539 if (!first) {
540 first = false;
541 removed += ",";
542 }
543 removed += " " + entry.toStringRootDot();
544 }
545 return "Removed Negative Trust Anchors for " + removed + "\n";
546 }
547
548 static string getNTAs()
549 {
550 if(checkDNSSECDisabled())
551 return "DNSSEC is disabled in the configuration\n";
552
553 string ret("Configured Negative Trust Anchors:\n");
554 auto luaconf = g_luaconfs.getLocal();
555 for (auto negAnchor : luaconf->negAnchors)
556 ret += negAnchor.first.toLogString() + "\t" + negAnchor.second + "\n";
557 return ret;
558 }
559
560 template<typename T>
561 string doAddTA(T begin, T end)
562 {
563 if(checkDNSSECDisabled())
564 return "DNSSEC is disabled in the configuration, not adding a Trust Anchor\n";
565
566 if(begin == end)
567 return "No TA specified, doing nothing\n";
568
569 DNSName who;
570 try {
571 who = DNSName(*begin);
572 }
573 catch(std::exception &e) {
574 string ret("Can't add Trust Anchor: ");
575 ret += e.what();
576 ret += "\n";
577 return ret;
578 }
579 begin++;
580
581 string what("");
582 while (begin != end) {
583 what += *begin + " ";
584 begin++;
585 }
586
587 try {
588 g_log<<Logger::Warning<<"Adding Trust Anchor for "<<who<<" with data '"<<what<<"', requested via control channel";
589 g_luaconfs.modify([who, what](LuaConfigItems& lci) {
590 auto ds=std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(what));
591 lci.dsAnchors[who].insert(*ds);
592 });
593 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, who, true));
594 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, who, true));
595 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, who, true));
596 g_log<<Logger::Warning<<endl;
597 return "Added Trust Anchor for " + who.toStringRootDot() + " with data " + what + "\n";
598 }
599 catch(std::exception &e) {
600 g_log<<Logger::Warning<<", failed: "<<e.what()<<endl;
601 return "Unable to add Trust Anchor for " + who.toStringRootDot() + ": " + e.what() + "\n";
602 }
603 }
604
605 template<typename T>
606 string doClearTA(T begin, T end)
607 {
608 if(checkDNSSECDisabled())
609 return "DNSSEC is disabled in the configuration, not removing a Trust Anchor\n";
610
611 if(begin == end)
612 return "No Trust Anchor to clear\n";
613
614 vector<DNSName> toRemove;
615 DNSName who;
616 while (begin != end) {
617 try {
618 who = DNSName(*begin);
619 }
620 catch(std::exception &e) {
621 string ret("Error: ");
622 ret += e.what();
623 ret += ". No Anchors removed\n";
624 return ret;
625 }
626 if (who.isRoot())
627 return "Refusing to remove root Trust Anchor, no Anchors removed\n";
628 toRemove.push_back(who);
629 begin++;
630 }
631
632 string removed("");
633 bool first(true);
634 for (auto const &entry : toRemove) {
635 g_log<<Logger::Warning<<"Removing Trust Anchor for "<<entry<<", requested via control channel"<<endl;
636 g_luaconfs.modify([entry](LuaConfigItems& lci) {
637 lci.dsAnchors.erase(entry);
638 });
639 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, entry, true));
640 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, entry, true));
641 broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, entry, true));
642 if (!first) {
643 first = false;
644 removed += ",";
645 }
646 removed += " " + entry.toStringRootDot();
647 }
648 return "Removed Trust Anchor(s) for" + removed + "\n";
649 }
650
651 static string getTAs()
652 {
653 if(checkDNSSECDisabled())
654 return "DNSSEC is disabled in the configuration\n";
655
656 string ret("Configured Trust Anchors:\n");
657 auto luaconf = g_luaconfs.getLocal();
658 for (auto anchor : luaconf->dsAnchors) {
659 ret += anchor.first.toLogString() + "\n";
660 for (auto e : anchor.second) {
661 ret+="\t\t"+e.getZoneRepresentation() + "\n";
662 }
663 }
664
665 return ret;
666 }
667
668 template<typename T>
669 string setMinimumTTL(T begin, T end)
670 {
671 if(end-begin != 1)
672 return "Need to supply new minimum TTL number\n";
673 SyncRes::s_minimumTTL = pdns_stou(*begin);
674 return "New minimum TTL: " + std::to_string(SyncRes::s_minimumTTL) + "\n";
675 }
676
677 template<typename T>
678 string setMaxCacheEntries(T begin, T end)
679 {
680 if(end-begin != 1)
681 return "Need to supply new cache size\n";
682 g_maxCacheEntries = pdns_stou(*begin);
683 return "New max cache entries: " + std::to_string(g_maxCacheEntries) + "\n";
684 }
685
686 template<typename T>
687 string setMaxPacketCacheEntries(T begin, T end)
688 {
689 if(end-begin != 1)
690 return "Need to supply new packet cache size\n";
691 g_maxPacketCacheEntries = pdns_stou(*begin);
692 return "New max packetcache entries: " + std::to_string(g_maxPacketCacheEntries) + "\n";
693 }
694
695
696 static uint64_t getSysTimeMsec()
697 {
698 struct rusage ru;
699 getrusage(RUSAGE_SELF, &ru);
700 return (ru.ru_stime.tv_sec*1000ULL + ru.ru_stime.tv_usec/1000);
701 }
702
703 static uint64_t getUserTimeMsec()
704 {
705 struct rusage ru;
706 getrusage(RUSAGE_SELF, &ru);
707 return (ru.ru_utime.tv_sec*1000ULL + ru.ru_utime.tv_usec/1000);
708 }
709
710 static uint64_t calculateUptime()
711 {
712 return time(0) - g_stats.startupTime;
713 }
714
715 static string* pleaseGetCurrentQueries()
716 {
717 ostringstream ostr;
718 struct timeval now;
719 gettimeofday(&now, 0);
720
721 ostr << getMT()->d_waiters.size() <<" currently outstanding questions\n";
722
723 boost::format fmt("%1% %|40t|%2% %|47t|%3% %|63t|%4% %|68t|%5% %|78t|%6%\n");
724
725 ostr << (fmt % "qname" % "qtype" % "remote" % "tcp" % "chained" % "spent(ms)");
726 unsigned int n=0;
727 for(const auto& mthread : getMT()->d_waiters) {
728 const PacketID& pident = mthread.key;
729 const double spent = g_networkTimeoutMsec - (DiffTime(now, mthread.ttd) * 1000);
730 ostr << (fmt
731 % pident.domain.toLogString() /* ?? */ % DNSRecordContent::NumberToType(pident.type)
732 % pident.remote.toString() % (pident.sock ? 'Y' : 'n')
733 % (pident.fd == -1 ? 'Y' : 'n')
734 % (spent > 0 ? spent : '0')
735 );
736 ++n;
737 if (n >= 100)
738 break;
739 }
740 ostr <<" - done\n";
741 return new string(ostr.str());
742 }
743
744 static string doCurrentQueries()
745 {
746 return broadcastAccFunction<string>(pleaseGetCurrentQueries);
747 }
748
749 uint64_t* pleaseGetThrottleSize()
750 {
751 return new uint64_t(SyncRes::getThrottledServersSize());
752 }
753
754 static uint64_t getThrottleSize()
755 {
756 return broadcastAccFunction<uint64_t>(pleaseGetThrottleSize);
757 }
758
759 uint64_t* pleaseGetNegCacheSize()
760 {
761 uint64_t tmp=(SyncRes::getNegCacheSize());
762 return new uint64_t(tmp);
763 }
764
765 uint64_t getNegCacheSize()
766 {
767 return broadcastAccFunction<uint64_t>(pleaseGetNegCacheSize);
768 }
769
770 uint64_t* pleaseGetFailedHostsSize()
771 {
772 uint64_t tmp=(SyncRes::getThrottledServersSize());
773 return new uint64_t(tmp);
774 }
775 uint64_t getFailedHostsSize()
776 {
777 return broadcastAccFunction<uint64_t>(pleaseGetFailedHostsSize);
778 }
779
780 uint64_t* pleaseGetNsSpeedsSize()
781 {
782 return new uint64_t(SyncRes::getNSSpeedsSize());
783 }
784
785 uint64_t getNsSpeedsSize()
786 {
787 return broadcastAccFunction<uint64_t>(pleaseGetNsSpeedsSize);
788 }
789
790 uint64_t* pleaseGetConcurrentQueries()
791 {
792 return new uint64_t(getMT() ? getMT()->numProcesses() : 0);
793 }
794
795 static uint64_t getConcurrentQueries()
796 {
797 return broadcastAccFunction<uint64_t>(pleaseGetConcurrentQueries);
798 }
799
800 uint64_t* pleaseGetCacheSize()
801 {
802 return new uint64_t(t_RC ? t_RC->size() : 0);
803 }
804
805 uint64_t* pleaseGetCacheBytes()
806 {
807 return new uint64_t(t_RC ? t_RC->bytes() : 0);
808 }
809
810
811 uint64_t doGetCacheSize()
812 {
813 return broadcastAccFunction<uint64_t>(pleaseGetCacheSize);
814 }
815
816 uint64_t doGetAvgLatencyUsec()
817 {
818 return (uint64_t) g_stats.avgLatencyUsec;
819 }
820
821
822 uint64_t doGetCacheBytes()
823 {
824 return broadcastAccFunction<uint64_t>(pleaseGetCacheBytes);
825 }
826
827 uint64_t* pleaseGetCacheHits()
828 {
829 return new uint64_t(t_RC ? t_RC->cacheHits : 0);
830 }
831
832 uint64_t doGetCacheHits()
833 {
834 return broadcastAccFunction<uint64_t>(pleaseGetCacheHits);
835 }
836
837 uint64_t* pleaseGetCacheMisses()
838 {
839 return new uint64_t(t_RC ? t_RC->cacheMisses : 0);
840 }
841
842 uint64_t doGetCacheMisses()
843 {
844 return broadcastAccFunction<uint64_t>(pleaseGetCacheMisses);
845 }
846
847
848 uint64_t* pleaseGetPacketCacheSize()
849 {
850 return new uint64_t(t_packetCache ? t_packetCache->size() : 0);
851 }
852
853 uint64_t* pleaseGetPacketCacheBytes()
854 {
855 return new uint64_t(t_packetCache ? t_packetCache->bytes() : 0);
856 }
857
858
859 uint64_t doGetPacketCacheSize()
860 {
861 return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheSize);
862 }
863
864 uint64_t doGetPacketCacheBytes()
865 {
866 return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheBytes);
867 }
868
869
870 uint64_t* pleaseGetPacketCacheHits()
871 {
872 return new uint64_t(t_packetCache ? t_packetCache->d_hits : 0);
873 }
874
875 uint64_t doGetPacketCacheHits()
876 {
877 return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheHits);
878 }
879
880 uint64_t* pleaseGetPacketCacheMisses()
881 {
882 return new uint64_t(t_packetCache ? t_packetCache->d_misses : 0);
883 }
884
885 uint64_t doGetPacketCacheMisses()
886 {
887 return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheMisses);
888 }
889
890 uint64_t doGetMallocated()
891 {
892 // this turned out to be broken
893 /* struct mallinfo mi = mallinfo();
894 return mi.uordblks; */
895 return 0;
896 }
897
898 extern ResponseStats g_rs;
899
900 void registerAllStats()
901 {
902 static std::atomic_flag s_init = ATOMIC_FLAG_INIT;
903 if(s_init.test_and_set())
904 return;
905
906 addGetStat("questions", &g_stats.qcounter);
907 addGetStat("ipv6-questions", &g_stats.ipv6qcounter);
908 addGetStat("tcp-questions", &g_stats.tcpqcounter);
909
910 addGetStat("cache-hits", doGetCacheHits);
911 addGetStat("cache-misses", doGetCacheMisses);
912 addGetStat("cache-entries", doGetCacheSize);
913 addGetStat("max-cache-entries", []() { return g_maxCacheEntries.load(); });
914 addGetStat("max-packetcache-entries", []() { return g_maxPacketCacheEntries.load();});
915 addGetStat("cache-bytes", doGetCacheBytes);
916
917 addGetStat("packetcache-hits", doGetPacketCacheHits);
918 addGetStat("packetcache-misses", doGetPacketCacheMisses);
919 addGetStat("packetcache-entries", doGetPacketCacheSize);
920 addGetStat("packetcache-bytes", doGetPacketCacheBytes);
921
922 addGetStat("malloc-bytes", doGetMallocated);
923
924 addGetStat("servfail-answers", &g_stats.servFails);
925 addGetStat("nxdomain-answers", &g_stats.nxDomains);
926 addGetStat("noerror-answers", &g_stats.noErrors);
927
928 addGetStat("unauthorized-udp", &g_stats.unauthorizedUDP);
929 addGetStat("unauthorized-tcp", &g_stats.unauthorizedTCP);
930 addGetStat("tcp-client-overflow", &g_stats.tcpClientOverflow);
931
932 addGetStat("client-parse-errors", &g_stats.clientParseError);
933 addGetStat("server-parse-errors", &g_stats.serverParseError);
934 addGetStat("too-old-drops", &g_stats.tooOldDrops);
935 addGetStat("truncated-drops", &g_stats.truncatedDrops);
936 addGetStat("query-pipe-full-drops", &g_stats.queryPipeFullDrops);
937
938 addGetStat("answers0-1", &g_stats.answers0_1);
939 addGetStat("answers1-10", &g_stats.answers1_10);
940 addGetStat("answers10-100", &g_stats.answers10_100);
941 addGetStat("answers100-1000", &g_stats.answers100_1000);
942 addGetStat("answers-slow", &g_stats.answersSlow);
943
944 addGetStat("x-ourtime0-1", &g_stats.ourtime0_1);
945 addGetStat("x-ourtime1-2", &g_stats.ourtime1_2);
946 addGetStat("x-ourtime2-4", &g_stats.ourtime2_4);
947 addGetStat("x-ourtime4-8", &g_stats.ourtime4_8);
948 addGetStat("x-ourtime8-16", &g_stats.ourtime8_16);
949 addGetStat("x-ourtime16-32", &g_stats.ourtime16_32);
950 addGetStat("x-ourtime-slow", &g_stats.ourtimeSlow);
951
952 addGetStat("auth4-answers0-1", &g_stats.auth4Answers0_1);
953 addGetStat("auth4-answers1-10", &g_stats.auth4Answers1_10);
954 addGetStat("auth4-answers10-100", &g_stats.auth4Answers10_100);
955 addGetStat("auth4-answers100-1000", &g_stats.auth4Answers100_1000);
956 addGetStat("auth4-answers-slow", &g_stats.auth4AnswersSlow);
957
958 addGetStat("auth6-answers0-1", &g_stats.auth6Answers0_1);
959 addGetStat("auth6-answers1-10", &g_stats.auth6Answers1_10);
960 addGetStat("auth6-answers10-100", &g_stats.auth6Answers10_100);
961 addGetStat("auth6-answers100-1000", &g_stats.auth6Answers100_1000);
962 addGetStat("auth6-answers-slow", &g_stats.auth6AnswersSlow);
963
964
965 addGetStat("qa-latency", doGetAvgLatencyUsec);
966 addGetStat("x-our-latency", []() { return g_stats.avgLatencyOursUsec; });
967 addGetStat("unexpected-packets", &g_stats.unexpectedCount);
968 addGetStat("case-mismatches", &g_stats.caseMismatchCount);
969 addGetStat("spoof-prevents", &g_stats.spoofCount);
970
971 addGetStat("nsset-invalidations", &g_stats.nsSetInvalidations);
972
973 addGetStat("resource-limits", &g_stats.resourceLimits);
974 addGetStat("over-capacity-drops", &g_stats.overCapacityDrops);
975 addGetStat("policy-drops", &g_stats.policyDrops);
976 addGetStat("no-packet-error", &g_stats.noPacketError);
977 addGetStat("dlg-only-drops", &SyncRes::s_nodelegated);
978 addGetStat("ignored-packets", &g_stats.ignoredCount);
979 addGetStat("empty-queries", &g_stats.emptyQueriesCount);
980 addGetStat("max-mthread-stack", &g_stats.maxMThreadStackUsage);
981
982 addGetStat("negcache-entries", boost::bind(getNegCacheSize));
983 addGetStat("throttle-entries", boost::bind(getThrottleSize));
984
985 addGetStat("nsspeeds-entries", boost::bind(getNsSpeedsSize));
986 addGetStat("failed-host-entries", boost::bind(getFailedHostsSize));
987
988 addGetStat("concurrent-queries", boost::bind(getConcurrentQueries));
989 addGetStat("security-status", &g_security_status);
990 addGetStat("outgoing-timeouts", &SyncRes::s_outgoingtimeouts);
991 addGetStat("outgoing4-timeouts", &SyncRes::s_outgoing4timeouts);
992 addGetStat("outgoing6-timeouts", &SyncRes::s_outgoing6timeouts);
993 addGetStat("auth-zone-queries", &SyncRes::s_authzonequeries);
994 addGetStat("tcp-outqueries", &SyncRes::s_tcpoutqueries);
995 addGetStat("all-outqueries", &SyncRes::s_outqueries);
996 addGetStat("ipv6-outqueries", &g_stats.ipv6queries);
997 addGetStat("throttled-outqueries", &SyncRes::s_throttledqueries);
998 addGetStat("dont-outqueries", &SyncRes::s_dontqueries);
999 addGetStat("throttled-out", &SyncRes::s_throttledqueries);
1000 addGetStat("unreachables", &SyncRes::s_unreachables);
1001 addGetStat("ecs-queries", &SyncRes::s_ecsqueries);
1002 addGetStat("ecs-responses", &SyncRes::s_ecsresponses);
1003 addGetStat("chain-resends", &g_stats.chainResends);
1004 addGetStat("tcp-clients", boost::bind(TCPConnection::getCurrentConnections));
1005
1006 #ifdef __linux__
1007 addGetStat("udp-recvbuf-errors", boost::bind(udpErrorStats, "udp-recvbuf-errors"));
1008 addGetStat("udp-sndbuf-errors", boost::bind(udpErrorStats, "udp-sndbuf-errors"));
1009 addGetStat("udp-noport-errors", boost::bind(udpErrorStats, "udp-noport-errors"));
1010 addGetStat("udp-in-errors", boost::bind(udpErrorStats, "udp-in-errors"));
1011 #endif
1012
1013 addGetStat("edns-ping-matches", &g_stats.ednsPingMatches);
1014 addGetStat("edns-ping-mismatches", &g_stats.ednsPingMismatches);
1015 addGetStat("dnssec-queries", &g_stats.dnssecQueries);
1016
1017 addGetStat("dnssec-authentic-data-queries", &g_stats.dnssecAuthenticDataQueries);
1018 addGetStat("dnssec-check-disabled-queries", &g_stats.dnssecCheckDisabledQueries);
1019
1020 addGetStat("variable-responses", &g_stats.variableResponses);
1021
1022 addGetStat("noping-outqueries", &g_stats.noPingOutQueries);
1023 addGetStat("noedns-outqueries", &g_stats.noEdnsOutQueries);
1024
1025 addGetStat("uptime", calculateUptime);
1026 addGetStat("real-memory-usage", boost::bind(getRealMemoryUsage, string()));
1027 addGetStat("special-memory-usage", boost::bind(getSpecialMemoryUsage, string()));
1028 addGetStat("fd-usage", boost::bind(getOpenFileDescriptors, string()));
1029
1030 // addGetStat("query-rate", getQueryRate);
1031 addGetStat("user-msec", getUserTimeMsec);
1032 addGetStat("sys-msec", getSysTimeMsec);
1033
1034 #ifdef MALLOC_TRACE
1035 addGetStat("memory-allocs", boost::bind(&MallocTracer::getAllocs, g_mtracer, string()));
1036 addGetStat("memory-alloc-flux", boost::bind(&MallocTracer::getAllocFlux, g_mtracer, string()));
1037 addGetStat("memory-allocated", boost::bind(&MallocTracer::getTotAllocated, g_mtracer, string()));
1038 #endif
1039
1040 addGetStat("dnssec-validations", &g_stats.dnssecValidations);
1041 addGetStat("dnssec-result-insecure", &g_stats.dnssecResults[Insecure]);
1042 addGetStat("dnssec-result-secure", &g_stats.dnssecResults[Secure]);
1043 addGetStat("dnssec-result-bogus", &g_stats.dnssecResults[Bogus]);
1044 addGetStat("dnssec-result-indeterminate", &g_stats.dnssecResults[Indeterminate]);
1045 addGetStat("dnssec-result-nta", &g_stats.dnssecResults[NTA]);
1046
1047 addGetStat("policy-result-noaction", &g_stats.policyResults[DNSFilterEngine::PolicyKind::NoAction]);
1048 addGetStat("policy-result-drop", &g_stats.policyResults[DNSFilterEngine::PolicyKind::Drop]);
1049 addGetStat("policy-result-nxdomain", &g_stats.policyResults[DNSFilterEngine::PolicyKind::NXDOMAIN]);
1050 addGetStat("policy-result-nodata", &g_stats.policyResults[DNSFilterEngine::PolicyKind::NODATA]);
1051 addGetStat("policy-result-truncate", &g_stats.policyResults[DNSFilterEngine::PolicyKind::Truncate]);
1052 addGetStat("policy-result-custom", &g_stats.policyResults[DNSFilterEngine::PolicyKind::Custom]);
1053 }
1054
1055 static void doExitGeneric(bool nicely)
1056 {
1057 g_log<<Logger::Error<<"Exiting on user request"<<endl;
1058 extern RecursorControlChannel s_rcc;
1059 s_rcc.~RecursorControlChannel();
1060
1061 extern string s_pidfname;
1062 if(!s_pidfname.empty())
1063 unlink(s_pidfname.c_str()); // we can at least try..
1064 if(nicely)
1065 exit(1);
1066 else
1067 _exit(1);
1068 }
1069
1070 static void doExit()
1071 {
1072 doExitGeneric(false);
1073 }
1074
1075 static void doExitNicely()
1076 {
1077 doExitGeneric(true);
1078 }
1079
1080 vector<pair<DNSName, uint16_t> >* pleaseGetQueryRing()
1081 {
1082 typedef pair<DNSName,uint16_t> query_t;
1083 vector<query_t >* ret = new vector<query_t>();
1084 if(!t_queryring)
1085 return ret;
1086 ret->reserve(t_queryring->size());
1087
1088 for(const query_t& q : *t_queryring) {
1089 ret->push_back(q);
1090 }
1091 return ret;
1092 }
1093 vector<pair<DNSName,uint16_t> >* pleaseGetServfailQueryRing()
1094 {
1095 typedef pair<DNSName,uint16_t> query_t;
1096 vector<query_t>* ret = new vector<query_t>();
1097 if(!t_servfailqueryring)
1098 return ret;
1099 ret->reserve(t_servfailqueryring->size());
1100 for(const query_t& q : *t_servfailqueryring) {
1101 ret->push_back(q);
1102 }
1103 return ret;
1104 }
1105 vector<pair<DNSName,uint16_t> >* pleaseGetBogusQueryRing()
1106 {
1107 typedef pair<DNSName,uint16_t> query_t;
1108 vector<query_t>* ret = new vector<query_t>();
1109 if(!t_bogusqueryring)
1110 return ret;
1111 ret->reserve(t_bogusqueryring->size());
1112 for(const query_t& q : *t_bogusqueryring) {
1113 ret->push_back(q);
1114 }
1115 return ret;
1116 }
1117
1118
1119
1120 typedef boost::function<vector<ComboAddress>*()> pleaseremotefunc_t;
1121 typedef boost::function<vector<pair<DNSName,uint16_t> >*()> pleasequeryfunc_t;
1122
1123 vector<ComboAddress>* pleaseGetRemotes()
1124 {
1125 vector<ComboAddress>* ret = new vector<ComboAddress>();
1126 if(!t_remotes)
1127 return ret;
1128
1129 ret->reserve(t_remotes->size());
1130 for(const ComboAddress& ca : *t_remotes) {
1131 ret->push_back(ca);
1132 }
1133 return ret;
1134 }
1135
1136 vector<ComboAddress>* pleaseGetServfailRemotes()
1137 {
1138 vector<ComboAddress>* ret = new vector<ComboAddress>();
1139 if(!t_servfailremotes)
1140 return ret;
1141 ret->reserve(t_servfailremotes->size());
1142 for(const ComboAddress& ca : *t_servfailremotes) {
1143 ret->push_back(ca);
1144 }
1145 return ret;
1146 }
1147
1148 vector<ComboAddress>* pleaseGetBogusRemotes()
1149 {
1150 vector<ComboAddress>* ret = new vector<ComboAddress>();
1151 if(!t_bogusremotes)
1152 return ret;
1153 ret->reserve(t_bogusremotes->size());
1154 for(const ComboAddress& ca : *t_bogusremotes) {
1155 ret->push_back(ca);
1156 }
1157 return ret;
1158 }
1159
1160 vector<ComboAddress>* pleaseGetLargeAnswerRemotes()
1161 {
1162 vector<ComboAddress>* ret = new vector<ComboAddress>();
1163 if(!t_largeanswerremotes)
1164 return ret;
1165 ret->reserve(t_largeanswerremotes->size());
1166 for(const ComboAddress& ca : *t_largeanswerremotes) {
1167 ret->push_back(ca);
1168 }
1169 return ret;
1170 }
1171
1172 vector<ComboAddress>* pleaseGetTimeouts()
1173 {
1174 vector<ComboAddress>* ret = new vector<ComboAddress>();
1175 if(!t_timeouts)
1176 return ret;
1177 ret->reserve(t_timeouts->size());
1178 for(const ComboAddress& ca : *t_timeouts) {
1179 ret->push_back(ca);
1180 }
1181 return ret;
1182 }
1183
1184 string doGenericTopRemotes(pleaseremotefunc_t func)
1185 {
1186 typedef map<ComboAddress, int, ComboAddress::addressOnlyLessThan> counts_t;
1187 counts_t counts;
1188
1189 vector<ComboAddress> remotes=broadcastAccFunction<vector<ComboAddress> >(func);
1190
1191 unsigned int total=0;
1192 for(const ComboAddress& ca : remotes) {
1193 total++;
1194 counts[ca]++;
1195 }
1196
1197 typedef std::multimap<int, ComboAddress> rcounts_t;
1198 rcounts_t rcounts;
1199
1200 for(counts_t::const_iterator i=counts.begin(); i != counts.end(); ++i)
1201 rcounts.insert(make_pair(-i->second, i->first));
1202
1203 ostringstream ret;
1204 ret<<"Over last "<<total<<" entries:\n";
1205 format fmt("%.02f%%\t%s\n");
1206 int limit=0, accounted=0;
1207 if(total) {
1208 for(rcounts_t::const_iterator i=rcounts.begin(); i != rcounts.end() && limit < 20; ++i, ++limit) {
1209 ret<< fmt % (-100.0*i->first/total) % i->second.toString();
1210 accounted+= -i->first;
1211 }
1212 ret<< '\n' << fmt % (100.0*(total-accounted)/total) % "rest";
1213 }
1214 return ret.str();
1215 }
1216
1217 // XXX DNSName Pain - this function should benefit from native DNSName methods
1218 DNSName getRegisteredName(const DNSName& dom)
1219 {
1220 auto parts=dom.getRawLabels();
1221 if(parts.size()<=2)
1222 return dom;
1223 reverse(parts.begin(), parts.end());
1224 for(string& str : parts) { str=toLower(str); };
1225
1226 // uk co migweb
1227 string last;
1228 while(!parts.empty()) {
1229 if(parts.size()==1 || binary_search(g_pubs.begin(), g_pubs.end(), parts)) {
1230
1231 string ret=last;
1232 if(!ret.empty())
1233 ret+=".";
1234
1235 for(auto p = parts.crbegin(); p != parts.crend(); ++p) {
1236 ret+=(*p)+".";
1237 }
1238 return DNSName(ret);
1239 }
1240
1241 last=parts[parts.size()-1];
1242 parts.resize(parts.size()-1);
1243 }
1244 return DNSName("??");
1245 }
1246
1247 static DNSName nopFilter(const DNSName& name)
1248 {
1249 return name;
1250 }
1251
1252 string doGenericTopQueries(pleasequeryfunc_t func, boost::function<DNSName(const DNSName&)> filter=nopFilter)
1253 {
1254 typedef pair<DNSName,uint16_t> query_t;
1255 typedef map<query_t, int> counts_t;
1256 counts_t counts;
1257 vector<query_t> queries=broadcastAccFunction<vector<query_t> >(func);
1258
1259 unsigned int total=0;
1260 for(const query_t& q : queries) {
1261 total++;
1262 counts[make_pair(filter(q.first),q.second)]++;
1263 }
1264
1265 typedef std::multimap<int, query_t> rcounts_t;
1266 rcounts_t rcounts;
1267
1268 for(counts_t::const_iterator i=counts.begin(); i != counts.end(); ++i)
1269 rcounts.insert(make_pair(-i->second, i->first));
1270
1271 ostringstream ret;
1272 ret<<"Over last "<<total<<" entries:\n";
1273 format fmt("%.02f%%\t%s\n");
1274 int limit=0, accounted=0;
1275 if(total) {
1276 for(rcounts_t::const_iterator i=rcounts.begin(); i != rcounts.end() && limit < 20; ++i, ++limit) {
1277 ret<< fmt % (-100.0*i->first/total) % (i->second.first.toLogString()+"|"+DNSRecordContent::NumberToType(i->second.second));
1278 accounted+= -i->first;
1279 }
1280 ret<< '\n' << fmt % (100.0*(total-accounted)/total) % "rest";
1281 }
1282
1283
1284 return ret.str();
1285 }
1286
1287 static string* nopFunction()
1288 {
1289 return new string("pong\n");
1290 }
1291
1292 string RecursorControlParser::getAnswer(const string& question, RecursorControlParser::func_t** command)
1293 {
1294 *command=nop;
1295 vector<string> words;
1296 stringtok(words, question);
1297
1298 if(words.empty())
1299 return "invalid command\n";
1300
1301 string cmd=toLower(words[0]);
1302 vector<string>::const_iterator begin=words.begin()+1, end=words.end();
1303
1304 // should probably have a smart dispatcher here, like auth has
1305 if(cmd=="help")
1306 return
1307 "add-nta DOMAIN [REASON] add a Negative Trust Anchor for DOMAIN with the comment REASON\n"
1308 "add-ta DOMAIN DSRECORD add a Trust Anchor for DOMAIN with data DSRECORD\n"
1309 "current-queries show currently active queries\n"
1310 "clear-nta [DOMAIN]... Clear the Negative Trust Anchor for DOMAINs, if no DOMAIN is specified, remove all\n"
1311 "clear-ta [DOMAIN]... Clear the Trust Anchor for DOMAINs\n"
1312 "dump-cache <filename> dump cache contents to the named file\n"
1313 "dump-edns [status] <filename> dump EDNS status to the named file\n"
1314 "dump-nsspeeds <filename> dump nsspeeds statistics to the named file\n"
1315 "dump-rpz <zone name> <filename> dump the content of a RPZ zone to the named file\n"
1316 "dump-throttlemap <filename> dump the contents of the throttle to the named file\n"
1317 "get [key1] [key2] .. get specific statistics\n"
1318 "get-all get all statistics\n"
1319 "get-ntas get all configured Negative Trust Anchors\n"
1320 "get-tas get all configured Trust Anchors\n"
1321 "get-parameter [key1] [key2] .. get configuration parameters\n"
1322 "get-qtypelist get QType statistics\n"
1323 " notice: queries from cache aren't being counted yet\n"
1324 "help get this list\n"
1325 "ping check that all threads are alive\n"
1326 "quit stop the recursor daemon\n"
1327 "quit-nicely stop the recursor daemon nicely\n"
1328 "reload-acls reload ACLS\n"
1329 "reload-lua-script [filename] (re)load Lua script\n"
1330 "reload-lua-config [filename] (re)load Lua configuration file\n"
1331 "reload-zones reload all auth and forward zones\n"
1332 "set-max-cache-entries value set new maximum cache size\n"
1333 "set-max-packetcache-entries val set new maximum packet cache size\n"
1334 "set-minimum-ttl value set minimum-ttl-override\n"
1335 "set-carbon-server set a carbon server for telemetry\n"
1336 "set-dnssec-log-bogus SETTING enable (SETTING=yes) or disable (SETTING=no) logging of DNSSEC validation failures\n"
1337 "trace-regex [regex] emit resolution trace for matching queries (empty regex to clear trace)\n"
1338 "top-largeanswer-remotes show top remotes receiving large answers\n"
1339 "top-queries show top queries\n"
1340 "top-pub-queries show top queries grouped by public suffix list\n"
1341 "top-remotes show top remotes\n"
1342 "top-timeouts show top downstream timeouts\n"
1343 "top-servfail-queries show top queries receiving servfail answers\n"
1344 "top-bogus-queries show top queries validating as bogus\n"
1345 "top-pub-servfail-queries show top queries receiving servfail answers grouped by public suffix list\n"
1346 "top-pub-bogus-queries show top queries validating as bogus grouped by public suffix list\n"
1347 "top-servfail-remotes show top remotes receiving servfail answers\n"
1348 "top-bogus-remotes show top remotes receiving bogus answers\n"
1349 "unload-lua-script unload Lua script\n"
1350 "version return Recursor version number\n"
1351 "wipe-cache domain0 [domain1] .. wipe domain data from cache\n";
1352
1353 if(cmd=="get-all")
1354 return getAllStats();
1355
1356 if(cmd=="get")
1357 return doGet(begin, end);
1358
1359 if(cmd=="get-parameter")
1360 return doGetParameter(begin, end);
1361
1362 if(cmd=="quit") {
1363 *command=&doExit;
1364 return "bye\n";
1365 }
1366
1367 if(cmd=="version") {
1368 return getPDNSVersion()+"\n";
1369 }
1370
1371 if(cmd=="quit-nicely") {
1372 *command=&doExitNicely;
1373 return "bye nicely\n";
1374 }
1375
1376 if(cmd=="dump-cache")
1377 return doDumpCache(begin, end);
1378
1379 if(cmd=="dump-ednsstatus" || cmd=="dump-edns")
1380 return doDumpEDNSStatus(begin, end);
1381
1382 if(cmd=="dump-nsspeeds")
1383 return doDumpNSSpeeds(begin, end);
1384
1385 if(cmd=="dump-rpz") {
1386 return doDumpRPZ(begin, end);
1387 }
1388
1389 if(cmd=="dump-throttlemap")
1390 return doDumpThrottleMap(begin, end);
1391
1392 if(cmd=="wipe-cache" || cmd=="flushname")
1393 return doWipeCache(begin, end);
1394
1395 if(cmd=="reload-lua-script")
1396 return doQueueReloadLuaScript(begin, end);
1397
1398 if(cmd=="reload-lua-config") {
1399 if(begin != end)
1400 ::arg().set("lua-config-file") = *begin;
1401
1402 try {
1403 luaConfigDelayedThreads delayedLuaThreads;
1404 loadRecursorLuaConfig(::arg()["lua-config-file"], delayedLuaThreads);
1405 startLuaConfigDelayedThreads(delayedLuaThreads, g_luaconfs.getCopy().generation);
1406 g_log<<Logger::Warning<<"Reloaded Lua configuration file '"<<::arg()["lua-config-file"]<<"', requested via control channel"<<endl;
1407 return "Reloaded Lua configuration file '"+::arg()["lua-config-file"]+"'\n";
1408 }
1409 catch(std::exception& e) {
1410 return "Unable to load Lua script from '"+::arg()["lua-config-file"]+"': "+e.what()+"\n";
1411 }
1412 catch(const PDNSException& e) {
1413 return "Unable to load Lua script from '"+::arg()["lua-config-file"]+"': "+e.reason+"\n";
1414 }
1415 }
1416
1417 if(cmd=="set-carbon-server")
1418 return doSetCarbonServer(begin, end);
1419
1420 if(cmd=="trace-regex")
1421 return doTraceRegex(begin, end);
1422
1423 if(cmd=="unload-lua-script") {
1424 vector<string> empty;
1425 empty.push_back(string());
1426 return doQueueReloadLuaScript(empty.begin(), empty.end());
1427 }
1428
1429 if(cmd=="reload-acls") {
1430 if(!::arg()["chroot"].empty()) {
1431 g_log<<Logger::Error<<"Unable to reload ACL when chroot()'ed, requested via control channel"<<endl;
1432 return "Unable to reload ACL when chroot()'ed, please restart\n";
1433 }
1434
1435 try {
1436 parseACLs();
1437 }
1438 catch(std::exception& e)
1439 {
1440 g_log<<Logger::Error<<"Reloading ACLs failed (Exception: "<<e.what()<<")"<<endl;
1441 return e.what() + string("\n");
1442 }
1443 catch(PDNSException& ae)
1444 {
1445 g_log<<Logger::Error<<"Reloading ACLs failed (PDNSException: "<<ae.reason<<")"<<endl;
1446 return ae.reason + string("\n");
1447 }
1448 return "ok\n";
1449 }
1450
1451
1452 if(cmd=="top-remotes")
1453 return doGenericTopRemotes(pleaseGetRemotes);
1454
1455 if(cmd=="top-queries")
1456 return doGenericTopQueries(pleaseGetQueryRing);
1457
1458 if(cmd=="top-pub-queries")
1459 return doGenericTopQueries(pleaseGetQueryRing, getRegisteredName);
1460
1461 if(cmd=="top-servfail-queries")
1462 return doGenericTopQueries(pleaseGetServfailQueryRing);
1463
1464 if(cmd=="top-pub-servfail-queries")
1465 return doGenericTopQueries(pleaseGetServfailQueryRing, getRegisteredName);
1466
1467 if(cmd=="top-bogus-queries")
1468 return doGenericTopQueries(pleaseGetBogusQueryRing);
1469
1470 if(cmd=="top-pub-bogus-queries")
1471 return doGenericTopQueries(pleaseGetBogusQueryRing, getRegisteredName);
1472
1473
1474 if(cmd=="top-servfail-remotes")
1475 return doGenericTopRemotes(pleaseGetServfailRemotes);
1476
1477 if(cmd=="top-bogus-remotes")
1478 return doGenericTopRemotes(pleaseGetBogusRemotes);
1479
1480 if(cmd=="top-largeanswer-remotes")
1481 return doGenericTopRemotes(pleaseGetLargeAnswerRemotes);
1482
1483 if(cmd=="top-timeouts")
1484 return doGenericTopRemotes(pleaseGetTimeouts);
1485
1486
1487 if(cmd=="current-queries")
1488 return doCurrentQueries();
1489
1490 if(cmd=="ping") {
1491 return broadcastAccFunction<string>(nopFunction);
1492 }
1493
1494 if(cmd=="reload-zones") {
1495 if(!::arg()["chroot"].empty()) {
1496 g_log<<Logger::Error<<"Unable to reload zones and forwards when chroot()'ed, requested via control channel"<<endl;
1497 return "Unable to reload zones and forwards when chroot()'ed, please restart\n";
1498 }
1499 return reloadAuthAndForwards();
1500 }
1501
1502 if(cmd=="set-max-cache-entries") {
1503 return setMaxCacheEntries(begin, end);
1504 }
1505 if(cmd=="set-max-packetcache-entries") {
1506 return setMaxPacketCacheEntries(begin, end);
1507 }
1508
1509 if(cmd=="set-minimum-ttl") {
1510 return setMinimumTTL(begin, end);
1511 }
1512
1513 if(cmd=="get-qtypelist") {
1514 return g_rs.getQTypeReport();
1515 }
1516
1517 if(cmd=="add-nta") {
1518 return doAddNTA(begin, end);
1519 }
1520
1521 if(cmd=="clear-nta") {
1522 return doClearNTA(begin, end);
1523 }
1524
1525 if(cmd=="get-ntas") {
1526 return getNTAs();
1527 }
1528
1529 if(cmd=="add-ta") {
1530 return doAddTA(begin, end);
1531 }
1532
1533 if(cmd=="clear-ta") {
1534 return doClearTA(begin, end);
1535 }
1536
1537 if(cmd=="get-tas") {
1538 return getTAs();
1539 }
1540
1541 if (cmd=="set-dnssec-log-bogus")
1542 return doSetDnssecLogBogus(begin, end);
1543
1544 return "Unknown command '"+cmd+"', try 'help'\n";
1545 }