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 "remotebackend.hh"
27 static const char *kBackendId
= "[RemoteBackend]";
30 * Forwarder for value. This is just in case
31 * we need to do some treatment to the value before
32 * sending it downwards.
34 bool Connector::send(Json
& value
) {
35 return send_message(value
)>0;
39 * Helper for handling receiving of data.
40 * Basically what happens here is that we check
41 * that the receiving happened ok, and extract
42 * result. Logging is performed here, too.
44 bool Connector::recv(Json
& value
) {
45 if (recv_message(value
)>0) {
48 if (value
["result"] == Json())
50 if (value
["result"].is_bool() && boolFromJson(value
, "result", false) == false)
52 for(const auto& message
: value
["log"].array_items())
53 L
<<Logger::Info
<<"[remotebackend]: "<< message
.string_value() <<std::endl
;
60 * Standard ctor and dtor
62 RemoteBackend::RemoteBackend(const std::string
&suffix
)
64 setArgPrefix("remote"+suffix
);
66 this->d_connstr
= getArg("connection-string");
67 this->d_dnssec
= mustDo("dnssec");
74 RemoteBackend::~RemoteBackend() {
75 if (connector
!= NULL
) {
80 bool RemoteBackend::send(Json
& value
) {
82 return connector
->send(value
);
83 } catch (PDNSException
&ex
) {
84 L
<<Logger::Error
<<"Exception caught when sending: "<<ex
.reason
<<std::endl
;
87 delete this->connector
;
92 bool RemoteBackend::recv(Json
& value
) {
94 return connector
->recv(value
);
95 } catch (PDNSException
&ex
) {
96 L
<<Logger::Error
<<"Exception caught when receiving: "<<ex
.reason
<<std::endl
;
98 L
<<Logger::Error
<<"Exception caught when receiving"<<std::endl
;;
101 delete this->connector
;
108 * Builds connector based on options
109 * Currently supports unix,pipe and http
111 int RemoteBackend::build() {
112 std::vector
<std::string
> parts
;
115 std::map
<std::string
, std::string
> options
;
117 // connstr is of format "type:options"
119 pos
= d_connstr
.find_first_of(":");
120 if (pos
== std::string::npos
)
121 throw PDNSException("Invalid connection string: malformed");
123 type
= d_connstr
.substr(0, pos
);
124 opts
= d_connstr
.substr(pos
+1);
126 // tokenize the string on comma
127 stringtok(parts
, opts
, ",");
129 // find out some options and parse them while we're at it
130 for(const auto& opt
: parts
) {
132 // make sure there is something else than air in the option...
133 if (opt
.find_first_not_of(" ") == std::string::npos
) continue;
135 // split it on '='. if not found, we treat it as "yes"
136 pos
= opt
.find_first_of("=");
138 if (pos
== std::string::npos
) {
142 key
= opt
.substr(0,pos
);
143 val
= opt
.substr(pos
+1);
148 // connectors know what they are doing
149 if (type
== "unix") {
150 this->connector
= new UnixsocketConnector(options
);
151 } else if (type
== "http") {
152 this->connector
= new HTTPConnector(options
);
153 } else if (type
== "zeromq") {
154 #ifdef REMOTEBACKEND_ZEROMQ
155 this->connector
= new ZeroMQConnector(options
);
157 throw PDNSException("Invalid connection string: zeromq connector support not enabled. Recompile with --enable-remotebackend-zeromq");
159 } else if (type
== "pipe") {
160 this->connector
= new PipeConnector(options
);
162 throw PDNSException("Invalid connection string: unknown connector");
169 * The functions here are just remote json stubs that send and receive the method call
170 * data is mainly left alone, some defaults are assumed.
172 void RemoteBackend::lookup(const QType
&qtype
, const DNSName
& qdomain
, DNSPacket
*pkt_p
, int zoneId
) {
174 throw PDNSException("Attempt to lookup while one running");
176 string localIP
="0.0.0.0";
177 string remoteIP
="0.0.0.0";
178 string realRemote
="0.0.0.0/0";
181 localIP
=pkt_p
->getLocal().toString();
182 realRemote
= pkt_p
->getRealRemote().toString();
183 remoteIP
= pkt_p
->getRemote().toString();
186 Json query
= Json::object
{
187 { "method", "lookup" },
188 { "parameters", Json::object
{
189 { "qtype", qtype
.getName() },
190 { "qname", qdomain
.toString() },
191 { "remote", remoteIP
},
192 { "local", localIP
},
193 { "real-remote", realRemote
},
194 { "zone-id", zoneId
}
198 if (this->send(query
) == false || this->recv(d_result
) == false) {
202 // OK. we have result parameters in result. do not process empty result.
203 if (d_result
["result"].is_array() == false || d_result
["result"].array_items().size() < 1)
209 bool RemoteBackend::list(const DNSName
& target
, int domain_id
, bool include_disabled
) {
211 throw PDNSException("Attempt to lookup while one running");
213 Json query
= Json::object
{
214 { "method", "list" },
215 { "parameters", Json::object
{
216 { "zonename", target
.toString() },
217 { "domain_id", domain_id
},
218 { "include_disabled", include_disabled
}
222 if (this->send(query
) == false || this->recv(d_result
) == false)
224 if (d_result
["result"].is_array() == false || d_result
["result"].array_items().size() < 1)
231 bool RemoteBackend::get(DNSResourceRecord
&rr
) {
232 if (d_index
== -1) return false;
234 rr
.qtype
= stringFromJson(d_result
["result"][d_index
], "qtype");
235 rr
.qname
= DNSName(stringFromJson(d_result
["result"][d_index
], "qname"));
236 rr
.qclass
= QClass::IN
;
237 rr
.content
= stringFromJson(d_result
["result"][d_index
], "content");
238 rr
.ttl
= d_result
["result"][d_index
]["ttl"].int_value();
239 rr
.domain_id
= intFromJson(d_result
["result"][d_index
], "domain_id", -1);
241 rr
.auth
= intFromJson(d_result
["result"][d_index
], "auth", 1);
244 rr
.scopeMask
= d_result
["result"][d_index
]["scopeMask"].int_value();
247 // id index is out of bounds, we know the results end here.
248 if (d_index
== static_cast<int>(d_result
["result"].array_items().size())) {
255 bool RemoteBackend::getBeforeAndAfterNamesAbsolute(uint32_t id
, const DNSName
& qname
, DNSName
& unhashed
, DNSName
& before
, DNSName
& after
) {
256 // no point doing dnssec if it's not supported
257 if (d_dnssec
== false) return false;
259 Json query
= Json::object
{
260 { "method", "getBeforeAndAfterNamesAbsolute" },
261 { "parameters", Json::object
{
262 { "id", Json(static_cast<double>(id
)) },
263 { "qname", qname
.toString() }
268 if (this->send(query
) == false || this->recv(answer
) == false)
271 unhashed
= DNSName(stringFromJson(answer
["result"], "unhashed"));
274 if (answer
["result"]["before"] != Json())
275 before
= DNSName(stringFromJson(answer
["result"], "before"));
276 if (answer
["result"]["after"] != Json())
277 after
= DNSName(stringFromJson(answer
["result"], "after"));
282 bool RemoteBackend::getAllDomainMetadata(const DNSName
& name
, std::map
<std::string
, std::vector
<std::string
> >& meta
) {
283 Json query
= Json::object
{
284 { "method", "getAllDomainMetadata" },
285 { "parameters", Json::object
{
286 { "name", name
.toString() }
290 if (this->send(query
) == false)
296 // not mandatory to implement
297 if (this->recv(answer
) == false)
300 for(const auto& pair
: answer
["result"].object_items()) {
301 if (pair
.second
.is_array()) {
302 for(const auto& val
: pair
.second
.array_items())
303 meta
[pair
.first
].push_back(asString(val
));
305 meta
[pair
.first
].push_back(asString(pair
.second
));
312 bool RemoteBackend::getDomainMetadata(const DNSName
& name
, const std::string
& kind
, std::vector
<std::string
>& meta
) {
313 Json query
= Json::object
{
314 { "method", "getDomainMetadata" },
315 { "parameters", Json::object
{
316 { "name", name
.toString() },
321 if (this->send(query
) == false)
327 // not mandatory to implement
328 if (this->recv(answer
) == false)
331 if (answer
["result"].is_array()) {
332 for(const auto& row
: answer
["result"].array_items())
333 meta
.push_back(row
.string_value());
334 } else if (answer
["result"].is_string()) {
335 meta
.push_back(answer
["result"].string_value());
341 bool RemoteBackend::setDomainMetadata(const DNSName
& name
, const std::string
& kind
, const std::vector
<std::string
>& meta
) {
342 Json query
= Json::object
{
343 { "method", "setDomainMetadata" },
344 { "parameters", Json::object
{
345 { "name", name
.toString() },
352 if (this->send(query
) == false || this->recv(answer
) == false)
355 return boolFromJson(answer
, "result", false);
359 bool RemoteBackend::getDomainKeys(const DNSName
& name
, std::vector
<DNSBackend::KeyData
>& keys
) {
360 // no point doing dnssec if it's not supported
361 if (d_dnssec
== false) return false;
363 Json query
= Json::object
{
364 { "method", "getDomainKeys" },
365 { "parameters", Json::object
{
366 { "name", name
.toString() }
371 if (this->send(query
) == false || this->recv(answer
) == false)
376 for(const auto& jsonKey
: answer
["result"].array_items()) {
377 DNSBackend::KeyData key
;
378 key
.id
= intFromJson(jsonKey
, "id");
379 key
.flags
= intFromJson(jsonKey
, "flags");
380 key
.active
= asBool(jsonKey
["active"]);
381 key
.content
= stringFromJson(jsonKey
, "content");
388 bool RemoteBackend::removeDomainKey(const DNSName
& name
, unsigned int id
) {
389 // no point doing dnssec if it's not supported
390 if (d_dnssec
== false) return false;
392 Json query
= Json::object
{
393 { "method", "removeDomainKey" },
394 { "parameters", Json::object
{
395 { "name", name
.toString() },
396 { "id", static_cast<int>(id
) }
401 if (this->send(query
) == false || this->recv(answer
) == false)
407 bool RemoteBackend::addDomainKey(const DNSName
& name
, const KeyData
& key
, int64_t& id
) {
408 // no point doing dnssec if it's not supported
409 if (d_dnssec
== false) return false;
411 Json query
= Json::object
{
412 { "method", "addDomainKey" },
413 { "parameters", Json::object
{
414 { "name", name
.toString() },
415 { "key", Json::object
{
416 { "flags", static_cast<int>(key
.flags
) },
417 { "active", key
.active
},
418 { "content", key
.content
}
424 if (this->send(query
) == false || this->recv(answer
) == false)
427 id
= answer
["result"].int_value();
431 bool RemoteBackend::activateDomainKey(const DNSName
& name
, unsigned int id
) {
432 // no point doing dnssec if it's not supported
433 if (d_dnssec
== false) return false;
435 Json query
= Json::object
{
436 { "method", "activateDomainKey" },
437 { "parameters", Json::object
{
438 { "name", name
.toString() },
439 { "id", static_cast<int>(id
) }
444 if (this->send(query
) == false || this->recv(answer
) == false)
450 bool RemoteBackend::deactivateDomainKey(const DNSName
& name
, unsigned int id
) {
451 // no point doing dnssec if it's not supported
452 if (d_dnssec
== false) return false;
454 Json query
= Json::object
{
455 { "method", "deactivateDomainKey" },
456 { "parameters", Json::object
{
457 { "name", name
.toString() },
458 { "id", static_cast<int>(id
) }
463 if (this->send(query
) == false || this->recv(answer
) == false)
469 bool RemoteBackend::doesDNSSEC() {
473 bool RemoteBackend::getTSIGKey(const DNSName
& name
, DNSName
* algorithm
, std::string
* content
) {
474 // no point doing dnssec if it's not supported
475 if (d_dnssec
== false) return false;
477 Json query
= Json::object
{
478 { "method", "getTSIGKey" },
479 { "parameters", Json::object
{
480 { "name", name
.toString() }
485 if (this->send(query
) == false || this->recv(answer
) == false)
488 (*algorithm
) = DNSName(stringFromJson(answer
["result"], "algorithm"));
489 (*content
) = stringFromJson(answer
["result"], "content");
494 bool RemoteBackend::setTSIGKey(const DNSName
& name
, const DNSName
& algorithm
, const std::string
& content
) {
495 // no point doing dnssec if it's not supported
496 if (d_dnssec
== false) return false;
498 Json query
= Json::object
{
499 { "method", "setTSIGKey" },
500 { "parameters", Json::object
{
501 { "name", name
.toString() },
502 { "algorithm", algorithm
.toString() },
503 { "content", content
}
508 if (connector
->send(query
) == false || connector
->recv(answer
) == false)
514 bool RemoteBackend::deleteTSIGKey(const DNSName
& name
) {
515 // no point doing dnssec if it's not supported
516 if (d_dnssec
== false) return false;
517 Json query
= Json::object
{
518 { "method", "deleteTSIGKey" },
519 { "parameters", Json::object
{
520 { "name", name
.toString() }
525 if (connector
->send(query
) == false || connector
->recv(answer
) == false)
531 bool RemoteBackend::getTSIGKeys(std::vector
<struct TSIGKey
>& keys
) {
532 // no point doing dnssec if it's not supported
533 if (d_dnssec
== false) return false;
534 Json query
= Json::object
{
535 { "method", "getTSIGKeys" },
536 { "parameters", Json::object
{
541 if (connector
->send(query
) == false || connector
->recv(answer
) == false)
544 for(const auto& jsonKey
: answer
["result"].array_items()) {
546 key
.name
= DNSName(stringFromJson(jsonKey
, "name"));
547 key
.algorithm
= DNSName(stringFromJson(jsonKey
, "algorithm"));
548 key
.key
= stringFromJson(jsonKey
, "content");
555 void RemoteBackend::parseDomainInfo(const Json
&obj
, DomainInfo
&di
)
557 di
.id
= intFromJson(obj
, "id", -1);
558 di
.zone
= DNSName(stringFromJson(obj
, "zone"));
559 for(const auto& master
: obj
["masters"].array_items())
560 di
.masters
.push_back(master
.string_value());
562 di
.notified_serial
= static_cast<unsigned int>(doubleFromJson(obj
, "notified_serial", -1));
563 di
.serial
= static_cast<unsigned int>(obj
["serial"].number_value());
564 di
.last_check
= static_cast<time_t>(obj
["last_check"].number_value());
567 if (obj
["kind"].is_string()) {
568 kind
= stringFromJson(obj
, "kind");
570 if (kind
== "master") {
571 di
.kind
= DomainInfo::Master
;
572 } else if (kind
== "slave") {
573 di
.kind
= DomainInfo::Slave
;
575 di
.kind
= DomainInfo::Native
;
580 bool RemoteBackend::getDomainInfo(const DNSName
& domain
, DomainInfo
&di
) {
581 if (domain
.empty()) return false;
582 Json query
= Json::object
{
583 { "method", "getDomainInfo" },
584 { "parameters", Json::object
{
585 { "name", domain
.toString() }
590 if (this->send(query
) == false || this->recv(answer
) == false)
593 this->parseDomainInfo(answer
["result"], di
);
597 void RemoteBackend::setNotified(uint32_t id
, uint32_t serial
) {
598 Json query
= Json::object
{
599 { "method", "setNotified" },
600 { "parameters", Json::object
{
601 { "id", static_cast<double>(id
) },
602 { "serial", static_cast<double>(serial
) }
607 if (this->send(query
) == false || this->recv(answer
) == false) {
608 L
<<Logger::Error
<<kBackendId
<<" Failed to execute RPC for RemoteBackend::setNotified("<<id
<<","<<serial
<<")"<<endl
;
612 bool RemoteBackend::isMaster(const DNSName
& name
, const string
&ip
)
614 Json query
= Json::object
{
615 { "method", "isMaster" },
616 { "parameters", Json::object
{
617 { "name", name
.toString() },
623 if (this->send(query
) == false || this->recv(answer
) == false)
629 bool RemoteBackend::superMasterBackend(const string
&ip
, const DNSName
& domain
, const vector
<DNSResourceRecord
>&nsset
, string
* nameserver
, string
*account
, DNSBackend
**ddb
)
633 for(const auto& ns
: nsset
) {
634 rrset
.push_back(Json::object
{
635 { "qtype", ns
.qtype
.getName() },
636 { "qname", ns
.qname
.toString() },
637 { "qclass", QClass::IN
},
638 { "content", ns
.content
},
639 { "ttl", static_cast<int>(ns
.ttl
) },
644 Json query
= Json::object
{
645 { "method", "superMasterBackend" },
646 { "parameters", Json::object
{
648 { "domain", domain
.toString() },
656 if (this->send(query
) == false || this->recv(answer
) == false)
659 // we are the backend
662 // we allow simple true as well...
663 if (answer
["result"].is_object()) {
664 *account
= stringFromJson(answer
["result"], "account");
665 *nameserver
= stringFromJson(answer
["result"], "nameserver");
671 bool RemoteBackend::createSlaveDomain(const string
&ip
, const DNSName
& domain
, const string
& nameserver
, const string
&account
) {
672 Json query
= Json::object
{
673 { "method", "createSlaveDomain" },
674 { "parameters", Json::object
{
676 { "domain", domain
.toString() },
677 { "nameserver", nameserver
},
678 { "account", account
},
683 if (this->send(query
) == false || this->recv(answer
) == false)
688 bool RemoteBackend::replaceRRSet(uint32_t domain_id
, const DNSName
& qname
, const QType
& qtype
, const vector
<DNSResourceRecord
>& rrset
) {
689 Json::array json_rrset
;
690 for(const auto& rr
: rrset
) {
691 json_rrset
.push_back(Json::object
{
692 { "qtype", rr
.qtype
.getName() },
693 { "qname", rr
.qname
.toString() },
694 { "qclass", QClass::IN
},
695 { "content", rr
.content
},
696 { "ttl", static_cast<int>(rr
.ttl
) },
701 Json query
= Json::object
{
702 { "method", "replaceRRSet" },
703 { "parameters", Json::object
{
704 { "domain_id", static_cast<double>(domain_id
) },
705 { "qname", qname
.toString() },
706 { "qtype", qtype
.getName() },
707 { "trxid", static_cast<double>(d_trxid
) },
708 { "rrset", json_rrset
}
713 if (this->send(query
) == false || this->recv(answer
) == false)
719 bool RemoteBackend::feedRecord(const DNSResourceRecord
&rr
, const DNSName
&ordername
) {
720 Json query
= Json::object
{
721 { "method", "feedRecord" },
722 { "parameters", Json::object
{
723 { "rr", Json::object
{
724 { "qtype", rr
.qtype
.getName() },
725 { "qname", rr
.qname
.toString() },
726 { "qclass", QClass::IN
},
727 { "content", rr
.content
},
728 { "ttl", static_cast<int>(rr
.ttl
) },
730 { "ordername", (ordername
.empty()?Json():ordername
.toString()) }
732 { "trxid", static_cast<double>(d_trxid
) },
737 if (this->send(query
) == false || this->recv(answer
) == false)
739 return true; // XXX FIXME this API should not return 'true' I think -ahu
742 bool RemoteBackend::feedEnts(int domain_id
, map
<DNSName
,bool>& nonterm
) {
745 for(const auto& t
: nonterm
)
746 nts
.push_back(Json::object
{
747 { "nonterm", t
.first
.toString() },
751 Json query
= Json::object
{
752 { "method", "feedEnts" },
753 { "parameters", Json::object
{
754 { "domain_id", domain_id
},
755 { "trxid", static_cast<double>(d_trxid
) },
761 if (this->send(query
) == false || this->recv(answer
) == false)
766 bool RemoteBackend::feedEnts3(int domain_id
, const DNSName
& domain
, map
<DNSName
,bool>& nonterm
, const NSEC3PARAMRecordContent
& ns3prc
, bool narrow
) {
769 for(const auto& t
: nonterm
)
770 nts
.push_back(Json::object
{
771 { "nonterm", t
.first
.toString() },
775 Json query
= Json::object
{
776 { "method", "feedEnts3" },
777 { "parameters", Json::object
{
778 { "domain_id", domain_id
},
779 { "domain", domain
.toString() },
780 { "times", ns3prc
.d_iterations
},
781 { "salt", ns3prc
.d_salt
},
782 { "narrow", narrow
},
783 { "trxid", static_cast<double>(d_trxid
) },
789 if (this->send(query
) == false || this->recv(answer
) == false)
794 bool RemoteBackend::startTransaction(const DNSName
& domain
, int domain_id
) {
795 this->d_trxid
= time((time_t*)NULL
);
797 Json query
= Json::object
{
798 { "method", "startTransaction" },
799 { "parameters", Json::object
{
800 { "domain", domain
.toString() },
801 { "domain_id", domain_id
},
802 { "trxid", static_cast<double>(d_trxid
) }
807 if (this->send(query
) == false || this->recv(answer
) == false) {
814 bool RemoteBackend::commitTransaction() {
815 if (d_trxid
== -1) return false;
817 Json query
= Json::object
{
818 { "method", "commitTransaction" },
819 { "parameters", Json::object
{
820 { "trxid", static_cast<double>(d_trxid
) }
826 if (this->send(query
) == false || this->recv(answer
) == false)
831 bool RemoteBackend::abortTransaction() {
832 if (d_trxid
== -1) return false;
834 Json query
= Json::object
{
835 { "method", "abortTransaction" },
836 { "parameters", Json::object
{
837 { "trxid", static_cast<double>(d_trxid
) }
843 if (this->send(query
) == false || this->recv(answer
) == false)
848 bool RemoteBackend::calculateSOASerial(const DNSName
& domain
, const SOAData
& sd
, uint32_t& serial
) {
849 Json query
= Json::object
{
850 { "method", "calculateSOASerial" },
851 { "parameters", Json::object
{
852 { "domain", domain
.toString() },
853 { "sd", Json::object
{
854 { "qname", sd
.qname
.toString() },
855 { "nameserver", sd
.nameserver
.toString() },
856 { "hostmaster", sd
.hostmaster
.toString() },
857 { "ttl", static_cast<int>(sd
.ttl
) },
858 { "serial", static_cast<double>(sd
.serial
) },
859 { "refresh", static_cast<int>(sd
.refresh
) },
860 { "retry", static_cast<int>(sd
.retry
) },
861 { "expire", static_cast<int>(sd
.expire
) },
862 { "default_ttl", static_cast<int>(sd
.default_ttl
) },
863 { "domain_id", static_cast<int>(sd
.domain_id
) },
864 { "scopeMask", sd
.scopeMask
}
870 if (this->send(query
) == false || this->recv(answer
) == false)
873 serial
= static_cast<unsigned int>(doubleFromJson(answer
,"result"));
877 string
RemoteBackend::directBackendCmd(const string
& querystr
) {
878 Json query
= Json::object
{
879 { "method", "directBackendCmd" },
880 { "parameters", Json::object
{
881 { "query", querystr
}
886 if (this->send(query
) == false || this->recv(answer
) == false)
887 return "backend command failed";
889 return asString(answer
["result"]);
892 bool RemoteBackend::searchRecords(const string
&pattern
, int maxResults
, vector
<DNSResourceRecord
>& result
)
894 Json query
= Json::object
{
895 { "method", "searchRecords" },
896 { "parameters", Json::object
{
897 { "pattern", pattern
},
898 { "maxResults", maxResults
}
903 if (this->send(query
) == false || this->recv(answer
) == false)
906 if (answer
["result"].is_array() == false)
909 for(const auto& row
: answer
["result"].array_items()) {
910 DNSResourceRecord rr
;
911 rr
.qtype
= stringFromJson(row
, "qtype");
912 rr
.qname
= DNSName(stringFromJson(row
, "qname"));
913 rr
.qclass
= QClass::IN
;
914 rr
.content
= stringFromJson(row
, "content");
915 rr
.ttl
= row
["ttl"].int_value();
916 rr
.domain_id
= intFromJson(row
, "domain_id", -1);
918 rr
.auth
= intFromJson(row
, "auth", 1);
921 rr
.scopeMask
= row
["scopeMask"].int_value();
922 result
.push_back(rr
);
928 bool RemoteBackend::searchComments(const string
&pattern
, int maxResults
, vector
<Comment
>& result
)
930 // FIXME: Implement Comment API
934 void RemoteBackend::getAllDomains(vector
<DomainInfo
> *domains
, bool include_disabled
)
936 Json query
= Json::object
{
937 { "method", "getAllDomains" },
938 { "parameters", Json::object
{
939 { "include_disabled", include_disabled
}
944 if (this->send(query
) == false || this->recv(answer
) == false)
947 if (answer
["result"].is_array() == false)
950 for(const auto& row
: answer
["result"].array_items()) {
952 this->parseDomainInfo(row
, di
);
953 domains
->push_back(di
);
957 DNSBackend
*RemoteBackend::maker()
960 return new RemoteBackend();
963 L
<<Logger::Error
<<kBackendId
<<" Unable to instantiate a remotebackend!"<<endl
;
970 class RemoteBackendFactory
: public BackendFactory
973 RemoteBackendFactory() : BackendFactory("remote") {}
975 void declareArguments(const std::string
&suffix
="")
977 declare(suffix
,"dnssec","Enable dnssec support","no");
978 declare(suffix
,"connection-string","Connection string","");
981 DNSBackend
*make(const std::string
&suffix
="")
983 return new RemoteBackend(suffix
);
994 RemoteLoader::RemoteLoader() {
995 BackendMakers().report(new RemoteBackendFactory
);
996 L
<< Logger::Info
<< kBackendId
<< " This is the remote backend version " VERSION
998 << " (" __DATE__
" " __TIME__
")"
1000 << " reporting" << endl
;
1003 static RemoteLoader remoteloader
;