From bbd3f8b280dc9476a3d6b38aabe2cbbedf11652b Mon Sep 17 00:00:00 2001 From: Aki Tuomi Date: Sat, 1 Jun 2013 21:28:47 +0300 Subject: [PATCH] Fixed bug where setNotified did not add parameters to query Support for superMaster, slaving and soa calculations superMasterBackend implementation createSlaveDomain implementation Removed references to GSQLBackend replaceRRSet implementation feedEnts, feedEnts3 implementation and few AddMember additions where forgotten Rest of the methods Final touches to remotebackend Partial support for new slave methods Added transaction ID for start/abort/commiTransaction --- modules/remotebackend/httpconnector.cc | 72 +++++++ modules/remotebackend/remotebackend.cc | 257 ++++++++++++++++++++++++- modules/remotebackend/remotebackend.hh | 13 +- 3 files changed, 337 insertions(+), 5 deletions(-) diff --git a/modules/remotebackend/httpconnector.cc b/modules/remotebackend/httpconnector.cc index af49cd4c67..8706d2a8fc 100644 --- a/modules/remotebackend/httpconnector.cc +++ b/modules/remotebackend/httpconnector.cc @@ -66,6 +66,8 @@ void HTTPConnector::requestbuilder(const std::string &method, const rapidjson::V std::stringstream ss; std::string sparam; char *tmpstr; + size_t k=0; + k=k; // special names are qname, name, zonename, kind, others go to headers @@ -106,6 +108,76 @@ void HTTPConnector::requestbuilder(const std::string &method, const rapidjson::V curl_easy_setopt(d_c, CURLOPT_COPYPOSTFIELDS, postfields); curl_free(tmpstr); delete postfields; + } else if (method == "superMasterBackend") { + std::stringstream ss2; + addUrlComponent(parameters, "ip", ss); + addUrlComponent(parameters, "domain", ss); + // then we need to serialize rrset payload into POST + for(rapidjson::Value::ConstValueIterator itr = parameters["nsset"].Begin(), k=0; itr != parameters["nsset"].End(); itr++, k++) { + for (rapidjson::Value::ConstMemberIterator itr2 = itr->MemberBegin(); itr2 != itr->MemberEnd(); itr2++) { + ss2 << "nsset[" << k << "][" << itr2->name.GetString() << "]="; + if (itr2->value.IsUint()) { + ss2 << itr2->value.GetUint(); + } else if (itr2->value.IsInt()) { + ss2 << itr2->value.GetInt(); + } else if (itr2->value.IsBool()) { + ss2 << (itr2->value.GetBool() ? 1 : 0); + } else if (itr2->value.IsString()) { + tmpstr = curl_easy_escape(d_c, itr2->value.GetString(), 0); + ss2 << tmpstr; + curl_free(tmpstr); + } + } + } + // then give it to curl + std::string out = ss2.str(); + curl_easy_setopt(d_c, CURLOPT_POSTFIELDSIZE, out.size()); + curl_easy_setopt(d_c, CURLOPT_COPYPOSTFIELDS, out.c_str()); + } else if (method == "createSlaveDomain") { + addUrlComponent(parameters, "ip", ss); + addUrlComponent(parameters, "domain", ss); + addUrlComponent(parameters, "account", ss); + } else if (method == "replaceRRSet") { + std::stringstream ss2; + for(rapidjson::Value::ConstValueIterator itr = parameters["nsset"].Begin(), k=0; itr != parameters["nsset"].End(); itr++, k++) { + for (rapidjson::Value::ConstMemberIterator itr2 = itr->MemberBegin(); itr2 != itr->MemberEnd(); itr2++) { + ss2 << "rrset[" << k << "][" << itr2->name.GetString() << "]="; + if (itr2->value.IsUint()) { + ss2 << itr2->value.GetUint(); + } else if (itr2->value.IsInt()) { + ss2 << itr2->value.GetInt(); + } else if (itr2->value.IsBool()) { + ss2 << (itr2->value.GetBool() ? 1 : 0); + } else if (itr2->value.IsString()) { + tmpstr = curl_easy_escape(d_c, itr2->value.GetString(), 0); + ss2 << tmpstr; + curl_free(tmpstr); + } + } + } + // then give it to curl + std::string out = ss2.str(); + curl_easy_setopt(d_c, CURLOPT_POSTFIELDSIZE, out.size()); + curl_easy_setopt(d_c, CURLOPT_COPYPOSTFIELDS, out.c_str()); + } else if (method == "feedRecord") { + std::stringstream ss2; + for (rapidjson::Value::ConstMemberIterator itr2 = parameters["rr"].MemberBegin(); itr2 != parameters["rr"].MemberEnd(); itr2++) { + ss2 << "rr[" << itr2->name.GetString() << "]="; + if (itr2->value.IsUint()) { + ss2 << itr2->value.GetUint(); + } else if (itr2->value.IsInt()) { + ss2 << itr2->value.GetInt(); + } else if (itr2->value.IsBool()) { + ss2 << (itr2->value.GetBool() ? 1 : 0); + } else if (itr2->value.IsString()) { + tmpstr = curl_easy_escape(d_c, itr2->value.GetString(), 0); + ss2 << tmpstr; + curl_free(tmpstr); + } + } + std::string out = ss2.str(); + curl_easy_setopt(d_c, CURLOPT_POSTFIELDSIZE, out.size()); + curl_easy_setopt(d_c, CURLOPT_COPYPOSTFIELDS, out.c_str()); } else if (method == "setDomainMetadata") { int n=0; // copy all metadata values into post diff --git a/modules/remotebackend/remotebackend.cc b/modules/remotebackend/remotebackend.cc index 0e9d132dce..c6b58bc1ce 100644 --- a/modules/remotebackend/remotebackend.cc +++ b/modules/remotebackend/remotebackend.cc @@ -43,12 +43,16 @@ bool Connector::recv(rapidjson::Document &value) { return false; } +/** + * Standard ctor and dtor + */ RemoteBackend::RemoteBackend(const std::string &suffix) { setArgPrefix("remote"+suffix); build(getArg("connection-string")); this->d_dnssec = mustDo("dnssec"); this->d_index = -1; + this->d_trxid = 0; } RemoteBackend::~RemoteBackend() { @@ -351,7 +355,7 @@ bool RemoteBackend::removeDomainKey(const string& name, unsigned int id) { if (connector->send(query) == false || connector->recv(answer) == false) return false; - return answer["result"].GetBool(); + return true; } int RemoteBackend::addDomainKey(const string& name, const KeyData& key) { @@ -394,7 +398,7 @@ bool RemoteBackend::activateDomainKey(const string& name, unsigned int id) { if (connector->send(query) == false || connector->recv(answer) == false) return false; - return answer["result"].GetBool(); + return true; } bool RemoteBackend::deactivateDomainKey(const string& name, unsigned int id) { @@ -414,7 +418,7 @@ bool RemoteBackend::deactivateDomainKey(const string& name, unsigned int id) { if (connector->send(query) == false || connector->recv(answer) == false) return false; - return answer["result"].GetBool(); + return true; } bool RemoteBackend::doesDNSSEC() { @@ -500,12 +504,257 @@ void RemoteBackend::setNotified(uint32_t id, uint32_t serial) { parameters.SetObject(); JSON_ADD_MEMBER(parameters, "id", id, query.GetAllocator()); JSON_ADD_MEMBER(parameters, "serial", id, query.GetAllocator()); - + query.AddMember("parameters", parameters, query.GetAllocator()); + if (connector->send(query) == false || connector->recv(answer) == false) { L<&nsset, string *account, DNSBackend **ddb) +{ + rapidjson::Document query,answer; + rapidjson::Value parameters; + rapidjson::Value rrset; + + query.SetObject(); + JSON_ADD_MEMBER(query, "method", "superMasterBackend", query.GetAllocator()); + parameters.SetObject(); + JSON_ADD_MEMBER(parameters, "ip", ip.c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(parameters, "domain", domain.c_str(), query.GetAllocator()); + rrset.SetArray(); + rrset.Reserve(nsset.size(), query.GetAllocator()); + for(rapidjson::SizeType i = 0; i < nsset.size(); i++) { + rapidjson::Value &rr = rrset[i]; + rr.SetObject(); + JSON_ADD_MEMBER(rr, "qtype", nsset[i].qtype.getName().c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(rr, "qname", nsset[i].qname.c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(rr, "qclass", QClass::IN, query.GetAllocator()); + JSON_ADD_MEMBER(rr, "content", nsset[i].content.c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(rr, "ttl", nsset[i].ttl, query.GetAllocator()); + JSON_ADD_MEMBER(rr, "priority", nsset[i].priority, query.GetAllocator()); + JSON_ADD_MEMBER(rr, "auth", nsset[i].auth, query.GetAllocator()); + } + parameters.AddMember("nsset", rrset, query.GetAllocator()); + query.AddMember("parameters", parameters, query.GetAllocator()); + + if (connector->send(query) == false || connector->recv(answer) == false) + return false; + + // we are the backend + *ddb = this; + + // we allow simple true as well... + if (answer["result"].IsObject() && answer["result"].HasMember("account")) + *account = answer["result"]["account"].GetString(); + + return true; +} + +bool RemoteBackend::createSlaveDomain(const string &ip, const string &domain, const string &account) { + rapidjson::Document query,answer; + rapidjson::Value parameters; + query.SetObject(); + JSON_ADD_MEMBER(query, "method", "createSlaveDomain", query.GetAllocator()); + parameters.SetObject(); + JSON_ADD_MEMBER(parameters, "ip", ip.c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(parameters, "domain", domain.c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(parameters, "account", account.c_str(), query.GetAllocator()); + query.AddMember("parameters", parameters, query.GetAllocator()); + + if (connector->send(query) == false || connector->recv(answer) == false) + return false; + return true; +} + +bool RemoteBackend::replaceRRSet(uint32_t domain_id, const string& qname, const QType& qtype, const vector& rrset) { + rapidjson::Document query,answer; + rapidjson::Value parameters; + rapidjson::Value rj_rrset; + query.SetObject(); + JSON_ADD_MEMBER(query, "method", "replaceRRSet", query.GetAllocator()); + parameters.SetObject(); + JSON_ADD_MEMBER(parameters, "domain_id", domain_id, query.GetAllocator()); + JSON_ADD_MEMBER(parameters, "qname", qname.c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(parameters, "qtype", qtype.getName().c_str(), query.GetAllocator()); + rj_rrset.SetArray(); + rj_rrset.Reserve(rrset.size(), query.GetAllocator()); + + for(rapidjson::SizeType i = 0; i < rrset.size(); i++) { + rapidjson::Value &rr = rj_rrset[i]; + rr.SetObject(); + JSON_ADD_MEMBER(rr, "qtype", rrset[i].qtype.getName().c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(rr, "qname", rrset[i].qname.c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(rr, "qclass", QClass::IN, query.GetAllocator()); + JSON_ADD_MEMBER(rr, "content", rrset[i].content.c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(rr, "ttl", rrset[i].ttl, query.GetAllocator()); + JSON_ADD_MEMBER(rr, "priority", rrset[i].priority, query.GetAllocator()); + JSON_ADD_MEMBER(rr, "auth", rrset[i].auth, query.GetAllocator()); + } + parameters.AddMember("rrset", rj_rrset, query.GetAllocator()); + query.AddMember("parameters", parameters, query.GetAllocator()); + + if (connector->send(query) == false || connector->recv(answer) == false) + return false; + + return true; +} + +bool RemoteBackend::feedRecord(const DNSResourceRecord &rr, string *ordername) { + rapidjson::Document query,answer; + rapidjson::Value parameters; + query.SetObject(); + JSON_ADD_MEMBER(query, "method", "feedRecord", query.GetAllocator()); + parameters.SetObject(); + JSON_ADD_MEMBER(parameters, "qtype", rr.qtype.getName().c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(parameters, "qname", rr.qname.c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(parameters, "qclass", QClass::IN, query.GetAllocator()); + JSON_ADD_MEMBER(parameters, "content", rr.content.c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(parameters, "ttl", rr.ttl, query.GetAllocator()); + JSON_ADD_MEMBER(parameters, "priority", rr.priority, query.GetAllocator()); + JSON_ADD_MEMBER(parameters, "auth", rr.auth, query.GetAllocator()); + if (ordername) { + JSON_ADD_MEMBER(parameters, "ordername", ordername->c_str(), query.GetAllocator()); + } + query.AddMember("parameters", parameters, query.GetAllocator()); + + if (connector->send(query) == false || connector->recv(answer) == false) + return false; + return true; // XXX FIXME this API should not return 'true' I think -ahu +} + +bool RemoteBackend::feedEnts(int domain_id, set& nonterm) { + rapidjson::Document query,answer; + rapidjson::Value parameters; + rapidjson::Value nts; + query.SetObject(); + JSON_ADD_MEMBER(query, "method", "feedEnts", query.GetAllocator()); + parameters.SetObject(); + JSON_ADD_MEMBER(parameters, "domain_id", domain_id, query.GetAllocator()); + nts.SetArray(); + BOOST_FOREACH(const string &t, nonterm) { + nts.PushBack(t.c_str(), query.GetAllocator()); + } + parameters.AddMember("nonterm", nts, query.GetAllocator()); + query.AddMember("parameters", parameters, query.GetAllocator()); + + if (connector->send(query) == false || connector->recv(answer) == false) + return false; + return true; +} + +bool RemoteBackend::feedEnts3(int domain_id, const string &domain, set &nonterm, unsigned int times, const string &salt, bool narrow) { + rapidjson::Document query,answer; + rapidjson::Value parameters; + rapidjson::Value nts; + query.SetObject(); + JSON_ADD_MEMBER(query, "method", "feedEnts3", query.GetAllocator()); + parameters.SetObject(); + JSON_ADD_MEMBER(parameters, "domain_id", domain_id, query.GetAllocator()); + JSON_ADD_MEMBER(parameters, "domain", domain.c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(parameters, "times", times, query.GetAllocator()); + JSON_ADD_MEMBER(parameters, "salt", salt.c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(parameters, "narrow", narrow, query.GetAllocator()); + + nts.SetArray(); + BOOST_FOREACH(const string &t, nonterm) { + nts.PushBack(t.c_str(), query.GetAllocator()); + } + parameters.AddMember("nonterm", nts, query.GetAllocator()); + query.AddMember("parameters", parameters, query.GetAllocator()); + + if (connector->send(query) == false || connector->recv(answer) == false) + return false; + return true; +} + +bool RemoteBackend::startTransaction(const string &domain, int domain_id) { + rapidjson::Document query,answer; + rapidjson::Value parameters; + this->d_trxid = time((time_t*)NULL); + + query.SetObject(); + JSON_ADD_MEMBER(query, "method", "startTransaction", query.GetAllocator()); + parameters.SetObject(); + JSON_ADD_MEMBER(parameters, "domain", domain.c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(parameters, "domain_id", domain_id, query.GetAllocator()); + JSON_ADD_MEMBER(parameters, "trxid", d_trxid, query.GetAllocator()); + + query.AddMember("parameters", parameters, query.GetAllocator()); + + if (connector->send(query) == false || connector->recv(answer) == false) { + d_trxid = -1; + return false; + } + return true; + +} +bool RemoteBackend::commitTransaction() { + rapidjson::Document query,answer; + rapidjson::Value parameters; + + query.SetObject(); + JSON_ADD_MEMBER(query, "method", "abortTransaction", query.GetAllocator()); + parameters.SetObject(); + JSON_ADD_MEMBER(parameters, "trxid", d_trxid, query.GetAllocator()); + query.AddMember("parameters", parameters, query.GetAllocator()); + + d_trxid = -1; + if (connector->send(query) == false || connector->recv(answer) == false) + return false; + return true; +} + +bool RemoteBackend::abortTransaction() { + rapidjson::Document query,answer; + rapidjson::Value parameters; + + query.SetObject(); + JSON_ADD_MEMBER(query, "method", "commitTransaction", query.GetAllocator()); + parameters.SetObject(); + JSON_ADD_MEMBER(parameters, "trxid", d_trxid, query.GetAllocator()); + query.AddMember("parameters", parameters, query.GetAllocator()); + + d_trxid = -1; + if (connector->send(query) == false || connector->recv(answer) == false) + return false; + return true; +} + +bool RemoteBackend::calculateSOASerial(const string& domain, const SOAData& sd, time_t& serial) { + rapidjson::Document query,answer; + rapidjson::Value parameters; + rapidjson::Value soadata; + + query.SetObject(); + JSON_ADD_MEMBER(query, "method", "calculateSOASerial", query.GetAllocator()); + parameters.SetObject(); + JSON_ADD_MEMBER(parameters, "domain", domain.c_str(), query.GetAllocator()); + soadata.SetObject(); + JSON_ADD_MEMBER(soadata, "qname", sd.qname.c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(soadata, "nameserver", sd.nameserver.c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(soadata, "hostmaster", sd.hostmaster.c_str(), query.GetAllocator()); + JSON_ADD_MEMBER(soadata, "ttl", sd.ttl, query.GetAllocator()); + JSON_ADD_MEMBER(soadata, "serial", sd.serial, query.GetAllocator()); + JSON_ADD_MEMBER(soadata, "refresh", sd.refresh, query.GetAllocator()); + JSON_ADD_MEMBER(soadata, "retry", sd.retry, query.GetAllocator()); + JSON_ADD_MEMBER(soadata, "expire", sd.expire, query.GetAllocator()); + JSON_ADD_MEMBER(soadata, "default_ttl", sd.default_ttl, query.GetAllocator()); + JSON_ADD_MEMBER(soadata, "domain_id", sd.domain_id, query.GetAllocator()); + JSON_ADD_MEMBER(soadata, "scopeMask", sd.scopeMask, query.GetAllocator()); + parameters.AddMember("sd", soadata, query.GetAllocator()); + query.AddMember("parameters", parameters, query.GetAllocator()); + + if (connector->send(query) == false || connector->recv(answer) == false) + return false; + + if (answer["result"].IsInt64() == false) + return false; + + serial = answer["result"].GetInt64(); + return true; +} + DNSBackend *RemoteBackend::maker() { try { diff --git a/modules/remotebackend/remotebackend.hh b/modules/remotebackend/remotebackend.hh index 7bc02b71e3..8984aa089f 100644 --- a/modules/remotebackend/remotebackend.hh +++ b/modules/remotebackend/remotebackend.hh @@ -111,6 +111,16 @@ class RemoteBackend : public DNSBackend virtual bool getDomainInfo(const string&, DomainInfo&); virtual void setNotified(uint32_t id, uint32_t serial); virtual bool doesDNSSEC(); + virtual bool superMasterBackend(const string &ip, const string &domain, const vector&nsset, string *account, DNSBackend **ddb); + virtual bool createSlaveDomain(const string &ip, const string &domain, const string &account); + virtual bool replaceRRSet(uint32_t domain_id, const string& qname, const QType& qt, const vector& rrset); + virtual bool feedRecord(const DNSResourceRecord &r, string *ordername); + virtual bool feedEnts(int domain_id, set& nonterm); + virtual bool feedEnts3(int domain_id, const string &domain, set &nonterm, unsigned int times, const string &salt, bool narrow); + virtual bool startTransaction(const string &domain, int domain_id); + virtual bool commitTransaction(); + virtual bool abortTransaction(); + virtual bool calculateSOASerial(const string& domain, const SOAData& sd, time_t& serial); static DNSBackend *maker(); @@ -119,6 +129,7 @@ class RemoteBackend : public DNSBackend Connector *connector; bool d_dnssec; rapidjson::Document *d_result; - int d_index; + int d_index; + time_t d_trxid; }; #endif -- 2.47.3