]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dynhandler.cc
Remove pdns_strtoui
[thirdparty/pdns.git] / pdns / dynhandler.cc
CommitLineData
12c86877
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
379ab445 3 Copyright (C) 2002 - 2008 PowerDNS.COM BV
12c86877
BH
4
5 This program is free software; you can redistribute it and/or modify
ea44d9d3
BH
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation.
12c86877 8
f782fe38
MH
9 Additionally, the license of this program contains a special
10 exception which allows to distribute the program in binary form when
11 it is linked against OpenSSL.
12
12c86877
BH
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.
17
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
06bd9ccf 20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12c86877 21*/
870a0fe4
AT
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
379ab445 25#include "packetcache.hh"
bd11bd1d 26#include "utility.hh"
12c86877
BH
27#include "dynhandler.hh"
28#include "statbag.hh"
29#include "logger.hh"
30#include "dns.hh"
31#include "arguments.hh"
32#include <signal.h>
bd11bd1d 33#include "misc.hh"
12c86877 34#include "communicator.hh"
627d2ca2 35#include "dnsseckeeper.hh"
ba7244a5 36#include "nameserver.hh"
09425ce1 37#include "responsestats.hh"
767da1a0 38#include "ueberbackend.hh"
3e8216c8 39#include "common_startup.hh"
09425ce1
F
40
41extern ResponseStats g_rs;
12c86877
BH
42
43static bool s_pleasequit;
64bcb6be 44static string d_status;
12c86877
BH
45
46bool DLQuitPlease()
47{
48 return s_pleasequit;
49}
50
51string DLQuitHandler(const vector<string>&parts, Utility::pid_t ppid)
52{
53 string ret="No return value";
54 if(parts[0]=="QUIT") {
55 s_pleasequit=true;
56 ret="Scheduling exit";
57 L<<Logger::Error<<"Scheduling exit on remote request"<<endl;
58 }
59 return ret;
12c86877
BH
60}
61
62static void dokill(int)
63{
e7f0140b 64 exit(0);
12c86877
BH
65}
66
64bcb6be
RA
67string DLCurrentConfigHandler(const vector<string>&parts, Utility::pid_t ppid)
68{
69 return ::arg().configstring(true);
70}
71
12c86877
BH
72string DLRQuitHandler(const vector<string>&parts, Utility::pid_t ppid)
73{
12c86877 74 signal(SIGALRM, dokill);
12c86877 75 alarm(1);
12c86877
BH
76 return "Exiting";
77}
78
79string DLPingHandler(const vector<string>&parts, Utility::pid_t ppid)
80{
81 return "PONG";
82}
83
84string DLShowHandler(const vector<string>&parts, Utility::pid_t ppid)
02feff9f 85try
12c86877
BH
86{
87 extern StatBag S;
88 string ret("Wrong number of parameters");
89 if(parts.size()==2) {
90 if(parts[1]=="*")
91 ret=S.directory();
92 else
93 ret=S.getValueStr(parts[1]);
94 }
95
96 return ret;
97}
02feff9f 98catch(...)
99{
100 return "Unknown";
101}
12c86877
BH
102
103void setStatus(const string &str)
104{
105 d_status=str;
106}
107
108string DLStatusHandler(const vector<string>&parts, Utility::pid_t ppid)
109{
110 ostringstream os;
111 os<<ppid<<": "<<d_status;
112 return os.str();
113}
114
115string DLUptimeHandler(const vector<string>&parts, Utility::pid_t ppid)
116{
117 ostringstream os;
118 os<<humanDuration(time(0)-s_starttime);
119 return os.str();
120}
121
122string DLPurgeHandler(const vector<string>&parts, Utility::pid_t ppid)
123{
124 extern PacketCache PC;
627d2ca2 125 DNSSECKeeper dk;
12c86877 126 ostringstream os;
27fdc3fc 127 int ret=0;
12c86877 128
27fdc3fc
BH
129 if(parts.size()>1) {
130 for (vector<string>::const_iterator i=++parts.begin();i<parts.end();++i) {
131 ret+=PC.purge(*i);
478748c3 132 if(!boost::ends_with(*i, "$"))
133 dk.clearCaches(DNSName(*i));
134 else
135 dk.clearAllCaches(); // at least we do what we promise.. and a bit more!
27fdc3fc
BH
136 }
137 }
627d2ca2 138 else {
12c86877 139 ret=PC.purge();
627d2ca2
PD
140 dk.clearAllCaches();
141 }
142
12c86877
BH
143 os<<ret;
144 return os.str();
145}
146
147string DLCCHandler(const vector<string>&parts, Utility::pid_t ppid)
148{
149 extern PacketCache PC;
150 map<char,int> counts=PC.getCounts();
151 ostringstream os;
152 bool first=true;
153 for(map<char,int>::const_iterator i=counts.begin();i!=counts.end();++i) {
154 if(!first)
155 os<<", ";
156 first=false;
157
158 if(i->first=='!')
159 os<<"negative queries: ";
160 else if(i->first=='Q')
161 os<<"queries: ";
162 else if(i->first=='n')
163 os<<"non-recursive packets: ";
164 else if(i->first=='r')
165 os<<"recursive packets: ";
166 else
167 os<<"unknown: ";
168
169 os<<i->second;
170 }
171
172 return os.str();
173}
174
ba7244a5
PD
175string DLQTypesHandler(const vector<string>&parts, Utility::pid_t ppid)
176{
09425ce1 177 return g_rs.getQTypeReport();
ba7244a5 178}
12c86877 179
93698ef3
PD
180string DLRSizesHandler(const vector<string>&parts, Utility::pid_t ppid)
181{
182 typedef map<uint16_t, uint64_t> respsizes_t;
183 respsizes_t respsizes = g_rs.getSizeResponseCounts();
184 ostringstream os;
185 boost::format fmt("%d\t%d\n");
ef7cd021 186 for(const respsizes_t::value_type& val : respsizes) {
93698ef3
PD
187 os << (fmt % val.first % val.second).str();
188 }
189 return os.str();
190}
191
192string DLRemotesHandler(const vector<string>&parts, Utility::pid_t ppid)
193{
194 extern StatBag S;
195 typedef vector<pair<string, unsigned int> > totals_t;
196 totals_t totals = S.getRing("remotes");
197 string ret;
198 boost::format fmt("%s\t%d\n");
ef7cd021 199 for(totals_t::value_type& val : totals) {
93698ef3
PD
200 ret += (fmt % val.first % val.second).str();
201 }
202 return ret;
203}
204
12c86877
BH
205string DLSettingsHandler(const vector<string>&parts, Utility::pid_t ppid)
206{
207 static const char *whitelist[]={"query-logging",0};
208 const char **p;
209
210 if(parts.size()!=3) {
211 return "Syntax: set variable value";
212 }
213
214 for(p=whitelist;*p;p++)
215 if(*p==parts[1])
216 break;
3120733f 217 if(*p) {
379ab445 218 ::arg().set(parts[1])=parts[2];
12c86877
BH
219 return "done";
220 }
221 else
3120733f 222 return "This setting cannot be changed at runtime, or no such setting";
12c86877
BH
223
224}
225
12c86877
BH
226string DLVersionHandler(const vector<string>&parts, Utility::pid_t ppid)
227{
12c86877
BH
228 return VERSION;
229}
230
ef1d2f44
BH
231string DLNotifyRetrieveHandler(const vector<string>&parts, Utility::pid_t ppid)
232{
233 extern CommunicatorClass Communicator;
234 ostringstream os;
235 if(parts.size()!=2)
236 return "syntax: retrieve domain";
237
238 const string& domain=parts[1];
239 DomainInfo di;
295c4a00 240 UeberBackend B;
290a083d 241 if(!B.getDomainInfo(DNSName(domain), di))
ef1d2f44
BH
242 return "Domain '"+domain+"' unknown";
243
e5b11b2f 244 if(di.masters.empty())
f2c11a48
BH
245 return "Domain '"+domain+"' is not a slave domain (or has no master defined)";
246
e5b11b2f 247 random_shuffle(di.masters.begin(), di.masters.end());
290a083d 248 Communicator.addSuckRequest(DNSName(domain), di.masters.front());
e5b11b2f 249 return "Added retrieval request for '"+domain+"' from master "+di.masters.front();
ef1d2f44 250}
12c86877
BH
251
252string DLNotifyHostHandler(const vector<string>&parts, Utility::pid_t ppid)
253{
254 extern CommunicatorClass Communicator;
255 ostringstream os;
256 if(parts.size()!=3)
ea44d9d3 257 return "syntax: notify-host domain ip";
2685008f
PD
258 if(!::arg().mustDo("master"))
259 return "PowerDNS not configured as master";
5762f14e 260
c069c1f2
BH
261 try {
262 ComboAddress ca(parts[2]);
263 } catch(...)
264 {
5762f14e 265 return "Unable to convert '"+parts[2]+"' to an IP address";
c069c1f2
BH
266 }
267
2d908573 268 L<<Logger::Warning<<"Notification request to host "<<parts[2]<<" for domain '"<<parts[1]<<"' received from operator"<<endl;
290a083d 269 Communicator.notify(DNSName(parts[1]), parts[2]);
12c86877
BH
270 return "Added to queue";
271}
272
290a083d 273// XXX DNSName pain - if you pass us something that is not DNS, you'll get an exception here, which you never got before
274// and I bet we don't report it well to the user...
275
12c86877
BH
276string DLNotifyHandler(const vector<string>&parts, Utility::pid_t ppid)
277{
278 extern CommunicatorClass Communicator;
f1b4b713 279 UeberBackend B;
12c86877
BH
280 if(parts.size()!=2)
281 return "syntax: notify domain";
2685008f
PD
282 if(!::arg().mustDo("master"))
283 return "PowerDNS not configured as master";
11a45617 284 L<<Logger::Warning<<"Notification request for domain '"<<parts[1]<<"' received from operator"<<endl;
f1b4b713
KM
285
286 if (parts[1] == "*") {
287 vector<DomainInfo> domains;
288 B.getAllDomains(&domains);
289
290 int total = 0;
291 int notified = 0;
292 for (vector<DomainInfo>::const_iterator di=domains.begin(); di != domains.end(); di++) {
293 if (di->kind == 0) { // MASTER
294 total++;
295 if(Communicator.notifyDomain(di->zone))
296 notified++;
297 }
298 }
299
300 if (total != notified)
301 return itoa(notified)+" out of "+itoa(total)+" zones added to queue - see log";
302 return "Added "+itoa(total)+" MASTER zones to queue";
303 } else {
290a083d 304 if(!Communicator.notifyDomain(DNSName(parts[1])))
f1b4b713
KM
305 return "Failed to add to the queue - see log";
306 return "Added to queue";
307 }
12c86877
BH
308}
309
310string DLRediscoverHandler(const vector<string>&parts, Utility::pid_t ppid)
311{
295c4a00 312 UeberBackend B;
6242d8a4
KM
313 try {
314 L<<Logger::Error<<"Rediscovery was requested"<<endl;
315 string status="Ok";
295c4a00 316 B.rediscover(&status);
6242d8a4
KM
317 return status;
318 }
319 catch(PDNSException &ae) {
320 return ae.reason;
321 }
322
12c86877
BH
323}
324
325string DLReloadHandler(const vector<string>&parts, Utility::pid_t ppid)
326{
295c4a00
CH
327 UeberBackend B;
328 B.reload();
12c86877
BH
329 L<<Logger::Error<<"Reload was requested"<<endl;
330 return "Ok";
331}
64bcb6be 332
f45a622c 333
ca8e1742 334string DLListZones(const vector<string>&parts, Utility::pid_t ppid)
767da1a0
RA
335{
336 UeberBackend B;
36811022 337 L<<Logger::Notice<<"Received request to list zones."<<endl;
767da1a0
RA
338 vector<DomainInfo> domains;
339 B.getAllDomains(&domains);
340 ostringstream ret;
341 int kindFilter = -1;
342 if (parts.size() > 1) {
343 if (toUpper(parts[1]) == "MASTER")
344 kindFilter = 0;
345 else if (toUpper(parts[1]) == "SLAVE")
346 kindFilter = 1;
347 else if (toUpper(parts[1]) == "NATIVE")
348 kindFilter = 2;
349 }
350
351 int count = 0;
352
353 for (vector<DomainInfo>::const_iterator di=domains.begin(); di != domains.end(); di++) {
354 if (di->kind == kindFilter || kindFilter == -1) {
675fa24c 355 ret<<di->zone.toString()<<endl;
767da1a0
RA
356 count++;
357 }
358 }
359 if (kindFilter != -1)
36811022 360 ret<<parts[1]<<" zonecount:"<<count;
767da1a0 361 else
36811022 362 ret<<"All zonecount:"<<count;
767da1a0
RA
363
364 return ret.str();
365}
3e8216c8
PD
366
367string DLPolicy(const vector<string>&parts, Utility::pid_t ppid)
368{
369 if(LPE) {
370 return LPE->policycmd(parts);
371 }
372 else {
373 return "no policy script loaded";
374 }
375}
24e0b305
AT
376
377#ifdef HAVE_P11KIT1
248d701f 378extern bool PKCS11ModuleSlotLogin(const std::string& module, const string& tokenId, const std::string& pin);
24e0b305
AT
379#endif
380
381string DLTokenLogin(const vector<string>&parts, Utility::pid_t ppid)
382{
383#ifndef HAVE_P11KIT1
384 return "PKCS#11 support not compiled in";
385#else
386 if (parts.size() != 4) {
387 return "invalid number of parameters, needs 4, got " + boost::lexical_cast<string>(parts.size());
388 }
389
248d701f 390 if (PKCS11ModuleSlotLogin(parts[1], parts[2], parts[3])) {
24e0b305
AT
391 return "logged in";
392 } else {
393 return "could not log in, check logs";
394 }
395#endif
396}