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