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