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