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