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