]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dynloader.cc
Merge branch 'validate-hostname' of https://github.com/hlindqvist/pdns into hlindqvis...
[thirdparty/pdns.git] / pdns / dynloader.cc
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
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.
8 *
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.
12 *
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
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include <iostream>
26 #include <cstdio>
27 #include <cstring>
28 #include <cstdlib>
29 #include <unistd.h>
30 #include <errno.h>
31 #include <climits>
32 #include <string>
33 #include <map>
34 #include <sys/mman.h>
35 #include <fcntl.h>
36 #include <sys/types.h>
37
38
39 #include <sys/stat.h>
40 #include "pdnsexception.hh"
41 #include "misc.hh"
42 #include "dynmessenger.hh"
43 #include "arguments.hh"
44 #include "statbag.hh"
45 #include "misc.hh"
46 #include "namespaces.hh"
47 #include "namespaces.hh"
48
49 ArgvMap &arg()
50 {
51 static ArgvMap arg;
52 return arg;
53 }
54
55 StatBag S;
56
57 int main(int argc, char **argv)
58 {
59 string s_programname="pdns";
60
61 ::arg().set("config-dir","Location of configuration directory (pdns.conf)")=SYSCONFDIR;
62 ::arg().set("socket-dir",string("Where the controlsocket will live, ")+LOCALSTATEDIR+" when unset and not chrooted" )="";
63 ::arg().set("remote-address","Remote address to query");
64 ::arg().set("remote-port","Remote port to query")="53000";
65 ::arg().set("secret","Secret needed to connect to remote PowerDNS");
66
67 ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")="";
68 ::arg().setCmd("no-config","Don't parse configuration file");
69 ::arg().set("chroot","")="";
70 ::arg().setCmd("help","Provide a helpful message");
71 ::arg().laxParse(argc,argv);
72
73 if(::arg().mustDo("help")) {
74 cout<<"syntax:"<<endl<<endl;
75 cout<<::arg().helpstring(::arg()["help"])<<endl;
76 cout<<"In addition, 'pdns_control help' can be used to retrieve a list\nof available commands from PowerDNS"<<endl;
77 exit(0);
78 }
79
80 const vector<string>commands=::arg().getCommands();
81
82 if(commands.empty()) {
83 cerr<<"No command passed"<<endl;
84 return 0;
85 }
86
87 if(::arg()["config-name"]!="")
88 s_programname+="-"+::arg()["config-name"];
89
90 string configname=::arg()["config-dir"]+"/"+s_programname+".conf";
91 cleanSlashes(configname);
92
93 if(!::arg().mustDo("no-config")) {
94 ::arg().laxFile(configname.c_str());
95 ::arg().laxParse(argc,argv); // reparse so the commandline still wins
96 }
97
98 string socketname=::arg()["socket-dir"];
99 if (::arg()["socket-dir"].empty()) {
100 if (::arg()["chroot"].empty())
101 socketname = LOCALSTATEDIR;
102 else
103 socketname = ::arg()["chroot"] + "/";
104 } else if (!::arg()["socket-dir"].empty() && !::arg()["chroot"].empty()) {
105 socketname = ::arg()["chroot"] + ::arg()["socket-dir"];
106 }
107
108 socketname += "/" + s_programname + ".controlsocket";
109 cleanSlashes(socketname);
110
111 try {
112 string command=commands[0];
113 shared_ptr<DynMessenger> D;
114 if(::arg()["remote-address"].empty())
115 D=shared_ptr<DynMessenger>(new DynMessenger(socketname));
116 else {
117 uint16_t port;
118 try {
119 port = static_cast<uint16_t>(pdns_stou(::arg()["remote-port"]));
120 }
121 catch(...) {
122 cerr<<"Unable to convert '"<<::arg()["remote-port"]<<"' to a port number for connecting to remote PowerDNS\n";
123 exit(99);
124 }
125
126 D=shared_ptr<DynMessenger>(new DynMessenger(ComboAddress(::arg()["remote-address"], port), ::arg()["secret"]));
127 }
128
129 string message;
130 for(vector<string>::const_iterator i=commands.begin();i!=commands.end();++i) {
131 if(i!=commands.begin())
132 message+=" ";
133 message+=*i;
134 }
135
136 if(command=="show") {
137 message="SHOW ";
138 for(unsigned int n=1;n<commands.size();n++) {
139 message+=commands[n];
140 message+=" ";
141 }
142 }
143 else if(command=="list") {
144 message="SHOW *";
145 command="show";
146 }
147 else if(command=="quit" || command=="QUIT") {
148 message="QUIT";
149 }
150 else if(command=="status" || command=="STATUS") {
151 message="STATUS";
152 }
153 else if(command=="version" || command=="VERSION") {
154 message="VERSION";
155 }
156
157
158 if(D->send(message)<0) {
159 cerr<<"Error sending command"<<endl;
160 return 1;
161 }
162
163 string resp=D->receive();
164 if(resp.compare(0, 7, "Unknown") == 0) {
165 cerr<<resp<<endl;
166 return 1;
167 }
168
169 cout<<resp<<endl;
170 }
171 catch(TimeoutException &ae) {
172 cerr<<"Timeout error: "<<ae.reason<<endl;
173 return 2;
174 }
175 catch(PDNSException &ae) {
176 cerr<<"Fatal error: "<<ae.reason<<endl;
177 return 1;
178 }
179 catch(const std::runtime_error& e) {
180 cerr<<"Runtime error: "<<e.what()<<endl;
181 return 2;
182 }
183 return 0;
184 }
185
186