2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "auth-caches.hh"
26 #include "auth-querycache.hh"
27 #include "auth-packetcache.hh"
29 #include "dynhandler.hh"
33 #include "arguments.hh"
36 #include "communicator.hh"
37 #include "dnsseckeeper.hh"
38 #include "nameserver.hh"
39 #include "responsestats.hh"
40 #include "ueberbackend.hh"
41 #include "common_startup.hh"
43 extern ResponseStats g_rs
;
45 static bool s_pleasequit
;
46 static string d_status
;
53 string
DLQuitHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
55 string ret
="No return value";
56 if(parts
[0]=="QUIT") {
58 ret
="Scheduling exit";
59 g_log
<<Logger::Error
<<"Scheduling exit on remote request"<<endl
;
64 static void dokill(int)
69 string
DLCurrentConfigHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
71 return ::arg().configstring(true);
74 string
DLRQuitHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
76 signal(SIGALRM
, dokill
);
81 string
DLPingHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
86 string
DLShowHandler(const vector
<string
>&parts
, Utility::pid_t ppid
) {
87 std::set
<string
> blacklist
;
88 blacklist
.insert("special-memory-usage");
91 string
ret("Wrong number of parameters");
92 if (parts
.size() == 2) {
94 ret
= S
.directory(blacklist
);
96 ret
= S
.getValueStr(parts
[1]);
106 void setStatus(const string
&str
)
111 string
DLStatusHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
114 os
<<ppid
<<": "<<d_status
;
118 string
DLUptimeHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
121 os
<<humanDuration(time(0)-s_starttime
);
125 string
DLPurgeHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
132 for (vector
<string
>::const_iterator i
=++parts
.begin();i
<parts
.end();++i
) {
133 ret
+=purgeAuthCaches(*i
);
134 if(!boost::ends_with(*i
, "$"))
135 dk
.clearCaches(DNSName(*i
));
137 dk
.clearAllCaches(); // at least we do what we promise.. and a bit more!
141 ret
= purgeAuthCaches();
149 string
DLCCHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
151 extern AuthPacketCache PC
;
152 extern AuthQueryCache QC
;
153 map
<char,uint64_t> counts
=QC
.getCounts();
154 uint64_t packetEntries
= PC
.size();
157 for(map
<char,uint64_t>::const_iterator i
=counts
.begin();i
!=counts
.end();++i
) {
163 os
<<"negative queries: ";
164 else if(i
->first
=='Q')
171 os
<<"packets: "<<packetEntries
;
176 string
DLQTypesHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
178 return g_rs
.getQTypeReport();
181 string
DLRSizesHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
183 typedef map
<uint16_t, uint64_t> respsizes_t
;
184 respsizes_t respsizes
= g_rs
.getSizeResponseCounts();
186 boost::format
fmt("%d\t%d\n");
187 for(const respsizes_t::value_type
& val
: respsizes
) {
188 os
<< (fmt
% val
.first
% val
.second
).str();
193 string
DLRemotesHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
196 typedef vector
<pair
<string
, unsigned int> > totals_t
;
197 totals_t totals
= S
.getRing("remotes");
199 boost::format
fmt("%s\t%d\n");
200 for(totals_t::value_type
& val
: totals
) {
201 ret
+= (fmt
% val
.first
% val
.second
).str();
206 string
DLSettingsHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
208 static const char *whitelist
[]={"query-logging",0};
211 if(parts
.size()!=3) {
212 return "Syntax: set variable value";
215 for(p
=whitelist
;*p
;p
++)
219 ::arg().set(parts
[1])=parts
[2];
223 return "This setting cannot be changed at runtime, or no such setting";
227 string
DLVersionHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
232 string
DLNotifyRetrieveHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
234 extern CommunicatorClass Communicator
;
237 return "syntax: retrieve domain";
241 domain
= DNSName(parts
[1]);
243 return "Failed to parse domain as valid DNS name";
248 if(!B
.getDomainInfo(domain
, di
))
249 return "Domain '"+domain
.toString()+"' unknown";
251 if(di
.kind
!= DomainInfo::Slave
|| di
.masters
.empty())
252 return "Domain '"+domain
.toString()+"' is not a slave domain (or has no master defined)";
254 random_shuffle(di
.masters
.begin(), di
.masters
.end());
255 Communicator
.addSuckRequest(domain
, di
.masters
.front());
256 return "Added retrieval request for '"+domain
.toString()+"' from master "+di
.masters
.front().toLogString();
259 string
DLNotifyHostHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
261 extern CommunicatorClass Communicator
;
264 return "syntax: notify-host domain ip";
265 if(!::arg().mustDo("master") && !(::arg().mustDo("slave") && ::arg().mustDo("slave-renotify")))
266 return "PowerDNS not configured as master or slave with re-notifications";
270 domain
= DNSName(parts
[1]);
272 return "Failed to parse domain as valid DNS name";
276 ComboAddress
ca(parts
[2]);
279 return "Unable to convert '"+parts
[2]+"' to an IP address";
282 g_log
<<Logger::Warning
<<"Notification request to host "<<parts
[2]<<" for domain '"<<domain
<<"' received from operator"<<endl
;
283 Communicator
.notify(domain
, parts
[2]);
284 return "Added to queue";
287 string
DLNotifyHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
289 extern CommunicatorClass Communicator
;
292 return "syntax: notify domain";
293 if(!::arg().mustDo("master") && !(::arg().mustDo("slave") && ::arg().mustDo("slave-renotify")))
294 return "PowerDNS not configured as master or slave with re-notifications";
295 g_log
<<Logger::Warning
<<"Notification request for domain '"<<parts
[1]<<"' received from operator"<<endl
;
297 if (parts
[1] == "*") {
298 vector
<DomainInfo
> domains
;
299 B
.getAllDomains(&domains
);
303 for (const auto& di
: domains
) {
304 if (di
.kind
== DomainInfo::Master
|| di
.kind
== DomainInfo::Slave
) { // MASTER and Slave if slave-renotify is enabled
306 if(Communicator
.notifyDomain(di
.zone
))
311 if (total
!= notified
)
312 return itoa(notified
)+" out of "+itoa(total
)+" zones added to queue - see log";
313 return "Added "+itoa(total
)+" MASTER/SLAVE zones to queue";
317 domain
= DNSName(parts
[1]);
319 return "Failed to parse domain as valid DNS name";
321 if(!Communicator
.notifyDomain(DNSName(parts
[1])))
322 return "Failed to add to the queue - see log";
323 return "Added to queue";
327 string
DLRediscoverHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
331 g_log
<<Logger::Error
<<"Rediscovery was requested"<<endl
;
333 B
.rediscover(&status
);
336 catch(PDNSException
&ae
) {
342 string
DLReloadHandler(const vector
<string
>&parts
, Utility::pid_t ppid
)
346 g_log
<<Logger::Error
<<"Reload was requested"<<endl
;
351 string
DLListZones(const vector
<string
>&parts
, Utility::pid_t ppid
)
354 g_log
<<Logger::Notice
<<"Received request to list zones."<<endl
;
355 vector
<DomainInfo
> domains
;
356 B
.getAllDomains(&domains
);
359 if (parts
.size() > 1) {
360 if (toUpper(parts
[1]) == "MASTER")
362 else if (toUpper(parts
[1]) == "SLAVE")
364 else if (toUpper(parts
[1]) == "NATIVE")
370 for (const auto& di
: domains
) {
371 if (di
.kind
== kindFilter
|| kindFilter
== -1) {
372 ret
<<di
.zone
.toString()<<endl
;
376 if (kindFilter
!= -1)
377 ret
<<parts
[1]<<" zonecount:"<<count
;
379 ret
<<"All zonecount:"<<count
;
385 extern bool PKCS11ModuleSlotLogin(const std::string
& module
, const string
& tokenId
, const std::string
& pin
);
388 string
DLTokenLogin(const vector
<string
>&parts
, Utility::pid_t ppid
)
391 return "PKCS#11 support not compiled in";
393 if (parts
.size() != 4) {
394 return "invalid number of parameters, needs 4, got " + std::to_string(parts
.size());
397 if (PKCS11ModuleSlotLogin(parts
[1], parts
[2], parts
[3])) {
400 return "could not log in, check logs";