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 #pragma once 23 #include <sys/types.h> 24 #include <sys/wait.h> 25 26 #include <string> 27 #include "pdns/arguments.hh" 28 #include "pdns/dns.hh" 29 #include "pdns/dnsbackend.hh" 30 #include "pdns/dnspacket.hh" 31 #include "pdns/logger.hh" 32 #include "pdns/namespaces.hh" 33 #include "pdns/pdnsexception.hh" 34 #include "pdns/sstuff.hh" 35 #include "pdns/json.hh" 36 #include "pdns/lock.hh" 37 #include "yahttp/yahttp.hpp" 38 39 #ifdef REMOTEBACKEND_ZEROMQ 40 #include <zmq.h> 41 42 // If the available ZeroMQ library version is < 2.x, create macros for the zmq_msg_send/recv functions 43 #ifndef HAVE_ZMQ_MSG_SEND 44 #define zmq_msg_send(msg, socket, flags) zmq_send(socket, msg, flags) 45 #define zmq_msg_recv(msg, socket, flags) zmq_recv(socket, msg, flags) 46 #endif 47 #endif 48 49 using json11::Json; 50 51 class Connector 52 { 53 public: ~Connector()54 virtual ~Connector(){}; 55 bool send(Json& value); 56 bool recv(Json& value); 57 virtual int send_message(const Json& input) = 0; 58 virtual int recv_message(Json& output) = 0; 59 60 protected: asString(const Json & value)61 string asString(const Json& value) 62 { 63 if (value.is_number()) 64 return std::to_string(value.int_value()); 65 if (value.is_bool()) 66 return (value.bool_value() ? "1" : "0"); 67 if (value.is_string()) 68 return value.string_value(); 69 throw JsonException("Json value not convertible to String"); 70 }; 71 }; 72 73 // fwd declarations 74 class UnixsocketConnector : public Connector 75 { 76 public: 77 UnixsocketConnector(std::map<std::string, std::string> options); 78 virtual ~UnixsocketConnector(); 79 virtual int send_message(const Json& input); 80 virtual int recv_message(Json& output); 81 82 private: 83 ssize_t read(std::string& data); 84 ssize_t write(const std::string& data); 85 void reconnect(); 86 std::map<std::string, std::string> options; 87 int fd; 88 std::string path; 89 bool connected; 90 int timeout; 91 }; 92 93 class HTTPConnector : public Connector 94 { 95 public: 96 HTTPConnector(std::map<std::string, std::string> options); 97 ~HTTPConnector(); 98 99 virtual int send_message(const Json& input); 100 virtual int recv_message(Json& output); 101 102 private: 103 std::string d_url; 104 std::string d_url_suffix; 105 std::string d_data; 106 int timeout; 107 bool d_post; 108 bool d_post_json; 109 void restful_requestbuilder(const std::string& method, const Json& parameters, YaHTTP::Request& req); 110 void post_requestbuilder(const Json& input, YaHTTP::Request& req); 111 void addUrlComponent(const Json& parameters, const string& element, std::stringstream& ss); 112 std::string buildMemberListArgs(std::string prefix, const Json& args); 113 std::unique_ptr<Socket> d_socket; 114 ComboAddress d_addr; 115 std::string d_host; 116 uint16_t d_port; 117 }; 118 119 #ifdef REMOTEBACKEND_ZEROMQ 120 class ZeroMQConnector : public Connector 121 { 122 public: 123 ZeroMQConnector(std::map<std::string, std::string> options); 124 virtual ~ZeroMQConnector(); 125 virtual int send_message(const Json& input); 126 virtual int recv_message(Json& output); 127 128 private: 129 void connect(); 130 std::string d_endpoint; 131 int d_timeout; 132 int d_timespent; 133 std::map<std::string, std::string> d_options; 134 std::unique_ptr<void, int (*)(void*)> d_ctx; 135 std::unique_ptr<void, int (*)(void*)> d_sock; 136 }; 137 #endif 138 139 class PipeConnector : public Connector 140 { 141 public: 142 PipeConnector(std::map<std::string, std::string> options); 143 ~PipeConnector(); 144 145 virtual int send_message(const Json& input); 146 virtual int recv_message(Json& output); 147 148 private: 149 void launch(); 150 bool checkStatus(); 151 152 std::string command; 153 std::map<std::string, std::string> options; 154 155 int d_fd1[2], d_fd2[2]; 156 int d_pid; 157 int d_timeout; 158 std::unique_ptr<FILE, int (*)(FILE*)> d_fp{nullptr, fclose}; 159 }; 160 161 class RemoteBackend : public DNSBackend 162 { 163 public: 164 RemoteBackend(const std::string& suffix = ""); 165 ~RemoteBackend(); 166 167 void lookup(const QType& qtype, const DNSName& qdomain, int zoneId = -1, DNSPacket* pkt_p = nullptr) override; 168 bool get(DNSResourceRecord& rr) override; 169 bool list(const DNSName& target, int domain_id, bool include_disabled = false) override; 170 171 bool getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string>>& meta) override; 172 bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta) override; 173 bool getDomainKeys(const DNSName& name, std::vector<DNSBackend::KeyData>& keys) override; 174 bool getTSIGKey(const DNSName& name, DNSName* algorithm, std::string* content) override; 175 bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) override; 176 bool setDomainMetadata(const DNSName& name, const string& kind, const std::vector<std::basic_string<char>>& meta) override; 177 bool removeDomainKey(const DNSName& name, unsigned int id) override; 178 bool addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) override; 179 bool activateDomainKey(const DNSName& name, unsigned int id) override; 180 bool deactivateDomainKey(const DNSName& name, unsigned int id) override; 181 bool publishDomainKey(const DNSName& name, unsigned int id) override; 182 bool unpublishDomainKey(const DNSName& name, unsigned int id) override; 183 bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial = true) override; 184 void setNotified(uint32_t id, uint32_t serial) override; 185 bool doesDNSSEC() override; 186 bool superMasterBackend(const string& ip, const DNSName& domain, const vector<DNSResourceRecord>& nsset, string* nameserver, string* account, DNSBackend** ddb) override; 187 bool createSlaveDomain(const string& ip, const DNSName& domain, const string& nameserver, const string& account) override; 188 bool replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector<DNSResourceRecord>& rrset) override; 189 bool feedRecord(const DNSResourceRecord& r, const DNSName& ordername, bool ordernameIsNSEC3 = false) override; 190 bool feedEnts(int domain_id, map<DNSName, bool>& nonterm) override; 191 bool feedEnts3(int domain_id, const DNSName& domain, map<DNSName, bool>& nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) override; 192 bool startTransaction(const DNSName& domain, int domain_id) override; 193 bool commitTransaction() override; 194 bool abortTransaction() override; 195 bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) override; 196 bool deleteTSIGKey(const DNSName& name) override; 197 bool getTSIGKeys(std::vector<struct TSIGKey>& keys) override; 198 string directBackendCmd(const string& querystr) override; 199 bool searchRecords(const string& pattern, int maxResults, vector<DNSResourceRecord>& result) override; 200 bool searchComments(const string& pattern, int maxResults, vector<Comment>& result) override; 201 void getAllDomains(vector<DomainInfo>* domains, bool include_disabled = false) override; 202 void getUpdatedMasters(vector<DomainInfo>* domains) override; 203 void alsoNotifies(const DNSName& domain, set<string>* ips) override; 204 void getUnfreshSlaveInfos(vector<DomainInfo>* domains) override; 205 void setStale(uint32_t domain_id) override; 206 void setFresh(uint32_t domain_id) override; 207 208 static DNSBackend* maker(); 209 210 private: 211 int build(); 212 std::unique_ptr<Connector> connector; 213 bool d_dnssec; 214 Json d_result; 215 int d_index; 216 int64_t d_trxid; 217 std::string d_connstr; 218 219 bool send(Json& value); 220 bool recv(Json& value); 221 void makeErrorAndThrow(Json& value); 222 asString(const Json & value)223 string asString(const Json& value) 224 { 225 if (value.is_number()) 226 return std::to_string(value.int_value()); 227 if (value.is_bool()) 228 return (value.bool_value() ? "1" : "0"); 229 if (value.is_string()) 230 return value.string_value(); 231 throw JsonException("Json value not convertible to String"); 232 }; 233 asBool(const Json & value)234 bool asBool(const Json& value) 235 { 236 if (value.is_bool()) 237 return value.bool_value(); 238 try { 239 string val = asString(value); 240 if (val == "0") 241 return false; 242 if (val == "1") 243 return true; 244 } 245 catch (const JsonException&) { 246 }; 247 throw JsonException("Json value not convertible to boolean"); 248 }; 249 250 void parseDomainInfo(const json11::Json& obj, DomainInfo& di); 251 }; 252