From: Otto Date: Wed, 3 Mar 2021 09:45:04 +0000 (+0100) Subject: Start format checks for pdns/modules X-Git-Tag: dnsdist-1.6.0-alpha2~5^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ff05c7e1cf006646cad663c5637c70e875fb4219;p=thirdparty%2Fpdns.git Start format checks for pdns/modules --- diff --git a/.circleci/config.yml b/.circleci/config.yml index f6b78e3599..2a0a661474 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -546,7 +546,7 @@ jobs: - run: name: Check formatting command: | - ./build-scripts/format-code pdns/recursordist/*.[ch][ch] + ./build-scripts/format-code pdns/recursordist/*.[ch][ch] $(find modules -name '*.[ch][ch]') git --no-pager diff exit $(git diff | wc -l) working_directory: ~/project diff --git a/modules/bindbackend/bindbackend2.cc b/modules/bindbackend/bindbackend2.cc index fc57cdc933..1d3312ed2d 100644 --- a/modules/bindbackend/bindbackend2.cc +++ b/modules/bindbackend/bindbackend2.cc @@ -73,73 +73,73 @@ */ Bind2Backend::state_t Bind2Backend::s_state; -int Bind2Backend::s_first=1; -bool Bind2Backend::s_ignore_broken_records=false; +int Bind2Backend::s_first = 1; +bool Bind2Backend::s_ignore_broken_records = false; ReadWriteLock Bind2Backend::s_state_lock; std::mutex Bind2Backend::s_supermaster_config_lock; // protects writes to config file std::mutex Bind2Backend::s_startup_lock; -string Bind2Backend::s_binddirectory; +string Bind2Backend::s_binddirectory; template std::mutex LookButDontTouch::s_lock; BB2DomainInfo::BB2DomainInfo() { - d_loaded=false; - d_lastcheck=0; - d_checknow=false; - d_status="Unknown"; + d_loaded = false; + d_lastcheck = 0; + d_checknow = false; + d_status = "Unknown"; } void BB2DomainInfo::setCheckInterval(time_t seconds) { - d_checkinterval=seconds; + d_checkinterval = seconds; } bool BB2DomainInfo::current() { - if(d_checknow) { + if (d_checknow) { return false; } - if(!d_checkinterval) + if (!d_checkinterval) return true; - if(time(nullptr) - d_lastcheck < d_checkinterval) + if (time(nullptr) - d_lastcheck < d_checkinterval) return true; - - if(d_filename.empty()) + + if (d_filename.empty()) return true; - return (getCtime()==d_ctime); + return (getCtime() == d_ctime); } time_t BB2DomainInfo::getCtime() { struct stat buf; - - if(d_filename.empty() || stat(d_filename.c_str(),&buf)<0) - return 0; - d_lastcheck=time(nullptr); + + if (d_filename.empty() || stat(d_filename.c_str(), &buf) < 0) + return 0; + d_lastcheck = time(nullptr); return buf.st_ctime; } void BB2DomainInfo::setCtime() { struct stat buf; - if(stat(d_filename.c_str(),&buf)<0) - return; - d_ctime=buf.st_ctime; + if (stat(d_filename.c_str(), &buf) < 0) + return; + d_ctime = buf.st_ctime; } bool Bind2Backend::safeGetBBDomainInfo(int id, BB2DomainInfo* bbd) { ReadLock rl(&s_state_lock); state_t::const_iterator iter = s_state.find(id); - if(iter == s_state.end()) + if (iter == s_state.end()) return false; - *bbd=*iter; + *bbd = *iter; return true; } @@ -150,9 +150,9 @@ bool Bind2Backend::safeGetBBDomainInfo(const DNSName& name, BB2DomainInfo* bbd) nameindex_t& nameindex = boost::multi_index::get(s_state); nameindex_t::const_iterator iter = nameindex.find(name); - if(iter == nameindex.end()) + if (iter == nameindex.end()) return false; - *bbd=*iter; + *bbd = *iter; return true; } @@ -163,7 +163,7 @@ bool Bind2Backend::safeRemoveBBDomainInfo(const DNSName& name) nameindex_t& nameindex = boost::multi_index::get(s_state); nameindex_t::iterator iter = nameindex.find(name); - if(iter == nameindex.end()) + if (iter == nameindex.end()) return false; nameindex.erase(iter); return true; @@ -187,47 +187,48 @@ void Bind2Backend::setNotified(uint32_t id, uint32_t serial) void Bind2Backend::setFresh(uint32_t domain_id) { BB2DomainInfo bbd; - if(safeGetBBDomainInfo(domain_id, &bbd)) { - bbd.d_lastcheck=time(nullptr); + if (safeGetBBDomainInfo(domain_id, &bbd)) { + bbd.d_lastcheck = time(nullptr); safePutBBDomainInfo(bbd); } } -bool Bind2Backend::startTransaction(const DNSName &qname, int id) +bool Bind2Backend::startTransaction(const DNSName& qname, int id) { - if(id < 0) { + if (id < 0) { d_transaction_tmpname.clear(); - d_transaction_id=id; + d_transaction_id = id; return false; } - if(id == 0) { + if (id == 0) { throw DBException("domain_id 0 is invalid for this backend."); } - d_transaction_id=id; - d_transaction_qname=qname; + d_transaction_id = id; + d_transaction_qname = qname; BB2DomainInfo bbd; - if(safeGetBBDomainInfo(id, &bbd)) { + if (safeGetBBDomainInfo(id, &bbd)) { d_transaction_tmpname = bbd.d_filename + "XXXXXX"; int fd = mkstemp(&d_transaction_tmpname.at(0)); if (fd == -1) { - throw DBException("Unable to create a unique temporary zonefile '"+d_transaction_tmpname+"': "+stringerror()); + throw DBException("Unable to create a unique temporary zonefile '" + d_transaction_tmpname + "': " + stringerror()); return false; } d_of = std::unique_ptr(new ofstream(d_transaction_tmpname.c_str())); - if(!*d_of) { + if (!*d_of) { unlink(d_transaction_tmpname.c_str()); close(fd); fd = -1; d_of.reset(); - throw DBException("Unable to open temporary zonefile '"+d_transaction_tmpname+"': "+stringerror()); + throw DBException("Unable to open temporary zonefile '" + d_transaction_tmpname + "': " + stringerror()); } close(fd); fd = -1; - *d_of<<"; Written by PowerDNS, don't edit!"<0 = actual transaction - if(d_transaction_id > 0) { + if (d_transaction_id > 0) { unlink(d_transaction_tmpname.c_str()); d_of.reset(); - d_transaction_id=0; + d_transaction_id = 0; } return true; } -bool Bind2Backend::feedRecord(const DNSResourceRecord &rr, const DNSName &ordername, bool ordernameIsNSEC3) +bool Bind2Backend::feedRecord(const DNSResourceRecord& rr, const DNSName& ordername, bool ordernameIsNSEC3) { if (d_transaction_id < 1) { throw DBException("Bind2Backend::feedRecord() called outside of transaction"); @@ -286,14 +287,14 @@ bool Bind2Backend::feedRecord(const DNSResourceRecord &rr, const DNSName &ordern } } else { - throw DBException("out-of-zone data '"+rr.qname.toLogString()+"' during AXFR of zone '"+d_transaction_qname.toLogString()+"'"); + throw DBException("out-of-zone data '" + rr.qname.toLogString() + "' during AXFR of zone '" + d_transaction_qname.toLogString() + "'"); } shared_ptr drc(DNSRecordContent::mastermake(rr.qtype.getCode(), QClass::IN, rr.content)); string content = drc->getZoneRepresentation(); // SOA needs stripping too! XXX FIXME - also, this should not be here I think - switch(rr.qtype.getCode()) { + switch (rr.qtype.getCode()) { case QType::MX: case QType::SRV: case QType::CNAME: @@ -303,57 +304,57 @@ bool Bind2Backend::feedRecord(const DNSResourceRecord &rr, const DNSName &ordern // fallthrough default: if (d_of && *d_of) { - *d_of< *changedDomains) +void Bind2Backend::getUpdatedMasters(vector* changedDomains) { vector consider; { ReadLock rl(&s_state_lock); - for(const auto & i : s_state) { - if(i.d_kind != DomainInfo::Master && this->alsoNotify.empty() && i.d_also_notify.empty()) + for (const auto& i : s_state) { + if (i.d_kind != DomainInfo::Master && this->alsoNotify.empty() && i.d_also_notify.empty()) continue; DomainInfo di; - di.id=i.d_id; - di.zone=i.d_name; - di.last_check=i.d_lastcheck; - di.notified_serial=i.d_lastnotified; - di.backend=this; - di.kind=DomainInfo::Master; + di.id = i.d_id; + di.zone = i.d_name; + di.last_check = i.d_lastcheck; + di.notified_serial = i.d_lastnotified; + di.backend = this; + di.kind = DomainInfo::Master; consider.push_back(std::move(di)); } } SOAData soadata; - for(DomainInfo& di : consider) { - soadata.serial=0; + for (DomainInfo& di : consider) { + soadata.serial = 0; try { this->getSOA(di.zone, soadata); // we might not *have* a SOA yet, but this might trigger a load of it } - catch(...) { + catch (...) { continue; } - if(di.notified_serial != soadata.serial) { + if (di.notified_serial != soadata.serial) { BB2DomainInfo bbd; - if(safeGetBBDomainInfo(di.id, &bbd)) { - bbd.d_lastnotified=soadata.serial; + if (safeGetBBDomainInfo(di.id, &bbd)) { + bbd.d_lastnotified = soadata.serial; safePutBBDomainInfo(bbd); } - if(di.notified_serial) { // don't do notification storm on startup - di.serial=soadata.serial; + if (di.notified_serial) { // don't do notification storm on startup + di.serial = soadata.serial; changedDomains->push_back(std::move(di)); } } } } -void Bind2Backend::getAllDomains(vector *domains, bool include_disabled) +void Bind2Backend::getAllDomains(vector* domains, bool include_disabled) { SOAData soadata; @@ -362,135 +363,139 @@ void Bind2Backend::getAllDomains(vector *domains, bool include_disab ReadLock rl(&s_state_lock); domains->reserve(s_state.size()); - for(const auto & i : s_state) { + for (const auto& i : s_state) { DomainInfo di; - di.id=i.d_id; - di.zone=i.d_name; - di.last_check=i.d_lastcheck; - di.kind=i.d_kind; - di.masters=i.d_masters; - di.backend=this; + di.id = i.d_id; + di.zone = i.d_name; + di.last_check = i.d_lastcheck; + di.kind = i.d_kind; + di.masters = i.d_masters; + di.backend = this; domains->push_back(std::move(di)); }; } - for(DomainInfo &di : *domains) { + for (DomainInfo& di : *domains) { // do not corrupt di if domain supplied by another backend. if (di.backend != this) continue; try { this->getSOA(di.zone, soadata); - } catch(...) { + } + catch (...) { continue; } - di.serial=soadata.serial; + di.serial = soadata.serial; } } -void Bind2Backend::getUnfreshSlaveInfos(vector *unfreshDomains) +void Bind2Backend::getUnfreshSlaveInfos(vector* unfreshDomains) { vector domains; { ReadLock rl(&s_state_lock); domains.reserve(s_state.size()); - for(const auto & i : s_state) { - if(i.d_kind != DomainInfo::Slave) + for (const auto& i : s_state) { + if (i.d_kind != DomainInfo::Slave) continue; DomainInfo sd; - sd.id=i.d_id; - sd.zone=i.d_name; - sd.masters=i.d_masters; - sd.last_check=i.d_lastcheck; - sd.backend=this; - sd.kind=DomainInfo::Slave; + sd.id = i.d_id; + sd.zone = i.d_name; + sd.masters = i.d_masters; + sd.last_check = i.d_lastcheck; + sd.backend = this; + sd.kind = DomainInfo::Slave; domains.push_back(std::move(sd)); } } unfreshDomains->reserve(domains.size()); - for(DomainInfo &sd : domains) { + for (DomainInfo& sd : domains) { SOAData soadata; - soadata.refresh=0; - soadata.serial=0; + soadata.refresh = 0; + soadata.serial = 0; try { - getSOA(sd.zone,soadata); // we might not *have* a SOA yet + getSOA(sd.zone, soadata); // we might not *have* a SOA yet + } + catch (...) { } - catch(...){} - sd.serial=soadata.serial; - if(sd.last_check+soadata.refresh < (unsigned int)time(nullptr)) + sd.serial = soadata.serial; + if (sd.last_check + soadata.refresh < (unsigned int)time(nullptr)) unfreshDomains->push_back(std::move(sd)); } } -bool Bind2Backend::getDomainInfo(const DNSName& domain, DomainInfo &di, bool getSerial) +bool Bind2Backend::getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial) { BB2DomainInfo bbd; - if(!safeGetBBDomainInfo(domain, &bbd)) + if (!safeGetBBDomainInfo(domain, &bbd)) return false; - di.id=bbd.d_id; - di.zone=domain; - di.masters=bbd.d_masters; - di.last_check=bbd.d_lastcheck; - di.backend=this; - di.kind=bbd.d_kind; - di.serial=0; - if(getSerial) { + di.id = bbd.d_id; + di.zone = domain; + di.masters = bbd.d_masters; + di.last_check = bbd.d_lastcheck; + di.backend = this; + di.kind = bbd.d_kind; + di.serial = 0; + if (getSerial) { try { SOAData sd; - sd.serial=0; + sd.serial = 0; - getSOA(bbd.d_name,sd); // we might not *have* a SOA yet - di.serial=sd.serial; + getSOA(bbd.d_name, sd); // we might not *have* a SOA yet + di.serial = sd.serial; + } + catch (...) { } - catch(...){} } - + return true; } -void Bind2Backend::alsoNotifies(const DNSName& domain, set *ips) +void Bind2Backend::alsoNotifies(const DNSName& domain, set* ips) { // combine global list with local list - for(const auto & i : this->alsoNotify) { + for (const auto& i : this->alsoNotify) { (*ips).insert(i); } // check metadata too if available vector meta; if (getDomainMetadata(domain, "ALSO-NOTIFY", meta)) { - for(const auto& str: meta) { + for (const auto& str : meta) { (*ips).insert(str); } } ReadLock rl(&s_state_lock); - for(const auto & i : s_state) { - if(i.d_name == domain) { - for(const auto & it : i.d_also_notify) { + for (const auto& i : s_state) { + if (i.d_name == domain) { + for (const auto& it : i.d_also_notify) { (*ips).insert(it); } return; } - } + } } // only parses, does NOT add to s_state! -void Bind2Backend::parseZoneFile(BB2DomainInfo *bbd) +void Bind2Backend::parseZoneFile(BB2DomainInfo* bbd) { NSEC3PARAMRecordContent ns3pr; bool nsec3zone; if (d_hybrid) { DNSSECKeeper dk; - nsec3zone=dk.getNSEC3PARAM(bbd->d_name, &ns3pr); - } else - nsec3zone=getNSEC3PARAM(bbd->d_name, &ns3pr); + nsec3zone = dk.getNSEC3PARAM(bbd->d_name, &ns3pr); + } + else + nsec3zone = getNSEC3PARAM(bbd->d_name, &ns3pr); auto records = std::make_shared(); ZoneParserTNG zpt(bbd->d_filename, bbd->d_name, s_binddirectory, d_upgradeContent); zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps")); DNSResourceRecord rr; string hashed; - while(zpt.get(rr)) { - if(rr.qtype.getCode() == QType::NSEC || rr.qtype.getCode() == QType::NSEC3 || rr.qtype.getCode() == QType::NSEC3PARAM) + while (zpt.get(rr)) { + if (rr.qtype.getCode() == QType::NSEC || rr.qtype.getCode() == QType::NSEC3 || rr.qtype.getCode() == QType::NSEC3PARAM) continue; // we synthesise NSECs on demand insertRecord(records, bbd->d_name, rr.qname, rr.qtype, rr.content, rr.ttl, ""); @@ -498,100 +503,99 @@ void Bind2Backend::parseZoneFile(BB2DomainInfo *bbd) fixupOrderAndAuth(records, bbd->d_name, nsec3zone, ns3pr); doEmptyNonTerminals(records, bbd->d_name, nsec3zone, ns3pr); bbd->setCtime(); - bbd->d_loaded=true; - bbd->d_checknow=false; - bbd->d_status="parsed into memory at "+nowTime(); + bbd->d_loaded = true; + bbd->d_checknow = false; + bbd->d_status = "parsed into memory at " + nowTime(); bbd->d_records = LookButDontTouch(records); } /** THIS IS AN INTERNAL FUNCTION! It does moadnsparser prio impedance matching Much of the complication is due to the efforts to benefit from std::string reference counting copy on write semantics */ -void Bind2Backend::insertRecord(std::shared_ptr& records, const DNSName& zoneName, const DNSName &qname, const QType &qtype, const string &content, int ttl, const std::string& hashed, bool *auth) +void Bind2Backend::insertRecord(std::shared_ptr& records, const DNSName& zoneName, const DNSName& qname, const QType& qtype, const string& content, int ttl, const std::string& hashed, bool* auth) { Bind2DNSRecord bdr; - bdr.qname=qname; + bdr.qname = qname; - if(zoneName.empty()) + if (zoneName.empty()) ; - else if(bdr.qname.isPartOf(zoneName)) + else if (bdr.qname.isPartOf(zoneName)) bdr.qname.makeUsRelative(zoneName); else { - string msg = "Trying to insert non-zone data, name='"+bdr.qname.toLogString()+"', qtype="+qtype.getName()+", zone='"+zoneName.toLogString()+"'"; - if(s_ignore_broken_records) { - g_log<empty() && bdr.qname==boost::prior(records->end())->qname) - bdr.qname=boost::prior(records->end())->qname; + if (!records->empty() && bdr.qname == boost::prior(records->end())->qname) + bdr.qname = boost::prior(records->end())->qname; - bdr.qname=bdr.qname; - bdr.qtype=qtype.getCode(); - bdr.content=content; + bdr.qname = bdr.qname; + bdr.qtype = qtype.getCode(); + bdr.content = content; bdr.nsec3hash = hashed; - + if (auth) // Set auth on empty non-terminals - bdr.auth=*auth; + bdr.auth = *auth; else - bdr.auth=true; + bdr.auth = true; - bdr.ttl=ttl; + bdr.ttl = ttl; records->insert(std::move(bdr)); } -string Bind2Backend::DLReloadNowHandler(const vector&parts, Utility::pid_t ppid) +string Bind2Backend::DLReloadNowHandler(const vector& parts, Utility::pid_t ppid) { ostringstream ret; - for(vector::const_iterator i=parts.begin()+1;i::const_iterator i = parts.begin() + 1; i < parts.end(); ++i) { BB2DomainInfo bbd; DNSName zone(*i); - if(safeGetBBDomainInfo(zone, &bbd)) { + if (safeGetBBDomainInfo(zone, &bbd)) { Bind2Backend bb2; bb2.queueReloadAndStore(bbd.d_id); if (!safeGetBBDomainInfo(zone, &bbd)) // Read the *new* domain status - ret << *i << ": [missing]\n"; + ret << *i << ": [missing]\n"; else - ret<< *i << ": "<< (bbd.d_wasRejectedLastReload ? "[rejected]": "") <<"\t"<&parts, Utility::pid_t ppid) +string Bind2Backend::DLDomStatusHandler(const vector& parts, Utility::pid_t ppid) { ostringstream ret; - if(parts.size() > 1) { - for(vector::const_iterator i=parts.begin()+1;i 1) { + for (vector::const_iterator i = parts.begin() + 1; i < parts.end(); ++i) { BB2DomainInfo bbd; - if(safeGetBBDomainInfo(DNSName(*i), &bbd)) { - ret<< *i << ": "<< (bbd.d_loaded ? "": "[rejected]") <<"\t"<&parts, Utility::pid_t ppid) +string Bind2Backend::DLDomExtendedStatusHandler(const vector& parts, Utility::pid_t ppid) { ostringstream ret; if (parts.size() > 1) { - for (vector::const_iterator i=parts.begin()+1;i::const_iterator i = parts.begin() + 1; i < parts.end(); ++i) { BB2DomainInfo bbd; if (safeGetBBDomainInfo(DNSName(*i), &bbd)) { printDomainExtendedStatus(ret, bbd); @@ -659,26 +663,26 @@ string Bind2Backend::DLDomExtendedStatusHandler(const vector&parts, Util return ret.str(); } -string Bind2Backend::DLListRejectsHandler(const vector&parts, Utility::pid_t ppid) +string Bind2Backend::DLListRejectsHandler(const vector& parts, Utility::pid_t ppid) { ostringstream ret; ReadLock rl(&s_state_lock); - for(const auto & i : s_state) { - if(!i.d_loaded) - ret<&parts, Utility::pid_t ppid) +string Bind2Backend::DLAddDomainHandler(const vector& parts, Utility::pid_t ppid) { - if(parts.size() < 3) + if (parts.size() < 3) return "ERROR: Domain name and zone filename are required"; DNSName domainname(parts[1]); - const string &filename = parts[2]; + const string& filename = parts[2]; BB2DomainInfo bbd; - if(safeGetBBDomainInfo(domainname, &bbd)) + if (safeGetBBDomainInfo(domainname, &bbd)) return "Already loaded"; if (!boost::starts_with(filename, "/") && ::arg()["chroot"].empty()) @@ -689,21 +693,21 @@ string Bind2Backend::DLAddDomainHandler(const vector&parts, Utility::pid return "Unable to load zone " + domainname.toLogString() + " from " + filename + ": " + strerror(errno); Bind2Backend bb2; // createdomainentry needs access to our configuration - bbd=bb2.createDomainEntry(domainname, filename); - bbd.d_filename=filename; - bbd.d_checknow=true; - bbd.d_loaded=true; - bbd.d_lastcheck=0; - bbd.d_status="parsing into memory"; + bbd = bb2.createDomainEntry(domainname, filename); + bbd.d_filename = filename; + bbd.d_checknow = true; + bbd.d_loaded = true; + bbd.d_lastcheck = 0; + bbd.d_status = "parsing into memory"; bbd.setCtime(); safePutBBDomainInfo(bbd); - g_log< l(s_startup_lock); - + setupDNSSEC(); - if(!s_first) { + if (!s_first) { return; } - - if(loadZones) { + + if (loadZones) { loadConfig(); - s_first=0; + s_first = 0; } - + DynListener::registerFunc("BIND-RELOAD-NOW", &DLReloadNowHandler, "bindbackend: reload domains", ""); DynListener::registerFunc("BIND-DOMAIN-STATUS", &DLDomStatusHandler, "bindbackend: list status of all domains", "[domains]"); DynListener::registerFunc("BIND-DOMAIN-EXTENDED-STATUS", &DLDomExtendedStatusHandler, "bindbackend: list the extended status of all domains", "[domains]"); @@ -750,9 +754,11 @@ Bind2Backend::Bind2Backend(const string &suffix, bool loadZones) } Bind2Backend::~Bind2Backend() -{ freeStatements(); } // deallocate statements +{ + freeStatements(); +} // deallocate statements -void Bind2Backend::rediscover(string *status) +void Bind2Backend::rediscover(string* status) { loadConfig(status); } @@ -760,8 +766,8 @@ void Bind2Backend::rediscover(string *status) void Bind2Backend::reload() { WriteLock rwl(&s_state_lock); - for(const auto & i : s_state) { - i.d_checknow=true; // being a bit cheeky here, don't index state_t on this (mutable) + for (const auto& i : s_state) { + i.d_checknow = true; // being a bit cheeky here, don't index state_t on this (mutable) } } @@ -771,31 +777,31 @@ void Bind2Backend::fixupOrderAndAuth(std::shared_ptr& records, DNSName shorter; set nssets, dssets; - for(const auto& bdr: *records) { - if(!bdr.qname.isRoot() && bdr.qtype == QType::NS) + for (const auto& bdr : *records) { + if (!bdr.qname.isRoot() && bdr.qtype == QType::NS) nssets.insert(bdr.qname); - else if(bdr.qtype == QType::DS) + else if (bdr.qtype == QType::DS) dssets.insert(bdr.qname); } - for(auto iter = records->begin(); iter != records->end(); iter++) { + for (auto iter = records->begin(); iter != records->end(); iter++) { skip = false; shorter = iter->qname; if (!iter->qname.isRoot() && shorter.chopOff() && !iter->qname.isRoot()) { do { - if(nssets.count(shorter)) { + if (nssets.count(shorter)) { skip = true; break; } - } while(shorter.chopOff() && !iter->qname.isRoot()); + } while (shorter.chopOff() && !iter->qname.isRoot()); } iter->auth = (!skip && (iter->qtype == QType::DS || iter->qtype == QType::RRSIG || !nssets.count(iter->qname))); - if(!skip && nsec3zone && iter->qtype != QType::RRSIG && (iter->auth || (iter->qtype == QType::NS && !ns3pr.d_flags) || dssets.count(iter->qname))) { + if (!skip && nsec3zone && iter->qtype != QType::RRSIG && (iter->auth || (iter->qtype == QType::NS && !ns3pr.d_flags) || dssets.count(iter->qname))) { Bind2DNSRecord bdr = *iter; - bdr.nsec3hash = toBase32Hex(hashQNameWithSalt(ns3pr, bdr.qname+zoneName)); + bdr.nsec3hash = toBase32Hex(hashQNameWithSalt(ns3pr, bdr.qname + zoneName)); records->replace(iter, bdr); } @@ -812,10 +818,10 @@ void Bind2Backend::doEmptyNonTerminals(std::shared_ptr& records uint32_t maxent = ::arg().asNum("max-ent-entries"); - for(const auto& bdr : *records) + for (const auto& bdr : *records) qnames.insert(bdr.qname); - for(const auto& bdr : *records) { + for (const auto& bdr : *records) { if (!bdr.auth && bdr.qtype == QType::NS) auth = (!nsec3zone || !ns3pr.d_flags); @@ -823,20 +829,18 @@ void Bind2Backend::doEmptyNonTerminals(std::shared_ptr& records auth = bdr.auth; shorter = bdr.qname; - while(shorter.chopOff()) - { - if(!qnames.count(shorter)) - { - if(!(maxent)) - { - g_log<& records rr.qtype = "#0"; rr.content = ""; rr.ttl = 0; - for(auto& nt : nonterm) - { + for (auto& nt : nonterm) { string hashed; rr.qname = nt.first + zoneName; - if(nsec3zone && nt.second) + if (nsec3zone && nt.second) hashed = toBase32Hex(hashQNameWithSalt(ns3pr, rr.qname)); insertRecord(records, zoneName, rr.qname, rr.qtype, rr.content, rr.ttl, hashed, &nt.second); @@ -860,158 +863,157 @@ void Bind2Backend::doEmptyNonTerminals(std::shared_ptr& records void Bind2Backend::loadConfig(string* status) { - static int domain_id=1; + static int domain_id = 1; - if(!getArg("config").empty()) { + if (!getArg("config").empty()) { BindParser BP; try { BP.parse(getArg("config")); } - catch(PDNSException &ae) { - g_log< domains=BP.getDomains(); + + vector domains = BP.getDomains(); this->alsoNotify = BP.getAlsoNotify(); - s_binddirectory=BP.getDirectory(); + s_binddirectory = BP.getDirectory(); // ZP.setDirectory(d_binddirectory); - g_log< oldnames, newnames; { ReadLock rl(&s_state_lock); - for(const BB2DomainInfo& bbd : s_state) { + for (const BB2DomainInfo& bbd : s_state) { oldnames.insert(bbd.d_name); } } - int rejected=0; - int newdomains=0; + int rejected = 0; + int newdomains = 0; struct stat st; - - for(auto & domain : domains) - { - if(stat(domain.filename.c_str(), &st) == 0) { + + for (auto& domain : domains) { + if (stat(domain.filename.c_str(), &st) == 0) { domain.d_dev = st.st_dev; domain.d_ino = st.st_ino; } } sort(domains.begin(), domains.end()); // put stuff in inode order - for(const auto & domain : domains) - { - if (!(domain.hadFileDirective)) { - g_log< diff; set_difference(oldnames.begin(), oldnames.end(), newnames.begin(), newnames.end(), back_inserter(diff)); - unsigned int remdomains=diff.size(); - - for(const DNSName& name: diff) { + unsigned int remdomains = diff.size(); + + for (const DNSName& name : diff) { safeRemoveBBDomainInfo(name); } // count number of entirely new domains diff.clear(); set_difference(newnames.begin(), newnames.end(), oldnames.begin(), oldnames.end(), back_inserter(diff)); - newdomains=diff.size(); + newdomains = diff.size(); ostringstream msg; - msg<<" Done parsing domains, "<(); parseZoneFile(&bbnew); - bbnew.d_checknow=false; - bbnew.d_wasRejectedLastReload=false; + bbnew.d_checknow = false; + bbnew.d_wasRejectedLastReload = false; safePutBBDomainInfo(bbnew); - g_log<upper_bound(qname.makeLowerCase()); - if(iterBefore != records->begin()) + if (iterBefore != records->begin()) --iterBefore; - while((!iterBefore->auth && iterBefore->qtype != QType::NS) || !iterBefore->qtype) + while ((!iterBefore->auth && iterBefore->qtype != QType::NS) || !iterBefore->qtype) --iterBefore; - before=iterBefore->qname; + before = iterBefore->qname; - if(iterAfter == records->end()) { + if (iterAfter == records->end()) { iterAfter = records->begin(); - } else { - while((!iterAfter->auth && iterAfter->qtype != QType::NS) || !iterAfter->qtype) { + } + else { + while ((!iterAfter->auth && iterAfter->qtype != QType::NS) || !iterAfter->qtype) { ++iterAfter; - if(iterAfter == records->end()) { + if (iterAfter == records->end()) { iterAfter = records->begin(); break; } @@ -1091,16 +1094,17 @@ bool Bind2Backend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qn bool nsec3zone; if (d_hybrid) { DNSSECKeeper dk; - nsec3zone=dk.getNSEC3PARAM(bbd.d_name, &ns3pr); - } else - nsec3zone=getNSEC3PARAM(bbd.d_name, &ns3pr); + nsec3zone = dk.getNSEC3PARAM(bbd.d_name, &ns3pr); + } + else + nsec3zone = getNSEC3PARAM(bbd.d_name, &ns3pr); shared_ptr records = bbd.d_records.get(); - if(!nsec3zone) { + if (!nsec3zone) { return findBeforeAndAfterUnhashed(records, qname, unhashed, before, after); } else { - auto& hashindex=boost::multi_index::get(*records); + auto& hashindex = boost::multi_index::get(*records); // for(auto iter = first; iter != hashindex.end(); iter++) // cerr<nsec3hash<nsec3hash); after = DNSName(first->nsec3hash); - } else { + } + else { after = DNSName(iter->nsec3hash); if (iter != first) --iter; @@ -1120,115 +1125,116 @@ bool Bind2Backend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qn iter = --hashindex.end(); before = DNSName(iter->nsec3hash); } - unhashed = iter->qname+bbd.d_name; + unhashed = iter->qname + bbd.d_name; return true; } } -void Bind2Backend::lookup(const QType &qtype, const DNSName &qname, int zoneId, DNSPacket *pkt_p ) +void Bind2Backend::lookup(const QType& qtype, const DNSName& qname, int zoneId, DNSPacket* pkt_p) { d_handle.reset(); - static bool mustlog=::arg().mustDo("query-logging"); + static bool mustlog = ::arg().mustDo("query-logging"); bool found; DNSName domain; BB2DomainInfo bbd; - if(mustlog) - g_log<= 0) { if ((found = (safeGetBBDomainInfo(zoneId, &bbd) && qname.isPartOf(bbd.d_name)))) { domain = std::move(bbd.d_name); } - } else { + } + else { domain = qname; do { found = safeGetBBDomainInfo(domain, &bbd); } while (!found && qtype != QType::SOA && domain.chopOff()); } - if(!found) { - if(mustlog) - g_log<empty()) - DLOG(g_log<<"Query with no results"<empty()) + DLOG(g_log << "Query with no results" << endl); d_handle.mustlog = mustlog; auto& hashedidx = boost::multi_index::get(*d_handle.d_records); auto range = hashedidx.equal_range(d_handle.qname); - - if(range.first==range.second) { - d_handle.d_list=false; - d_handle.d_iter = d_handle.d_end_iter = range.first; + + if (range.first == range.second) { + d_handle.d_list = false; + d_handle.d_iter = d_handle.d_end_iter = range.first; return; } else { - d_handle.d_iter=range.first; - d_handle.d_end_iter=range.second; + d_handle.d_iter = range.first; + d_handle.d_end_iter = range.second; } - d_handle.d_list=false; + d_handle.d_list = false; } Bind2Backend::handle::handle() { - mustlog=false; + mustlog = false; } -bool Bind2Backend::get(DNSResourceRecord &r) +bool Bind2Backend::get(DNSResourceRecord& r) { - if(!d_handle.d_records) { - if(d_handle.mustlog) - g_log<size()<<" available in total!"<size() << " available in total!" << endl); + + if (d_iter == d_end_iter) { return false; } - while(d_iter!=d_end_iter && !(qtype.getCode()==QType::ANY || (d_iter)->qtype==qtype.getCode())) { - DLOG(g_log<qtype).getName()<<": '"<content<<"'"<qtype == qtype.getCode())) { + DLOG(g_log << Logger::Warning << "Skipped " << qname << "/" << QType(d_iter->qtype).getName() << ": '" << d_iter->content << "'" << endl); d_iter++; } - if(d_iter==d_end_iter) { + if (d_iter == d_end_iter) { return false; } - DLOG(g_log << "Bind2Backend get() returning a rr with a "<qtype).getCode()<qtype).getCode() << endl); - r.qname=qname.empty() ? domain : (qname+domain); - r.domain_id=id; - r.content=(d_iter)->content; + r.qname = qname.empty() ? domain : (qname + domain); + r.domain_id = id; + r.content = (d_iter)->content; // r.domain_id=(d_iter)->domain_id; - r.qtype=(d_iter)->qtype; - r.ttl=(d_iter)->ttl; + r.qtype = (d_iter)->qtype; + r.ttl = (d_iter)->ttl; //if(!d_iter->auth && r.qtype.getCode() != QType::A && r.qtype.getCode()!=QType::AAAA && r.qtype.getCode() != QType::NS) // cerr<<"Warning! Unauth response for qtype "<< r.qtype.getName() << " for '"<begin(); - d_handle.d_qname_end=d_handle.d_records->end(); // iter now points to a vector of pointers to vector + d_handle.d_records = bbd.d_records.get(); // give it a copy, which will stay around + d_handle.d_qname_iter = d_handle.d_records->begin(); + d_handle.d_qname_end = d_handle.d_records->end(); // iter now points to a vector of pointers to vector - d_handle.id=id; - d_handle.domain=bbd.d_name; - d_handle.d_list=true; + d_handle.id = id; + d_handle.domain = bbd.d_name; + d_handle.d_list = true; return true; } -bool Bind2Backend::handle::get_list(DNSResourceRecord &r) +bool Bind2Backend::handle::get_list(DNSResourceRecord& r) { - if(d_qname_iter!=d_qname_end) { - r.qname=d_qname_iter->qname.empty() ? domain : (d_qname_iter->qname+domain); - r.domain_id=id; - r.content=(d_qname_iter)->content; - r.qtype=(d_qname_iter)->qtype; - r.ttl=(d_qname_iter)->ttl; + if (d_qname_iter != d_qname_end) { + r.qname = d_qname_iter->qname.empty() ? domain : (d_qname_iter->qname + domain); + r.domain_id = id; + r.content = (d_qname_iter)->content; + r.qtype = (d_qname_iter)->qtype; + r.ttl = (d_qname_iter)->ttl; r.auth = d_qname_iter->auth; d_qname_iter++; return true; @@ -1311,7 +1316,7 @@ bool Bind2Backend::handle::get_list(DNSResourceRecord &r) return false; } -bool Bind2Backend::superMasterBackend(const string &ip, const DNSName& domain, const vector&nsset, string *nameserver, string *account, DNSBackend **db) +bool Bind2Backend::superMasterBackend(const string& ip, const DNSName& domain, const vector& nsset, string* nameserver, string* account, DNSBackend** db) { // Check whether we have a configfile available. if (getArg("supermaster-config").empty()) @@ -1333,61 +1338,60 @@ bool Bind2Backend::superMasterBackend(const string &ip, const DNSName& domain, c ii >> saccount; break; } - } + } c_if.close(); - if (sip != ip) // ip not found in authorization list - reject + if (sip != ip) // ip not found in authorization list - reject return false; - + // ip authorized as supermaster - accept *db = this; if (saccount.length() > 0) - *account = saccount.c_str(); + *account = saccount.c_str(); return true; } - -BB2DomainInfo Bind2Backend::createDomainEntry(const DNSName& domain, const string &filename) +BB2DomainInfo Bind2Backend::createDomainEntry(const DNSName& domain, const string& filename) { - int newid=1; - { // Find a free zone id nr. + int newid = 1; + { // Find a free zone id nr. ReadLock rl(&s_state_lock); if (!s_state.empty()) { // older (1.53) versions of boost have an expression for s_state.rbegin() // that is ambiguous in C++17. So construct it explicitly - newid = boost::make_reverse_iterator(s_state.end())->d_id+1; + newid = boost::make_reverse_iterator(s_state.end())->d_id + 1; } } - + BB2DomainInfo bbd; bbd.d_kind = DomainInfo::Native; bbd.d_id = newid; - bbd.d_records = std::make_shared(); + bbd.d_records = std::make_shared(); bbd.d_name = domain; bbd.setCheckInterval(getArgAsNum("check-interval")); bbd.d_filename = filename; - + return bbd; } -bool Bind2Backend::createSlaveDomain(const string &ip, const DNSName& domain, const string &nameserver, const string &account) +bool Bind2Backend::createSlaveDomain(const string& ip, const DNSName& domain, const string& nameserver, const string& account) { - string filename = getArg("supermaster-destdir")+'/'+domain.toStringNoDot(); - + string filename = getArg("supermaster-destdir") + '/' + domain.toStringNoDot(); + g_log << Logger::Warning << d_logprefix - << " Writing bind config zone statement for superslave zone '" << domain - << "' from supermaster " << ip << endl; + << " Writing bind config zone statement for superslave zone '" << domain + << "' from supermaster " << ip << endl; { std::lock_guard l2(s_supermaster_config_lock); - - ofstream c_of(getArg("supermaster-config").c_str(), std::ios::app); + + ofstream c_of(getArg("supermaster-config").c_str(), std::ios::app); if (!c_of) { g_log << Logger::Error << "Unable to open supermaster configfile for append: " << stringerror() << endl; - throw DBException("Unable to open supermaster configfile for append: "+stringerror()); + throw DBException("Unable to open supermaster configfile for append: " + stringerror()); } - + c_of << endl; c_of << "# Superslave zone '" << domain.toString() << "' (added: " << nowTime() << ") (account: " << account << ')' << endl; c_of << "zone \"" << domain.toStringNoDot() << "\" {" << endl; @@ -1406,17 +1410,17 @@ bool Bind2Backend::createSlaveDomain(const string &ip, const DNSName& domain, co return true; } -bool Bind2Backend::searchRecords(const string &pattern, int maxResults, vector& result) +bool Bind2Backend::searchRecords(const string& pattern, int maxResults, vector& result) { - SimpleMatch sm(pattern,true); - static bool mustlog=::arg().mustDo("query-logging"); - if(mustlog) - g_log< rhandle = h.d_records.get(); - for(recordstorage_t::const_iterator ri = rhandle->begin(); result.size() < static_cast::size_type>(maxResults) && ri != rhandle->end(); ri++) { - DNSName name = ri->qname.empty() ? i.d_name : (ri->qname+i.d_name); + for (recordstorage_t::const_iterator ri = rhandle->begin(); result.size() < static_cast::size_type>(maxResults) && ri != rhandle->end(); ri++) { + DNSName name = ri->qname.empty() ? i.d_name : (ri->qname + i.d_name); if (sm.match(name) || sm.match(ri->content)) { DNSResourceRecord r; - r.qname=name; - r.domain_id=i.d_id; - r.content=ri->content; - r.qtype=ri->qtype; - r.ttl=ri->ttl; + r.qname = name; + r.domain_id = i.d_id; + r.content = ri->content; + r.qtype = ri->qtype; + r.ttl = ri->ttl; r.auth = ri->auth; result.push_back(std::move(r)); } @@ -1445,39 +1449,41 @@ bool Bind2Backend::searchRecords(const string &pattern, int maxResults, vector -{ - using std::less::operator(); - // use operator< - bool operator() (const DNSName& a, const Bind2DNSRecord& b) const - {return a.canonCompare(b.qname);} - bool operator() (const Bind2DNSRecord& a, const DNSName& b) const - {return a.qname.canonCompare(b);} - bool operator() (const Bind2DNSRecord& a, const Bind2DNSRecord& b) const - {return a.qname.canonCompare(b.qname);} +struct Bind2DNSCompare : std::less +{ + using std::less::operator(); + // use operator< + bool operator()(const DNSName& a, const Bind2DNSRecord& b) const + { + return a.canonCompare(b.qname); + } + bool operator()(const Bind2DNSRecord& a, const DNSName& b) const + { + return a.qname.canonCompare(b); + } + bool operator()(const Bind2DNSRecord& a, const Bind2DNSRecord& b) const + { + return a.qname.canonCompare(b.qname); + } }; -struct NSEC3Tag{}; -struct UnorderedNameTag{}; +struct NSEC3Tag +{ +}; +struct UnorderedNameTag +{ +}; typedef multi_index_container< Bind2DNSRecord, - indexed_by < - ordered_non_unique, Bind2DNSCompare >, - hashed_non_unique, member >, - ordered_non_unique, member > - > -> recordstorage_t; + indexed_by< + ordered_non_unique, Bind2DNSCompare>, + hashed_non_unique, member>, + ordered_non_unique, member>>> + recordstorage_t; template class LookButDontTouch // : public boost::noncopyable @@ -104,7 +113,8 @@ public: LookButDontTouch() { } - LookButDontTouch(shared_ptr records) : d_records(records) + LookButDontTouch(shared_ptr records) : + d_records(records) { } @@ -129,7 +139,6 @@ private: shared_ptr d_records; }; - /** Class which describes all metadata of a domain for storage by the Bind2Backend, and also contains a pointer to a vector of Bind2DNSRecord's */ class BB2DomainInfo { @@ -144,19 +153,19 @@ public: return d_checkinterval; } - DNSName d_name; //!< actual name of the domain + DNSName d_name; //!< actual name of the domain DomainInfo::DomainKind d_kind; //!< the kind of domain string d_filename; //!< full absolute filename of the zone on disk string d_status; //!< message describing status of a domain, for human consumption - vector d_masters; //!< IP address of the master of this domain + vector d_masters; //!< IP address of the master of this domain set d_also_notify; //!< IP list of hosts to also notify - LookButDontTouch d_records; //!< the actual records belonging to this domain - time_t d_ctime{0}; //!< last known ctime of the file on disk + LookButDontTouch d_records; //!< the actual records belonging to this domain + time_t d_ctime{0}; //!< last known ctime of the file on disk time_t d_lastcheck{0}; //!< last time domain was checked for freshness uint32_t d_lastnotified{0}; //!< Last serial number we notified our slaves of - unsigned int d_id; //!< internal id of the domain + unsigned int d_id; //!< internal id of the domain mutable bool d_checknow; //!< if this domain has been flagged for a check - bool d_loaded; //!< if a domain is loaded + bool d_loaded; //!< if a domain is loaded bool d_wasRejectedLastReload{false}; //!< if the domain was rejected during Bind2Backend::queueReloadAndStore private: @@ -168,38 +177,39 @@ class SSQLite3; class NSEC3PARAMRecordContent; struct NameTag -{}; +{ +}; class Bind2Backend : public DNSBackend { public: - Bind2Backend(const string &suffix="", bool loadZones=true); + Bind2Backend(const string& suffix = "", bool loadZones = true); ~Bind2Backend(); - void getUnfreshSlaveInfos(vector *unfreshDomains) override; - void getUpdatedMasters(vector *changedDomains) override; - bool getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial=true ) override; - time_t getCtime(const string &fname); - // DNSSEC + void getUnfreshSlaveInfos(vector* unfreshDomains) override; + void getUpdatedMasters(vector* changedDomains) override; + bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial = true) override; + time_t getCtime(const string& fname); + // DNSSEC bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) override; - void lookup(const QType &, const DNSName &qdomain, int zoneId, DNSPacket *p=nullptr) override; - bool list(const DNSName &target, int id, bool include_disabled=false) override; - bool get(DNSResourceRecord &) override; - void getAllDomains(vector *domains, bool include_disabled=false) override; + void lookup(const QType&, const DNSName& qdomain, int zoneId, DNSPacket* p = nullptr) override; + bool list(const DNSName& target, int id, bool include_disabled = false) override; + bool get(DNSResourceRecord&) override; + void getAllDomains(vector* domains, bool include_disabled = false) override; - static DNSBackend *maker(); + static DNSBackend* maker(); static std::mutex s_startup_lock; void setFresh(uint32_t domain_id) override; void setNotified(uint32_t id, uint32_t serial) override; - bool startTransaction(const DNSName &qname, int id) override; - bool feedRecord(const DNSResourceRecord &rr, const DNSName &ordername, bool ordernameIsNSEC3=false) override; + bool startTransaction(const DNSName& qname, int id) override; + bool feedRecord(const DNSResourceRecord& rr, const DNSName& ordername, bool ordernameIsNSEC3 = false) override; bool commitTransaction() override; bool abortTransaction() override; - void alsoNotifies(const DNSName &domain, set *ips) override; - bool searchRecords(const string &pattern, int maxResults, vector& result) override; + void alsoNotifies(const DNSName& domain, set* ips) override; + bool searchRecords(const string& pattern, int maxResults, vector& result) override; -// the DNSSEC related (getDomainMetadata has broader uses too) - bool getAllDomainMetadata(const DNSName& name, std::map >& meta) override; + // the DNSSEC related (getDomainMetadata has broader uses too) + bool getAllDomainMetadata(const DNSName& name, std::map>& meta) override; bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) override; bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) override; bool getDomainKeys(const DNSName& name, std::vector& keys) override; @@ -212,25 +222,24 @@ public: bool getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) override; bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) override; bool deleteTSIGKey(const DNSName& name) override; - bool getTSIGKeys(std::vector< struct TSIGKey > &keys) override; + bool getTSIGKeys(std::vector& keys) override; bool doesDNSSEC() override; - // end of DNSSEC + // end of DNSSEC - typedef multi_index_container < BB2DomainInfo , - indexed_by < ordered_unique >, - ordered_unique, member > - > > state_t; + typedef multi_index_container>, + ordered_unique, member>>> + state_t; static state_t s_state; static ReadWriteLock s_state_lock; - void parseZoneFile(BB2DomainInfo *bbd); - void rediscover(string *status=nullptr) override; - + void parseZoneFile(BB2DomainInfo* bbd); + void rediscover(string* status = nullptr) override; // for supermaster support - bool superMasterBackend(const string &ip, const DNSName &domain, const vector&nsset, string *nameserver, string *account, DNSBackend **db) override; + bool superMasterBackend(const string& ip, const DNSName& domain, const vector& nsset, string* nameserver, string* account, DNSBackend** db) override; static std::mutex s_supermaster_config_lock; - bool createSlaveDomain(const string &ip, const DNSName &domain, const string &nameserver, const string &account) override; + bool createSlaveDomain(const string& ip, const DNSName& domain, const string& nameserver, const string& account) override; private: void setupDNSSEC(); @@ -245,12 +254,12 @@ private: class handle { public: - bool get(DNSResourceRecord &); + bool get(DNSResourceRecord&); void reset(); - + handle(); - shared_ptr d_records; + shared_ptr d_records; recordstorage_t::index::type::const_iterator d_iter, d_end_iter; recordstorage_t::const_iterator d_qname_iter, d_qname_end; @@ -264,11 +273,11 @@ private: bool mustlog; private: - bool get_normal(DNSResourceRecord &); - bool get_list(DNSResourceRecord &); + bool get_normal(DNSResourceRecord&); + bool get_list(DNSResourceRecord&); - void operator=(const handle& ); // don't go copying this - handle(const handle &); + void operator=(const handle&); // don't go copying this + handle(const handle&); }; unique_ptr d_getAllDomainMetadataQuery_stmt; @@ -294,25 +303,25 @@ private: set alsoNotify; //!< this is used to store the also-notify list of interested peers. std::unique_ptr d_of; handle d_handle; - static string s_binddirectory; //!< this is used to store the 'directory' setting of the bind configuration - static int s_first; //!< this is raised on construction to prevent multiple instances of us being generated + static string s_binddirectory; //!< this is used to store the 'directory' setting of the bind configuration + static int s_first; //!< this is raised on construction to prevent multiple instances of us being generated int d_transaction_id; static bool s_ignore_broken_records; bool d_hybrid; bool d_upgradeContent; - BB2DomainInfo createDomainEntry(const DNSName& domain, const string &filename); //!< does not insert in s_state + BB2DomainInfo createDomainEntry(const DNSName& domain, const string& filename); //!< does not insert in s_state void queueReloadAndStore(unsigned int id); static bool findBeforeAndAfterUnhashed(std::shared_ptr& records, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after); - static void insertRecord(std::shared_ptr& records, const DNSName& zoneName, const DNSName &qname, const QType &qtype, const string &content, int ttl, const std::string& hashed=string(), bool *auth=nullptr); + static void insertRecord(std::shared_ptr& records, const DNSName& zoneName, const DNSName& qname, const QType& qtype, const string& content, int ttl, const std::string& hashed = string(), bool* auth = nullptr); void reload() override; - static string DLDomStatusHandler(const vector&parts, Utility::pid_t ppid); - static string DLDomExtendedStatusHandler(const vector&parts, Utility::pid_t ppid); - static string DLListRejectsHandler(const vector&parts, Utility::pid_t ppid); - static string DLReloadNowHandler(const vector&parts, Utility::pid_t ppid); - static string DLAddDomainHandler(const vector&parts, Utility::pid_t ppid); + static string DLDomStatusHandler(const vector& parts, Utility::pid_t ppid); + static string DLDomExtendedStatusHandler(const vector& parts, Utility::pid_t ppid); + static string DLListRejectsHandler(const vector& parts, Utility::pid_t ppid); + static string DLReloadNowHandler(const vector& parts, Utility::pid_t ppid); + static string DLAddDomainHandler(const vector& parts, Utility::pid_t ppid); static void fixupOrderAndAuth(std::shared_ptr& records, const DNSName& zoneName, bool nsec3zone, const NSEC3PARAMRecordContent& ns3pr); static void doEmptyNonTerminals(std::shared_ptr& records, const DNSName& zoneName, bool nsec3zone, const NSEC3PARAMRecordContent& ns3pr); - void loadConfig(string *status=nullptr); + void loadConfig(string* status = nullptr); }; diff --git a/modules/bindbackend/binddnssec.cc b/modules/bindbackend/binddnssec.cc index ddf1459234..b3dd4959b4 100644 --- a/modules/bindbackend/binddnssec.cc +++ b/modules/bindbackend/binddnssec.cc @@ -31,82 +31,123 @@ void Bind2Backend::setupDNSSEC() { - if(!getArg("dnssec-db").empty()) + if (!getArg("dnssec-db").empty()) throw runtime_error("bind-dnssec-db requires building PowerDNS with SQLite3"); } bool Bind2Backend::doesDNSSEC() -{ return d_hybrid; } +{ + return d_hybrid; +} bool Bind2Backend::getNSEC3PARAM(const DNSName& name, NSEC3PARAMRecordContent* ns3p) -{ return false; } +{ + return false; +} -bool Bind2Backend::getAllDomainMetadata(const DNSName& name, std::map >& meta) -{ return false; } +bool Bind2Backend::getAllDomainMetadata(const DNSName& name, std::map>& meta) +{ + return false; +} bool Bind2Backend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) -{ return false; } +{ + return false; +} bool Bind2Backend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) -{ return false; } +{ + return false; +} bool Bind2Backend::getDomainKeys(const DNSName& name, std::vector& keys) -{ return false; } +{ + return false; +} bool Bind2Backend::removeDomainKey(const DNSName& name, unsigned int id) -{ return false; } +{ + return false; +} bool Bind2Backend::addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) -{ return false; } +{ + return false; +} bool Bind2Backend::activateDomainKey(const DNSName& name, unsigned int id) -{ return false; } +{ + return false; +} bool Bind2Backend::deactivateDomainKey(const DNSName& name, unsigned int id) -{ return false; } +{ + return false; +} bool Bind2Backend::publishDomainKey(const DNSName& name, unsigned int id) -{ return false; } +{ + return false; +} bool Bind2Backend::unpublishDomainKey(const DNSName& name, unsigned int id) -{ return false; } +{ + return false; +} bool Bind2Backend::getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) -{ return false; } +{ + return false; +} bool Bind2Backend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) -{ return false; } +{ + return false; +} bool Bind2Backend::deleteTSIGKey(const DNSName& name) -{ return false; } +{ + return false; +} -bool Bind2Backend::getTSIGKeys(std::vector &keys) -{ return false; } +bool Bind2Backend::getTSIGKeys(std::vector& keys) +{ + return false; +} void Bind2Backend::setupStatements() -{ return; } +{ + return; +} void Bind2Backend::freeStatements() -{ return; } +{ + return; +} #else #include "pdns/logger.hh" #include "pdns/ssqlite3.hh" -#define ASSERT_ROW_COLUMNS(query, row, num) { if (row.size() != num) { throw PDNSException(std::string(query) + " returned wrong number of columns, expected " #num ", got " + std::to_string(row.size())); } } +#define ASSERT_ROW_COLUMNS(query, row, num) \ + { \ + if (row.size() != num) { \ + throw PDNSException(std::string(query) + " returned wrong number of columns, expected " #num ", got " + std::to_string(row.size())); \ + } \ + } void Bind2Backend::setupDNSSEC() { - if(getArg("dnssec-db").empty() || d_hybrid) + if (getArg("dnssec-db").empty() || d_hybrid) return; try { d_dnssecdb = shared_ptr(new SSQLite3(getArg("dnssec-db"), getArg("dnssec-db-journal-mode"))); setupStatements(); } - catch(SSqlException& se) { + catch (SSqlException& se) { // this error is meant to kill the server dead - it makes no sense to continue.. - throw runtime_error("Error opening DNSSEC database in BIND backend: "+se.txtReason()); + throw runtime_error("Error opening DNSSEC database in BIND backend: " + se.txtReason()); } d_dnssecdb->setLog(::arg().mustDo("query-logging")); @@ -114,12 +155,12 @@ void Bind2Backend::setupDNSSEC() void Bind2Backend::setupStatements() { - d_getAllDomainMetadataQuery_stmt = d_dnssecdb->prepare("select kind, content from domainmetadata where domain=:domain",1); - d_getDomainMetadataQuery_stmt = d_dnssecdb->prepare("select content from domainmetadata where domain=:domain and kind=:kind",2); - d_deleteDomainMetadataQuery_stmt = d_dnssecdb->prepare("delete from domainmetadata where domain=:domain and kind=:kind",2); - d_insertDomainMetadataQuery_stmt = d_dnssecdb->prepare("insert into domainmetadata (domain, kind, content) values (:domain,:kind,:content)",3); - d_getDomainKeysQuery_stmt = d_dnssecdb->prepare("select id,flags, active, published, content from cryptokeys where domain=:domain",1); - d_deleteDomainKeyQuery_stmt = d_dnssecdb->prepare("delete from cryptokeys where domain=:domain and id=:key_id",2); + d_getAllDomainMetadataQuery_stmt = d_dnssecdb->prepare("select kind, content from domainmetadata where domain=:domain", 1); + d_getDomainMetadataQuery_stmt = d_dnssecdb->prepare("select content from domainmetadata where domain=:domain and kind=:kind", 2); + d_deleteDomainMetadataQuery_stmt = d_dnssecdb->prepare("delete from domainmetadata where domain=:domain and kind=:kind", 2); + d_insertDomainMetadataQuery_stmt = d_dnssecdb->prepare("insert into domainmetadata (domain, kind, content) values (:domain,:kind,:content)", 3); + d_getDomainKeysQuery_stmt = d_dnssecdb->prepare("select id,flags, active, published, content from cryptokeys where domain=:domain", 1); + d_deleteDomainKeyQuery_stmt = d_dnssecdb->prepare("delete from cryptokeys where domain=:domain and id=:key_id", 2); d_insertDomainKeyQuery_stmt = d_dnssecdb->prepare("insert into cryptokeys (domain, flags, active, published, content) values (:domain, :flags, :active, :published, :content)", 5); d_GetLastInsertedKeyIdQuery_stmt = d_dnssecdb->prepare("select last_insert_rowid()", 0); d_activateDomainKeyQuery_stmt = d_dnssecdb->prepare("update cryptokeys set active=1 where domain=:domain and id=:key_id", 2); @@ -159,29 +200,29 @@ bool Bind2Backend::doesDNSSEC() bool Bind2Backend::getNSEC3PARAM(const DNSName& name, NSEC3PARAMRecordContent* ns3p) { - if(!d_dnssecdb || d_hybrid) + if (!d_dnssecdb || d_hybrid) return false; string value; vector meta; getDomainMetadata(name, "NSEC3PARAM", meta); - if(!meta.empty()) - value=*meta.begin(); + if (!meta.empty()) + value = *meta.begin(); else return false; // No NSEC3 zone - static int maxNSEC3Iterations=::arg().asNum("max-nsec3-iterations"); - if(ns3p) { - auto tmp=std::dynamic_pointer_cast(DNSRecordContent::mastermake(QType::NSEC3PARAM, 1, value)); + static int maxNSEC3Iterations = ::arg().asNum("max-nsec3-iterations"); + if (ns3p) { + auto tmp = std::dynamic_pointer_cast(DNSRecordContent::mastermake(QType::NSEC3PARAM, 1, value)); *ns3p = *tmp; if (ns3p->d_iterations > maxNSEC3Iterations) { ns3p->d_iterations = maxNSEC3Iterations; - g_log<d_algorithm != 1) { - g_log<d_algorithm)<<"', setting to 1 for zone '"<d_algorithm) << "', setting to 1 for zone '" << name << "'." << endl; ns3p->d_algorithm = 1; } } @@ -189,96 +230,80 @@ bool Bind2Backend::getNSEC3PARAM(const DNSName& name, NSEC3PARAMRecordContent* n return true; } -bool Bind2Backend::getAllDomainMetadata(const DNSName& name, std::map >& meta) +bool Bind2Backend::getAllDomainMetadata(const DNSName& name, std::map>& meta) { - if(!d_dnssecdb || d_hybrid) + if (!d_dnssecdb || d_hybrid) return false; try { - d_getAllDomainMetadataQuery_stmt-> - bind("domain", name)-> - execute(); + d_getAllDomainMetadataQuery_stmt->bind("domain", name)->execute(); SSqlStatement::row_t row; - while(d_getAllDomainMetadataQuery_stmt->hasNextRow()) { + while (d_getAllDomainMetadataQuery_stmt->hasNextRow()) { d_getAllDomainMetadataQuery_stmt->nextRow(row); meta[row[0]].push_back(row[1]); } d_getAllDomainMetadataQuery_stmt->reset(); } - catch(SSqlException& se) { - throw PDNSException("Error accessing DNSSEC database in BIND backend, getAllDomainMetadata(): "+se.txtReason()); + catch (SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, getAllDomainMetadata(): " + se.txtReason()); } return true; } bool Bind2Backend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) { - if(!d_dnssecdb || d_hybrid) + if (!d_dnssecdb || d_hybrid) return false; try { - d_getDomainMetadataQuery_stmt-> - bind("domain", name)-> - bind("kind", kind)-> - execute(); + d_getDomainMetadataQuery_stmt->bind("domain", name)->bind("kind", kind)->execute(); SSqlStatement::row_t row; - while(d_getDomainMetadataQuery_stmt->hasNextRow()) { + while (d_getDomainMetadataQuery_stmt->hasNextRow()) { d_getDomainMetadataQuery_stmt->nextRow(row); meta.push_back(row[0]); } d_getDomainMetadataQuery_stmt->reset(); } - catch(SSqlException& se) { - throw PDNSException("Error accessing DNSSEC database in BIND backend, getDomainMetadata(): "+se.txtReason()); + catch (SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, getDomainMetadata(): " + se.txtReason()); } return true; } bool Bind2Backend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) { - if(!d_dnssecdb || d_hybrid) + if (!d_dnssecdb || d_hybrid) return false; try { - d_deleteDomainMetadataQuery_stmt-> - bind("domain", name)-> - bind("kind", kind)-> - execute()-> - reset(); - if(!meta.empty()) { - for(const auto& value: meta) { - d_insertDomainMetadataQuery_stmt-> - bind("domain", name)-> - bind("kind", kind)-> - bind("content", value)-> - execute()-> - reset(); + d_deleteDomainMetadataQuery_stmt->bind("domain", name)->bind("kind", kind)->execute()->reset(); + if (!meta.empty()) { + for (const auto& value : meta) { + d_insertDomainMetadataQuery_stmt->bind("domain", name)->bind("kind", kind)->bind("content", value)->execute()->reset(); } } } - catch(SSqlException& se) { - throw PDNSException("Error accessing DNSSEC database in BIND backend, setDomainMetadata(): "+se.txtReason()); + catch (SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, setDomainMetadata(): " + se.txtReason()); } return true; } bool Bind2Backend::getDomainKeys(const DNSName& name, std::vector& keys) { - if(!d_dnssecdb || d_hybrid) + if (!d_dnssecdb || d_hybrid) return false; try { - d_getDomainKeysQuery_stmt-> - bind("domain", name)-> - execute(); + d_getDomainKeysQuery_stmt->bind("domain", name)->execute(); KeyData kd; SSqlStatement::row_t row; - while(d_getDomainKeysQuery_stmt->hasNextRow()) { + while (d_getDomainKeysQuery_stmt->hasNextRow()) { d_getDomainKeysQuery_stmt->nextRow(row); kd.id = pdns_stou(row[0]); kd.flags = pdns_stou(row[1]); @@ -290,47 +315,36 @@ bool Bind2Backend::getDomainKeys(const DNSName& name, std::vector& keys d_getDomainKeysQuery_stmt->reset(); } - catch(SSqlException& se) { - throw PDNSException("Error accessing DNSSEC database in BIND backend, getDomainKeys(): "+se.txtReason()); + catch (SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, getDomainKeys(): " + se.txtReason()); } return true; } bool Bind2Backend::removeDomainKey(const DNSName& name, unsigned int id) { - if(!d_dnssecdb || d_hybrid) + if (!d_dnssecdb || d_hybrid) return false; try { - d_deleteDomainKeyQuery_stmt-> - bind("domain", name)-> - bind("key_id", id)-> - execute()-> - reset(); + d_deleteDomainKeyQuery_stmt->bind("domain", name)->bind("key_id", id)->execute()->reset(); } - catch(SSqlException& se) { - throw PDNSException("Error accessing DNSSEC database in BIND backend, removeDomainKeys(): "+se.txtReason()); + catch (SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, removeDomainKeys(): " + se.txtReason()); } return true; } bool Bind2Backend::addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) { - if(!d_dnssecdb || d_hybrid) + if (!d_dnssecdb || d_hybrid) return false; try { - d_insertDomainKeyQuery_stmt-> - bind("domain", name)-> - bind("flags", key.flags)-> - bind("active", key.active)-> - bind("published", key.published)-> - bind("content", key.content)-> - execute()-> - reset(); + d_insertDomainKeyQuery_stmt->bind("domain", name)->bind("flags", key.flags)->bind("active", key.active)->bind("published", key.published)->bind("content", key.content)->execute()->reset(); } - catch(SSqlException& se) { - throw PDNSException("Error accessing DNSSEC database in BIND backend, addDomainKey(): "+se.txtReason()); + catch (SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, addDomainKey(): " + se.txtReason()); } try { @@ -346,7 +360,7 @@ bool Bind2Backend::addDomainKey(const DNSName& name, const KeyData& key, int64_t d_GetLastInsertedKeyIdQuery_stmt->reset(); return true; } - catch (SSqlException &e) { + catch (SSqlException& e) { id = -2; return true; } @@ -356,92 +370,73 @@ bool Bind2Backend::addDomainKey(const DNSName& name, const KeyData& key, int64_t bool Bind2Backend::activateDomainKey(const DNSName& name, unsigned int id) { - if(!d_dnssecdb || d_hybrid) + if (!d_dnssecdb || d_hybrid) return false; try { - d_activateDomainKeyQuery_stmt-> - bind("domain", name)-> - bind("key_id", id)-> - execute()-> - reset(); + d_activateDomainKeyQuery_stmt->bind("domain", name)->bind("key_id", id)->execute()->reset(); } - catch(SSqlException& se) { - throw PDNSException("Error accessing DNSSEC database in BIND backend, activateDomainKey(): "+se.txtReason()); + catch (SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, activateDomainKey(): " + se.txtReason()); } return true; } bool Bind2Backend::deactivateDomainKey(const DNSName& name, unsigned int id) { - if(!d_dnssecdb || d_hybrid) + if (!d_dnssecdb || d_hybrid) return false; try { - d_deactivateDomainKeyQuery_stmt-> - bind("domain", name)-> - bind("key_id", id)-> - execute()-> - reset(); + d_deactivateDomainKeyQuery_stmt->bind("domain", name)->bind("key_id", id)->execute()->reset(); } - catch(SSqlException& se) { - throw PDNSException("Error accessing DNSSEC database in BIND backend, deactivateDomainKey(): "+se.txtReason()); + catch (SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, deactivateDomainKey(): " + se.txtReason()); } return true; } bool Bind2Backend::publishDomainKey(const DNSName& name, unsigned int id) { - if(!d_dnssecdb || d_hybrid) + if (!d_dnssecdb || d_hybrid) return false; try { - d_publishDomainKeyQuery_stmt-> - bind("domain", name)-> - bind("key_id", id)-> - execute()-> - reset(); + d_publishDomainKeyQuery_stmt->bind("domain", name)->bind("key_id", id)->execute()->reset(); } - catch(SSqlException& se) { - throw PDNSException("Error accessing DNSSEC database in BIND backend, publishDomainKey(): "+se.txtReason()); + catch (SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, publishDomainKey(): " + se.txtReason()); } return true; } bool Bind2Backend::unpublishDomainKey(const DNSName& name, unsigned int id) { - if(!d_dnssecdb || d_hybrid) + if (!d_dnssecdb || d_hybrid) return false; try { - d_unpublishDomainKeyQuery_stmt-> - bind("domain", name)-> - bind("key_id", id)-> - execute()-> - reset(); + d_unpublishDomainKeyQuery_stmt->bind("domain", name)->bind("key_id", id)->execute()->reset(); } - catch(SSqlException& se) { - throw PDNSException("Error accessing DNSSEC database in BIND backend, unpublishDomainKey(): "+se.txtReason()); + catch (SSqlException& se) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, unpublishDomainKey(): " + se.txtReason()); } return true; } - bool Bind2Backend::getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) { - if(!d_dnssecdb || d_hybrid) + if (!d_dnssecdb || d_hybrid) return false; try { - d_getTSIGKeyQuery_stmt-> - bind("key_name", name)-> - execute(); + d_getTSIGKeyQuery_stmt->bind("key_name", name)->execute(); SSqlStatement::row_t row; content->clear(); - while(d_getTSIGKeyQuery_stmt->hasNextRow()) { + while (d_getTSIGKeyQuery_stmt->hasNextRow()) { d_getTSIGKeyQuery_stmt->nextRow(row); - if(row.size() >= 2 && (algorithm->empty() || *algorithm == DNSName(row[0]))) { + if (row.size() >= 2 && (algorithm->empty() || *algorithm == DNSName(row[0]))) { *algorithm = DNSName(row[0]); *content = row[1]; } @@ -449,59 +444,50 @@ bool Bind2Backend::getTSIGKey(const DNSName& name, DNSName* algorithm, string* c d_getTSIGKeyQuery_stmt->reset(); } - catch (SSqlException &e) { - throw PDNSException("Error accessing DNSSEC database in BIND backend, getTSIGKey(): "+e.txtReason()); + catch (SSqlException& e) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, getTSIGKey(): " + e.txtReason()); } return !content->empty(); } bool Bind2Backend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) { - if(!d_dnssecdb || d_hybrid) + if (!d_dnssecdb || d_hybrid) return false; try { - d_setTSIGKeyQuery_stmt-> - bind("key_name", name)-> - bind("algorithm", algorithm)-> - bind("content", content)-> - execute()-> - reset(); + d_setTSIGKeyQuery_stmt->bind("key_name", name)->bind("algorithm", algorithm)->bind("content", content)->execute()->reset(); } - catch (SSqlException &e) { - throw PDNSException("Error accessing DNSSEC database in BIND backend, setTSIGKey(): "+e.txtReason()); + catch (SSqlException& e) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, setTSIGKey(): " + e.txtReason()); } return true; } bool Bind2Backend::deleteTSIGKey(const DNSName& name) { - if(!d_dnssecdb || d_hybrid) + if (!d_dnssecdb || d_hybrid) return false; try { - d_deleteTSIGKeyQuery_stmt-> - bind("key_name", name)-> - execute()-> - reset(); + d_deleteTSIGKeyQuery_stmt->bind("key_name", name)->execute()->reset(); } - catch (SSqlException &e) { - throw PDNSException("Error accessing DNSSEC database in BIND backend, deleteTSIGKey(): "+e.txtReason()); + catch (SSqlException& e) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, deleteTSIGKey(): " + e.txtReason()); } return true; } -bool Bind2Backend::getTSIGKeys(std::vector< struct TSIGKey > &keys) +bool Bind2Backend::getTSIGKeys(std::vector& keys) { - if(!d_dnssecdb || d_hybrid) + if (!d_dnssecdb || d_hybrid) return false; try { - d_getTSIGKeysQuery_stmt-> - execute(); + d_getTSIGKeysQuery_stmt->execute(); SSqlStatement::row_t row; - while(d_getTSIGKeysQuery_stmt->hasNextRow()) { + while (d_getTSIGKeysQuery_stmt->hasNextRow()) { d_getTSIGKeysQuery_stmt->nextRow(row); struct TSIGKey key; key.name = DNSName(row[0]); @@ -512,8 +498,8 @@ bool Bind2Backend::getTSIGKeys(std::vector< struct TSIGKey > &keys) d_getTSIGKeysQuery_stmt->reset(); } - catch (SSqlException &e) { - throw PDNSException("Error accessing DNSSEC database in BIND backend, getTSIGKeys(): "+e.txtReason()); + catch (SSqlException& e) { + throw PDNSException("Error accessing DNSSEC database in BIND backend, getTSIGKeys(): " + e.txtReason()); } return !keys.empty(); } diff --git a/modules/geoipbackend/geoipbackend.cc b/modules/geoipbackend/geoipbackend.cc index d52ad031c8..bf1a89e33d 100644 --- a/modules/geoipbackend/geoipbackend.cc +++ b/modules/geoipbackend/geoipbackend.cc @@ -34,23 +34,26 @@ ReadWriteLock GeoIPBackend::s_state_lock; -struct GeoIPDNSResourceRecord: DNSResourceRecord { +struct GeoIPDNSResourceRecord : DNSResourceRecord +{ int weight; bool has_weight; }; -struct GeoIPService { - NetmaskTree > masks; +struct GeoIPService +{ + NetmaskTree> masks; unsigned int netmask4; unsigned int netmask6; }; -struct GeoIPDomain { +struct GeoIPDomain +{ int id; DNSName domain; int ttl; map services; - map > records; + map> records; vector mapping_lookup_formats; map custom_mapping; }; @@ -58,8 +61,8 @@ struct GeoIPDomain { static vector s_domains; static int s_rc = 0; // refcount - always accessed under lock -static string GeoIP_WEEKDAYS[] = { "mon", "tue", "wed", "thu", "fri", "sat", "sun" }; -static string GeoIP_MONTHS[] = { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" }; +static string GeoIP_WEEKDAYS[] = {"mon", "tue", "wed", "thu", "fri", "sat", "sun"}; +static string GeoIP_MONTHS[] = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"}; /* So how does it work - we have static records and services. Static records "win". We also insert empty non terminals for records and services. @@ -70,12 +73,13 @@ static string GeoIP_MONTHS[] = { "jan", "feb", "mar", "apr", "may", "jun", "jul" If the reference is external, we spoof up a CNAME, and good luck with that */ -GeoIPBackend::GeoIPBackend(const string& suffix) { +GeoIPBackend::GeoIPBackend(const string& suffix) +{ WriteLock wl(&s_state_lock); d_dnssec = false; setArgPrefix("geoip" + suffix); if (getArg("dnssec-keydir").empty() == false) { - DIR *d = opendir(getArg("dnssec-keydir").c_str()); + DIR* d = opendir(getArg("dnssec-keydir").c_str()); if (d == NULL) { throw PDNSException("dnssec-keydir " + getArg("dnssec-keydir") + " does not exist"); } @@ -88,7 +92,7 @@ GeoIPBackend::GeoIPBackend(const string& suffix) { s_rc++; } -static vector > s_geoip_files; +static vector> s_geoip_files; string getGeoForLua(const std::string& ip, int qaint); static string queryGeoIP(const Netmask& addr, GeoIPInterface::GeoIPQueryAttribute attribute, GeoIPNetmask& gl); @@ -96,15 +100,18 @@ static string queryGeoIP(const Netmask& addr, GeoIPInterface::GeoIPQueryAttribut // validateMappingLookupFormats validates any custom format provided by the // user does not use the custom mapping placeholder again, else it would do an // infinite recursion. -static bool validateMappingLookupFormats(const vector& formats) { - string::size_type cur,last; +static bool validateMappingLookupFormats(const vector& formats) +{ + string::size_type cur, last; for (const auto& lookupFormat : formats) { - last=0; - while((cur = lookupFormat.find("%", last)) != string::npos) { - if (!lookupFormat.compare(cur,3,"%mp")) { + last = 0; + while ((cur = lookupFormat.find("%", last)) != string::npos) { + if (!lookupFormat.compare(cur, 3, "%mp")) { return false; - } else if (!lookupFormat.compare(cur,2,"%%")) { // Ensure escaped % is also accepted - last = cur + 2; continue; + } + else if (!lookupFormat.compare(cur, 2, "%%")) { // Ensure escaped % is also accepted + last = cur + 2; + continue; } last = cur + 1; // move to next attribute } @@ -112,7 +119,8 @@ static bool validateMappingLookupFormats(const vector& formats) { return true; } -void GeoIPBackend::initialize() { +void GeoIPBackend::initialize() +{ YAML::Node config; vector tmp_domains; @@ -121,19 +129,20 @@ void GeoIPBackend::initialize() { if (getArg("database-files").empty() == false) { vector files; stringtok(files, getArg("database-files"), " ,\t\r\n"); - for(auto const& file: files) { + for (auto const& file : files) { s_geoip_files.push_back(GeoIPInterface::makeInterface(file)); } } if (s_geoip_files.empty()) - g_log<>(); } - for(YAML::const_iterator _domain = config["domains"].begin(); _domain != config["domains"].end(); _domain++) { + for (YAML::const_iterator _domain = config["domains"].begin(); _domain != config["domains"].end(); _domain++) { const auto& domain = *_domain; GeoIPDomain dom; dom.id = tmp_domains.size(); dom.domain = DNSName(domain["domain"].as()); dom.ttl = domain["ttl"].as(); - for(YAML::const_iterator recs = domain["records"].begin(); recs != domain["records"].end(); recs++) { + for (YAML::const_iterator recs = domain["records"].begin(); recs != domain["records"].end(); recs++) { DNSName qname = DNSName(recs->first.as()); vector rrs; - for(YAML::const_iterator item = recs->second.begin(); item != recs->second.end(); item++) { + for (YAML::const_iterator item = recs->second.begin(); item != recs->second.end(); item++) { YAML::const_iterator rec = item->begin(); GeoIPDNSResourceRecord rr; rr.domain_id = dom.id; @@ -169,7 +178,8 @@ void GeoIPBackend::initialize() { rr.qname = qname; if (rec->first.IsNull()) { rr.qtype = QType(0); - } else { + } + else { string qtype = boost::to_upper_copy(rec->first.as()); rr.qtype = qtype; } @@ -177,28 +187,33 @@ void GeoIPBackend::initialize() { rr.weight = 100; if (rec->second.IsNull()) { rr.content = ""; - } else if (rec->second.IsMap()) { - for(YAML::const_iterator iter = rec->second.begin(); iter != rec->second.end(); iter++) { - string attr = iter->first.as(); - if (attr == "content") { - string content = iter->second.as(); - rr.content = content; - } else if (attr == "weight") { - rr.weight = iter->second.as(); - if (rr.weight <= 0) { - g_log<second.as(); - } else { - g_log<second.as(); + } + else if (rec->second.IsMap()) { + for (YAML::const_iterator iter = rec->second.begin(); iter != rec->second.end(); iter++) { + string attr = iter->first.as(); + if (attr == "content") { + string content = iter->second.as(); + rr.content = content; + } + else if (attr == "weight") { + rr.weight = iter->second.as(); + if (rr.weight <= 0) { + g_log << Logger::Error << "Weight must be positive for " << rr.qname << endl; + throw PDNSException(string("Weight must be positive for ") + rr.qname.toLogString()); + } + rr.has_weight = true; + } + else if (attr == "ttl") { + rr.ttl = iter->second.as(); + } + else { + g_log << Logger::Error << "Unsupported record attribute " << attr << " for " << rr.qname << endl; + throw PDNSException(string("Unsupported record attribute ") + attr + string(" for ") + rr.qname.toLogString()); + } + } + } + else { + string content = rec->second.as(); rr.content = content; rr.weight = 100; } @@ -208,24 +223,26 @@ void GeoIPBackend::initialize() { std::swap(dom.records[qname], rrs); } - for(YAML::const_iterator service = domain["services"].begin(); service != domain["services"].end(); service++) { + for (YAML::const_iterator service = domain["services"].begin(); service != domain["services"].end(); service++) { unsigned int netmask4 = 0, netmask6 = 0; DNSName srvName{service->first.as()}; - NetmaskTree > nmt; + NetmaskTree> nmt; // if it's an another map, we need to iterate it again, otherwise we just add two root entries. if (service->second.IsMap()) { - for(YAML::const_iterator net = service->second.begin(); net != service->second.end(); net++) { + for (YAML::const_iterator net = service->second.begin(); net != service->second.end(); net++) { vector value; if (net->second.IsSequence()) { - value = net->second.as >(); - } else { + value = net->second.as>(); + } + else { value.push_back(net->second.as()); } if (net->first.as() == "default") { - nmt.insert(Netmask("0.0.0.0/0")).second.assign(value.begin(),value.end()); + nmt.insert(Netmask("0.0.0.0/0")).second.assign(value.begin(), value.end()); nmt.insert(Netmask("::/0")).second.swap(value); - } else { + } + else { Netmask nm{net->first.as()}; nmt.insert(nm).second.swap(value); if (nm.isIPv6() == true && netmask6 < nm.getBits()) @@ -234,14 +251,16 @@ void GeoIPBackend::initialize() { netmask4 = nm.getBits(); } } - } else { + } + else { vector value; if (service->second.IsSequence()) { - value = service->second.as >(); - } else { + value = service->second.as>(); + } + else { value.push_back(service->second.as()); } - nmt.insert(Netmask("0.0.0.0/0")).second.assign(value.begin(),value.end()); + nmt.insert(Netmask("0.0.0.0/0")).second.assign(value.begin(), value.end()); nmt.insert(Netmask("::/0")).second.swap(value); } @@ -253,12 +272,14 @@ void GeoIPBackend::initialize() { throw PDNSException(string("%mp is not allowed in mapping lookup formats of domain ") + dom.domain.toLogString()); dom.mapping_lookup_formats = mapping_lookup_formats; - } else { + } + else { dom.mapping_lookup_formats = global_mapping_lookup_formats; } if (YAML::Node mapping = domain["custom_mapping"]) { - dom.custom_mapping = mapping.as>(); - } else { + dom.custom_mapping = mapping.as>(); + } + else { dom.custom_mapping = global_custom_mapping; } @@ -268,10 +289,10 @@ void GeoIPBackend::initialize() { } // rectify the zone, first static records - for(auto &item : dom.records) { + for (auto& item : dom.records) { // ensure we have parent in records DNSName name = item.first; - while(name.chopOff() && name.isPartOf(dom.domain)) { + while (name.chopOff() && name.isPartOf(dom.domain)) { if (dom.records.find(name) == dom.records.end() && !dom.services.count(name)) { // don't ENT out a service! GeoIPDNSResourceRecord rr; vector rrs; @@ -290,10 +311,10 @@ void GeoIPBackend::initialize() { } // then services - for(auto &item : dom.services) { + for (auto& item : dom.services) { // ensure we have parent in records DNSName name = item.first; - while(name.chopOff() && name.isPartOf(dom.domain)) { + while (name.chopOff() && name.isPartOf(dom.domain)) { if (dom.records.find(name) == dom.records.end()) { GeoIPDNSResourceRecord rr; vector rrs; @@ -312,30 +333,31 @@ void GeoIPBackend::initialize() { } // finally fix weights - for(auto &item: dom.records) { + for (auto& item : dom.records) { map weights; map sums; map lasts; - bool has_weight=false; + bool has_weight = false; // first we look for used weight - for(const auto &rr: item.second) { + for (const auto& rr : item.second) { weights[rr.qtype.getCode()] += rr.weight; - if (rr.has_weight) has_weight = true; + if (rr.has_weight) + has_weight = true; } if (has_weight) { // put them back as probabilities and values.. - for(auto &rr: item.second) { + for (auto& rr : item.second) { uint16_t rr_type = rr.qtype.getCode(); - rr.weight=static_cast((static_cast(rr.weight) / weights[rr_type])*1000.0); + rr.weight = static_cast((static_cast(rr.weight) / weights[rr_type]) * 1000.0); sums[rr_type] += rr.weight; rr.has_weight = has_weight; lasts[rr_type] = &rr; } // remove rounding gap - for(auto &x: lasts) { + for (auto& x : lasts) { float sum = sums[x.first]; if (sum < 1000) - x.second->weight += (1000-sum); + x.second->weight += (1000 - sum); } } } @@ -350,7 +372,8 @@ void GeoIPBackend::initialize() { g_getGeo = getGeoForLua; } -GeoIPBackend::~GeoIPBackend() { +GeoIPBackend::~GeoIPBackend() +{ try { WriteLock wl(&s_state_lock); s_rc--; @@ -359,30 +382,32 @@ GeoIPBackend::~GeoIPBackend() { s_domains.clear(); } } - catch(...) { + catch (...) { } } -bool GeoIPBackend::lookup_static(const GeoIPDomain &dom, const DNSName &search, const QType &qtype, const DNSName& qdomain, const Netmask& addr, GeoIPNetmask &gl) { +bool GeoIPBackend::lookup_static(const GeoIPDomain& dom, const DNSName& search, const QType& qtype, const DNSName& qdomain, const Netmask& addr, GeoIPNetmask& gl) +{ const auto& i = dom.records.find(search); - map cumul_probabilities; - map weighted_match; - int probability_rnd = 1+(dns_random(1000)); // setting probability=0 means it never is used + map cumul_probabilities; + map weighted_match; + int probability_rnd = 1 + (dns_random(1000)); // setting probability=0 means it never is used if (i != dom.records.end()) { // return static value - for(const auto& rr : i->second) { + for (const auto& rr : i->second) { if ((qtype != QType::ANY && rr.qtype != qtype) || weighted_match[rr.qtype.getCode()]) continue; if (rr.has_weight) { - gl.netmask = (addr.isIPv6()?128:32); + gl.netmask = (addr.isIPv6() ? 128 : 32); int comp = cumul_probabilities[rr.qtype.getCode()]; cumul_probabilities[rr.qtype.getCode()] += rr.weight; if (rr.weight == 0 || probability_rnd < comp || probability_rnd > (comp + rr.weight)) continue; } const string& content = format2str(rr.content, addr, gl, dom); - if (rr.qtype != QType::ENT && rr.qtype != QType::TXT && content.empty()) continue; + if (rr.qtype != QType::ENT && rr.qtype != QType::TXT && content.empty()) + continue; d_result.push_back(rr); d_result.back().content = content; d_result.back().qname = qdomain; @@ -392,7 +417,7 @@ bool GeoIPBackend::lookup_static(const GeoIPDomain &dom, const DNSName &search, weighted_match[rr.qtype.getCode()] = true; } // ensure we get most strict netmask - for(DNSResourceRecord& rr: d_result) { + for (DNSResourceRecord& rr : d_result) { rr.scopeMask = gl.netmask; } return true; // no need to go further @@ -401,13 +426,14 @@ bool GeoIPBackend::lookup_static(const GeoIPDomain &dom, const DNSName &search, return false; }; -void GeoIPBackend::lookup(const QType &qtype, const DNSName& qdomain, int zoneId, DNSPacket *pkt_p) { +void GeoIPBackend::lookup(const QType& qtype, const DNSName& qdomain, int zoneId, DNSPacket* pkt_p) +{ ReadLock rl(&s_state_lock); const GeoIPDomain* dom; GeoIPNetmask gl; bool found = false; - if (d_result.size()>0) + if (d_result.size() > 0) throw PDNSException("Cannot perform lookup while another is running"); d_result.clear(); @@ -415,14 +441,15 @@ void GeoIPBackend::lookup(const QType &qtype, const DNSName& qdomain, int zoneId if (zoneId > -1 && zoneId < static_cast(s_domains.size())) dom = &(s_domains[zoneId]); else { - for(const GeoIPDomain& i : s_domains) { // this is arguably wrong, we should probably find the most specific match + for (const GeoIPDomain& i : s_domains) { // this is arguably wrong, we should probably find the most specific match if (qdomain.isPartOf(i.domain)) { dom = &i; found = true; break; } } - if (!found) return; // not found + if (!found) + return; // not found } Netmask addr{"0.0.0.0/0"}; @@ -434,10 +461,12 @@ void GeoIPBackend::lookup(const QType &qtype, const DNSName& qdomain, int zoneId (void)this->lookup_static(*dom, qdomain, qtype, qdomain, addr, gl); const auto& target = (*dom).services.find(qdomain); - if (target == (*dom).services.end()) return; // no hit + if (target == (*dom).services.end()) + return; // no hit - const NetmaskTree >::node_type* node = target->second.masks.lookup(addr); - if (node == NULL) return; // no hit, again. + const NetmaskTree>::node_type* node = target->second.masks.lookup(addr); + if (node == NULL) + return; // no hit, again. DNSName sformat; gl.netmask = node->first.getBits(); @@ -452,7 +481,8 @@ void GeoIPBackend::lookup(const QType &qtype, const DNSName& qdomain, int zoneId else gl.netmask = target->second.netmask4; } - } else { + } + else { if (addr.isIPv6()) gl.netmask = target->second.netmask6; else @@ -460,7 +490,7 @@ void GeoIPBackend::lookup(const QType &qtype, const DNSName& qdomain, int zoneId } // note that this means the array format won't work with indirect - for(auto it = node->second.begin(); it != node->second.end(); it++) { + for (auto it = node->second.begin(); it != node->second.end(); it++) { sformat = DNSName(format2str(*it, addr, gl, *dom)); // see if the record can be found @@ -469,16 +499,16 @@ void GeoIPBackend::lookup(const QType &qtype, const DNSName& qdomain, int zoneId } if (!d_result.empty()) { - g_log<id; @@ -491,8 +521,10 @@ void GeoIPBackend::lookup(const QType &qtype, const DNSName& qdomain, int zoneId d_result.push_back(rr); } -bool GeoIPBackend::get(DNSResourceRecord &r) { - if (d_result.empty()) return false; +bool GeoIPBackend::get(DNSResourceRecord& r) +{ + if (d_result.empty()) + return false; r = d_result.back(); d_result.pop_back(); @@ -500,59 +532,78 @@ bool GeoIPBackend::get(DNSResourceRecord &r) { return true; } -static string queryGeoIP(const Netmask& addr, GeoIPInterface::GeoIPQueryAttribute attribute, GeoIPNetmask& gl) { +static string queryGeoIP(const Netmask& addr, GeoIPInterface::GeoIPQueryAttribute attribute, GeoIPNetmask& gl) +{ string ret = "unknown"; - for(auto const& gi: s_geoip_files) { + for (auto const& gi : s_geoip_files) { string val; const string ip = addr.toStringNoMask(); bool found = false; - switch(attribute) { + switch (attribute) { case GeoIPInterface::ASn: - if (addr.isIPv6()) found = gi->queryASnumV6(val, gl, ip); - else found =gi->queryASnum(val, gl, ip); + if (addr.isIPv6()) + found = gi->queryASnumV6(val, gl, ip); + else + found = gi->queryASnum(val, gl, ip); break; case GeoIPInterface::Name: - if (addr.isIPv6()) found = gi->queryNameV6(val, gl, ip); - else found = gi->queryName(val, gl, ip); + if (addr.isIPv6()) + found = gi->queryNameV6(val, gl, ip); + else + found = gi->queryName(val, gl, ip); break; case GeoIPInterface::Continent: - if (addr.isIPv6()) found = gi->queryContinentV6(val, gl, ip); - else found = gi->queryContinent(val, gl, ip); + if (addr.isIPv6()) + found = gi->queryContinentV6(val, gl, ip); + else + found = gi->queryContinent(val, gl, ip); break; case GeoIPInterface::Region: - if (addr.isIPv6()) found = gi->queryRegionV6(val, gl, ip); - else found = gi->queryRegion(val, gl, ip); + if (addr.isIPv6()) + found = gi->queryRegionV6(val, gl, ip); + else + found = gi->queryRegion(val, gl, ip); break; case GeoIPInterface::Country: - if (addr.isIPv6()) found = gi->queryCountryV6(val, gl, ip); - else found = gi->queryCountry(val, gl, ip); + if (addr.isIPv6()) + found = gi->queryCountryV6(val, gl, ip); + else + found = gi->queryCountry(val, gl, ip); break; case GeoIPInterface::Country2: - if (addr.isIPv6()) found = gi->queryCountry2V6(val, gl, ip); - else found = gi->queryCountry2(val, gl, ip); + if (addr.isIPv6()) + found = gi->queryCountry2V6(val, gl, ip); + else + found = gi->queryCountry2(val, gl, ip); break; case GeoIPInterface::City: - if (addr.isIPv6()) found = gi->queryCityV6(val, gl, ip); - else found = gi->queryCity(val, gl, ip); + if (addr.isIPv6()) + found = gi->queryCityV6(val, gl, ip); + else + found = gi->queryCity(val, gl, ip); break; case GeoIPInterface::Location: - double lat=0, lon=0; + double lat = 0, lon = 0; boost::optional alt, prec; - if (addr.isIPv6()) found = gi->queryLocationV6(gl, ip, lat, lon, alt, prec); - else found = gi->queryLocation(gl, ip, lat, lon, alt, prec); - val = std::to_string(lat)+" "+std::to_string(lon); + if (addr.isIPv6()) + found = gi->queryLocationV6(gl, ip, lat, lon, alt, prec); + else + found = gi->queryLocation(gl, ip, lat, lon, alt, prec); + val = std::to_string(lat) + " " + std::to_string(lon); break; } - if (!found || val.empty() || val == "--") continue; // try next database + if (!found || val.empty() || val == "--") + continue; // try next database ret = val; std::transform(ret.begin(), ret.end(), ret.begin(), ::tolower); break; } - if (ret == "unknown") gl.netmask = (addr.isIPv6()?128:32); // prevent caching + if (ret == "unknown") + gl.netmask = (addr.isIPv6() ? 128 : 32); // prevent caching return ret; } @@ -562,50 +613,52 @@ string getGeoForLua(const std::string& ip, int qaint) try { const Netmask addr{ip}; GeoIPNetmask gl; - string res=queryGeoIP(addr, qa, gl); + string res = queryGeoIP(addr, qa, gl); // cout<<"Result for "<& alt, boost::optional& prec) + boost::optional& alt, boost::optional& prec) { - for(auto const& gi: s_geoip_files) { + for (auto const& gi : s_geoip_files) { string val; if (addr.isIPv6()) { if (gi->queryLocationV6(gl, addr.toStringNoMask(), lat, lon, alt, prec)) return true; - } else if (gi->queryLocation(gl, addr.toStringNoMask(), lat, lon, alt, prec)) - return true; + } + else if (gi->queryLocation(gl, addr.toStringNoMask(), lat, lon, alt, prec)) + return true; } return false; } -string GeoIPBackend::format2str(string sformat, const Netmask& addr, GeoIPNetmask& gl, const GeoIPDomain &dom) { - string::size_type cur,last; +string GeoIPBackend::format2str(string sformat, const Netmask& addr, GeoIPNetmask& gl, const GeoIPDomain& dom) +{ + string::size_type cur, last; boost::optional alt, prec; double lat, lon; time_t t = time((time_t*)NULL); GeoIPNetmask tmp_gl; // largest wins struct tm gtm; gmtime_r(&t, >m); - last=0; + last = 0; - while((cur = sformat.find("%", last)) != string::npos) { + while ((cur = sformat.find("%", last)) != string::npos) { string rep; - int nrep=3; + int nrep = 3; tmp_gl.netmask = 0; - if (!sformat.compare(cur,3,"%mp")) { + if (!sformat.compare(cur, 3, "%mp")) { rep = "unknown"; for (const auto& lookupFormat : dom.mapping_lookup_formats) { auto it = dom.custom_mapping.find(format2str(lookupFormat, addr, gl, dom)); @@ -614,43 +667,52 @@ string GeoIPBackend::format2str(string sformat, const Netmask& addr, GeoIPNetmas break; } } - } else if (!sformat.compare(cur,3,"%cn")) { + } + else if (!sformat.compare(cur, 3, "%cn")) { rep = queryGeoIP(addr, GeoIPInterface::Continent, tmp_gl); - } else if (!sformat.compare(cur,3,"%co")) { + } + else if (!sformat.compare(cur, 3, "%co")) { rep = queryGeoIP(addr, GeoIPInterface::Country, tmp_gl); - } else if (!sformat.compare(cur,3,"%cc")) { + } + else if (!sformat.compare(cur, 3, "%cc")) { rep = queryGeoIP(addr, GeoIPInterface::Country2, tmp_gl); - } else if (!sformat.compare(cur,3,"%af")) { - rep = (addr.isIPv6()?"v6":"v4"); - } else if (!sformat.compare(cur,3,"%as")) { + } + else if (!sformat.compare(cur, 3, "%af")) { + rep = (addr.isIPv6() ? "v6" : "v4"); + } + else if (!sformat.compare(cur, 3, "%as")) { rep = queryGeoIP(addr, GeoIPInterface::ASn, tmp_gl); - } else if (!sformat.compare(cur,3,"%re")) { + } + else if (!sformat.compare(cur, 3, "%re")) { rep = queryGeoIP(addr, GeoIPInterface::Region, tmp_gl); - } else if (!sformat.compare(cur,3,"%na")) { + } + else if (!sformat.compare(cur, 3, "%na")) { rep = queryGeoIP(addr, GeoIPInterface::Name, tmp_gl); - } else if (!sformat.compare(cur,3,"%ci")) { + } + else if (!sformat.compare(cur, 3, "%ci")) { rep = queryGeoIP(addr, GeoIPInterface::City, tmp_gl); - } else if (!sformat.compare(cur,4,"%loc")) { + } + else if (!sformat.compare(cur, 4, "%loc")) { char ns, ew; int d1, d2, m1, m2; double s1, s2; if (!queryGeoLocation(addr, gl, lat, lon, alt, prec)) { rep = ""; - tmp_gl.netmask = (addr.isIPv6()?128:32); - } else { - ns = (lat>0) ? 'N' : 'S'; - ew = (lon>0) ? 'E' : 'W'; + tmp_gl.netmask = (addr.isIPv6() ? 128 : 32); + } + else { + ns = (lat > 0) ? 'N' : 'S'; + ew = (lon > 0) ? 'E' : 'W'; /* remove sign */ lat = fabs(lat); lon = fabs(lon); d1 = static_cast(lat); d2 = static_cast(lon); - m1 = static_cast((lat - d1)*60.0); - m2 = static_cast((lon - d2)*60.0); - s1 = static_cast(lat - d1 - m1/60.0)*3600.0; - s2 = static_cast(lon - d2 - m2/60.0)*3600.0; - rep = str(boost::format("%d %d %0.3f %c %d %d %0.3f %c") % - d1 % m1 % s1 % ns % d2 % m2 % s2 % ew); + m1 = static_cast((lat - d1) * 60.0); + m2 = static_cast((lon - d2) * 60.0); + s1 = static_cast(lat - d1 - m1 / 60.0) * 3600.0; + s2 = static_cast(lon - d2 - m2 / 60.0) * 3600.0; + rep = str(boost::format("%d %d %0.3f %c %d %d %0.3f %c") % d1 % m1 % s1 % ns % d2 % m2 % s2 % ew); if (alt) rep = rep + str(boost::format(" %d.00") % *alt); else @@ -659,96 +721,121 @@ string GeoIPBackend::format2str(string sformat, const Netmask& addr, GeoIPNetmas rep = rep + str(boost::format(" %dm") % *prec); } nrep = 4; - } else if (!sformat.compare(cur,4,"%lat")) { + } + else if (!sformat.compare(cur, 4, "%lat")) { if (!queryGeoLocation(addr, gl, lat, lon, alt, prec)) { rep = ""; - tmp_gl.netmask = (addr.isIPv6()?128:32); - } else { + tmp_gl.netmask = (addr.isIPv6() ? 128 : 32); + } + else { rep = str(boost::format("%lf") % lat); } nrep = 4; - } else if (!sformat.compare(cur,4,"%lon")) { + } + else if (!sformat.compare(cur, 4, "%lon")) { if (!queryGeoLocation(addr, gl, lat, lon, alt, prec)) { rep = ""; - tmp_gl.netmask = (addr.isIPv6()?128:32); - } else { + tmp_gl.netmask = (addr.isIPv6() ? 128 : 32); + } + else { rep = str(boost::format("%lf") % lon); } nrep = 4; - } else if (!sformat.compare(cur,3,"%hh")) { + } + else if (!sformat.compare(cur, 3, "%hh")) { rep = boost::str(boost::format("%02d") % gtm.tm_hour); - tmp_gl.netmask = (addr.isIPv6()?128:32); - } else if (!sformat.compare(cur,3,"%yy")) { + tmp_gl.netmask = (addr.isIPv6() ? 128 : 32); + } + else if (!sformat.compare(cur, 3, "%yy")) { rep = boost::str(boost::format("%02d") % (gtm.tm_year + 1900)); - tmp_gl.netmask = (addr.isIPv6()?128:32); - } else if (!sformat.compare(cur,3,"%dd")) { + tmp_gl.netmask = (addr.isIPv6() ? 128 : 32); + } + else if (!sformat.compare(cur, 3, "%dd")) { rep = boost::str(boost::format("%02d") % (gtm.tm_yday + 1)); - tmp_gl.netmask = (addr.isIPv6()?128:32); - } else if (!sformat.compare(cur,4,"%wds")) { - nrep=4; + tmp_gl.netmask = (addr.isIPv6() ? 128 : 32); + } + else if (!sformat.compare(cur, 4, "%wds")) { + nrep = 4; rep = GeoIP_WEEKDAYS[gtm.tm_wday]; - tmp_gl.netmask = (addr.isIPv6()?128:32); - } else if (!sformat.compare(cur,4,"%mos")) { - nrep=4; + tmp_gl.netmask = (addr.isIPv6() ? 128 : 32); + } + else if (!sformat.compare(cur, 4, "%mos")) { + nrep = 4; rep = GeoIP_MONTHS[gtm.tm_mon]; - tmp_gl.netmask = (addr.isIPv6()?128:32); - } else if (!sformat.compare(cur,3,"%wd")) { + tmp_gl.netmask = (addr.isIPv6() ? 128 : 32); + } + else if (!sformat.compare(cur, 3, "%wd")) { rep = boost::str(boost::format("%02d") % (gtm.tm_wday + 1)); - tmp_gl.netmask = (addr.isIPv6()?128:32); - } else if (!sformat.compare(cur,3,"%mo")) { + tmp_gl.netmask = (addr.isIPv6() ? 128 : 32); + } + else if (!sformat.compare(cur, 3, "%mo")) { rep = boost::str(boost::format("%02d") % (gtm.tm_mon + 1)); - tmp_gl.netmask = (addr.isIPv6()?128:32); - } else if (!sformat.compare(cur,4,"%ip6")) { + tmp_gl.netmask = (addr.isIPv6() ? 128 : 32); + } + else if (!sformat.compare(cur, 4, "%ip6")) { nrep = 4; if (addr.isIPv6()) rep = addr.toStringNoMask(); else rep = ""; - tmp_gl.netmask = (addr.isIPv6()?128:32); - } else if (!sformat.compare(cur,4,"%ip4")) { + tmp_gl.netmask = (addr.isIPv6() ? 128 : 32); + } + else if (!sformat.compare(cur, 4, "%ip4")) { nrep = 4; if (!addr.isIPv6()) rep = addr.toStringNoMask(); else rep = ""; - tmp_gl.netmask = (addr.isIPv6()?128:32); - } else if (!sformat.compare(cur,3,"%ip")) { + tmp_gl.netmask = (addr.isIPv6() ? 128 : 32); + } + else if (!sformat.compare(cur, 3, "%ip")) { rep = addr.toStringNoMask(); - tmp_gl.netmask = (addr.isIPv6()?128:32); - } else if (!sformat.compare(cur,2,"%%")) { - last = cur + 2; continue; - } else { - last = cur + 1; continue; + tmp_gl.netmask = (addr.isIPv6() ? 128 : 32); + } + else if (!sformat.compare(cur, 2, "%%")) { + last = cur + 2; + continue; } - if (tmp_gl.netmask > gl.netmask) gl.netmask = tmp_gl.netmask; + else { + last = cur + 1; + continue; + } + if (tmp_gl.netmask > gl.netmask) + gl.netmask = tmp_gl.netmask; sformat.replace(cur, nrep, rep); last = cur + rep.size(); // move to next attribute } return sformat; } -void GeoIPBackend::reload() { +void GeoIPBackend::reload() +{ WriteLock wl(&s_state_lock); try { initialize(); - } catch (PDNSException &pex) { - g_log<getSOA(domain, sd); @@ -763,11 +850,13 @@ bool GeoIPBackend::getDomainInfo(const DNSName& domain, DomainInfo &di, bool get return false; } -bool GeoIPBackend::getAllDomainMetadata(const DNSName& name, std::map >& meta) { - if (!d_dnssec) return false; +bool GeoIPBackend::getAllDomainMetadata(const DNSName& name, std::map>& meta) +{ + if (!d_dnssec) + return false; ReadLock rl(&s_state_lock); - for(GeoIPDomain dom : s_domains) { + for (GeoIPDomain dom : s_domains) { if (dom.domain == name) { if (hasDNSSECkey(dom.domain)) { meta[string("NSEC3NARROW")].push_back("1"); @@ -779,11 +868,13 @@ bool GeoIPBackend::getAllDomainMetadata(const DNSName& name, std::map& meta) { - if (!d_dnssec) return false; +bool GeoIPBackend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) +{ + if (!d_dnssec) + return false; ReadLock rl(&s_state_lock); - for(GeoIPDomain dom : s_domains) { + for (GeoIPDomain dom : s_domains) { if (dom.domain == name) { if (hasDNSSECkey(dom.domain)) { if (kind == "NSEC3NARROW") @@ -797,31 +888,33 @@ bool GeoIPBackend::getDomainMetadata(const DNSName& name, const std::string& kin return false; } -bool GeoIPBackend::getDomainKeys(const DNSName& name, std::vector& keys) { - if (!d_dnssec) return false; +bool GeoIPBackend::getDomainKeys(const DNSName& name, std::vector& keys) +{ + if (!d_dnssec) + return false; ReadLock rl(&s_state_lock); - for(GeoIPDomain dom : s_domains) { + for (GeoIPDomain dom : s_domains) { if (dom.domain == name) { regex_t reg; regmatch_t regm[5]; - regcomp(®, "(.*)[.]([0-9]+)[.]([0-9]+)[.]([01])[.]key$", REG_ICASE|REG_EXTENDED); + regcomp(®, "(.*)[.]([0-9]+)[.]([0-9]+)[.]([01])[.]key$", REG_ICASE | REG_EXTENDED); ostringstream pathname; pathname << getArg("dnssec-keydir") << "/" << dom.domain.toStringNoDot() << "*.key"; glob_t glob_result; - if (glob(pathname.str().c_str(),GLOB_ERR,NULL,&glob_result) == 0) { - for(size_t i=0;i0) { + if (ifs.gcount() > 0) { content << string(buffer, ifs.gcount()); } } @@ -839,23 +932,25 @@ bool GeoIPBackend::getDomainKeys(const DNSName& name, std::vector= nextid) nextid = kid+1; + unsigned int kid = pdns_stou(glob_result.gl_pathv[i] + regm[3].rm_so); + if (kid >= nextid) + nextid = kid + 1; } } } regfree(®); globfree(&glob_result); pathname.str(""); - pathname << getArg("dnssec-keydir") << "/" << dom.domain.toStringNoDot() << "." << key.flags << "." << nextid << "." << (key.active?"1":"0") << ".key"; + pathname << getArg("dnssec-keydir") << "/" << dom.domain.toStringNoDot() << "." << key.flags << "." << nextid << "." << (key.active ? "1" : "0") << ".key"; ofstream ofs(pathname.str().c_str()); ofs.write(key.content.c_str(), key.content.size()); ofs.close(); @@ -906,27 +1004,28 @@ bool GeoIPBackend::addDomainKey(const DNSName& name, const KeyData& key, int64_t } } return false; - } -bool GeoIPBackend::activateDomainKey(const DNSName& name, unsigned int id) { - if (!d_dnssec) return false; +bool GeoIPBackend::activateDomainKey(const DNSName& name, unsigned int id) +{ + if (!d_dnssec) + return false; WriteLock rl(&s_state_lock); - for(GeoIPDomain dom : s_domains) { + for (GeoIPDomain dom : s_domains) { if (dom.domain == name) { regex_t reg; regmatch_t regm[5]; - regcomp(®, "(.*)[.]([0-9]+)[.]([0-9]+)[.]([01])[.]key$", REG_ICASE|REG_EXTENDED); + regcomp(®, "(.*)[.]([0-9]+)[.]([0-9]+)[.]([01])[.]key$", REG_ICASE | REG_EXTENDED); ostringstream pathname; pathname << getArg("dnssec-keydir") << "/" << dom.domain.toStringNoDot() << "*.key"; glob_t glob_result; - if (glob(pathname.str().c_str(),GLOB_ERR,NULL,&glob_result) == 0) { - for(size_t i=0;i >& meta) override; + bool getAllDomainMetadata(const DNSName& name, std::map>& meta) override; bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) override; bool getDomainKeys(const DNSName& name, std::vector& keys) override; bool removeDomainKey(const DNSName& name, unsigned int id) override; @@ -70,10 +72,10 @@ private: static ReadWriteLock s_state_lock; void initialize(); - string format2str(string format, const Netmask &addr, GeoIPNetmask& gl, const GeoIPDomain &dom); + string format2str(string format, const Netmask& addr, GeoIPNetmask& gl, const GeoIPDomain& dom); bool d_dnssec; bool hasDNSSECkey(const DNSName& name); - bool lookup_static(const GeoIPDomain &dom, const DNSName &search, const QType &qtype, const DNSName& qdomain, const Netmask &addr, GeoIPNetmask& gl); + bool lookup_static(const GeoIPDomain& dom, const DNSName& search, const QType& qtype, const DNSName& qdomain, const Netmask& addr, GeoIPNetmask& gl); vector d_result; vector d_files; }; diff --git a/modules/geoipbackend/geoipinterface-dat.cc b/modules/geoipbackend/geoipinterface-dat.cc index 87e261ccfd..584ae94bce 100644 --- a/modules/geoipbackend/geoipinterface-dat.cc +++ b/modules/geoipbackend/geoipinterface-dat.cc @@ -28,33 +28,41 @@ #include "GeoIPCity.h" #include "GeoIP.h" -struct geoip_deleter { - void operator()(GeoIP* ptr) { +struct geoip_deleter +{ + void operator()(GeoIP* ptr) + { if (ptr) { GeoIP_delete(ptr); } }; }; -struct geoiprecord_deleter { - void operator()(GeoIPRecord* ptr) { +struct geoiprecord_deleter +{ + void operator()(GeoIPRecord* ptr) + { if (ptr) { GeoIPRecord_delete(ptr); } } }; -struct geoipregion_deleter { - void operator()(GeoIPRegion* ptr) { +struct geoipregion_deleter +{ + void operator()(GeoIPRegion* ptr) + { if (ptr) { GeoIPRegion_delete(ptr); } } }; -class GeoIPInterfaceDAT : public GeoIPInterface { +class GeoIPInterfaceDAT : public GeoIPInterface +{ public: - GeoIPInterfaceDAT(const string &fname, const string &modeStr) { + GeoIPInterfaceDAT(const string& fname, const string& modeStr) + { int flags; if (modeStr == "standard") flags = GEOIP_STANDARD; @@ -75,28 +83,28 @@ public: d_db_type = GeoIP_database_edition(d_gi.get()); } - bool queryCountry(string &ret, GeoIPNetmask& gl, const string &ip) override { + bool queryCountry(string& ret, GeoIPNetmask& gl, const string& ip) override + { GeoIPLookup tmp_gl = { .netmask = gl.netmask, }; - if (d_db_type == GEOIP_COUNTRY_EDITION || - d_db_type == GEOIP_LARGE_COUNTRY_EDITION) { + if (d_db_type == GEOIP_COUNTRY_EDITION || d_db_type == GEOIP_LARGE_COUNTRY_EDITION) { int id; if ((id = GeoIP_id_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl)) > 0) { ret = GeoIP_code3_by_id(id); gl.netmask = tmp_gl.netmask; return true; } - } else if (d_db_type == GEOIP_REGION_EDITION_REV0 || - d_db_type == GEOIP_REGION_EDITION_REV1) { + } + else if (d_db_type == GEOIP_REGION_EDITION_REV0 || d_db_type == GEOIP_REGION_EDITION_REV1) { std::unique_ptr gir(GeoIP_region_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl)); if (gir) { gl.netmask = tmp_gl.netmask; ret = GeoIP_code3_by_id(GeoIP_id_by_code(gir->country_code)); return true; } - } else if (d_db_type == GEOIP_CITY_EDITION_REV0 || - d_db_type == GEOIP_CITY_EDITION_REV1) { + } + else if (d_db_type == GEOIP_CITY_EDITION_REV0 || d_db_type == GEOIP_CITY_EDITION_REV1) { std::unique_ptr gir(GeoIP_record_by_addr(d_gi.get(), ip.c_str())); if (gir) { ret = gir->country_code3; @@ -107,28 +115,28 @@ public: return false; } - bool queryCountryV6(string &ret, GeoIPNetmask& gl, const string &ip) override { + bool queryCountryV6(string& ret, GeoIPNetmask& gl, const string& ip) override + { GeoIPLookup tmp_gl = { .netmask = gl.netmask, }; - if (d_db_type == GEOIP_COUNTRY_EDITION_V6 || - d_db_type == GEOIP_LARGE_COUNTRY_EDITION_V6) { + if (d_db_type == GEOIP_COUNTRY_EDITION_V6 || d_db_type == GEOIP_LARGE_COUNTRY_EDITION_V6) { int id; if ((id = GeoIP_id_by_addr_v6_gl(d_gi.get(), ip.c_str(), &tmp_gl)) > 0) { ret = GeoIP_code3_by_id(id); gl.netmask = tmp_gl.netmask; return true; } - } else if (d_db_type == GEOIP_REGION_EDITION_REV0 || - d_db_type == GEOIP_REGION_EDITION_REV1) { + } + else if (d_db_type == GEOIP_REGION_EDITION_REV0 || d_db_type == GEOIP_REGION_EDITION_REV1) { std::unique_ptr gir(GeoIP_region_by_addr_v6_gl(d_gi.get(), ip.c_str(), &tmp_gl)); if (gir) { gl.netmask = tmp_gl.netmask; ret = GeoIP_code3_by_id(GeoIP_id_by_code(gir->country_code)); return true; } - } else if (d_db_type == GEOIP_CITY_EDITION_REV0_V6 || - d_db_type == GEOIP_CITY_EDITION_REV1_V6) { + } + else if (d_db_type == GEOIP_CITY_EDITION_REV0_V6 || d_db_type == GEOIP_CITY_EDITION_REV1_V6) { std::unique_ptr gir(GeoIP_record_by_addr_v6(d_gi.get(), ip.c_str())); if (gir) { ret = gir->country_code3; @@ -139,28 +147,28 @@ public: return false; } - bool queryCountry2(string &ret, GeoIPNetmask& gl, const string &ip) override { + bool queryCountry2(string& ret, GeoIPNetmask& gl, const string& ip) override + { GeoIPLookup tmp_gl = { .netmask = gl.netmask, }; - if (d_db_type == GEOIP_COUNTRY_EDITION || - d_db_type == GEOIP_LARGE_COUNTRY_EDITION) { + if (d_db_type == GEOIP_COUNTRY_EDITION || d_db_type == GEOIP_LARGE_COUNTRY_EDITION) { int id; if ((id = GeoIP_id_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl)) > 0) { ret = GeoIP_code_by_id(id); gl.netmask = tmp_gl.netmask; return true; } - } else if (d_db_type == GEOIP_REGION_EDITION_REV0 || - d_db_type == GEOIP_REGION_EDITION_REV1) { - std::unique_ptr gir(GeoIP_region_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl)); + } + else if (d_db_type == GEOIP_REGION_EDITION_REV0 || d_db_type == GEOIP_REGION_EDITION_REV1) { + std::unique_ptr gir(GeoIP_region_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl)); if (gir) { gl.netmask = tmp_gl.netmask; ret = GeoIP_code_by_id(GeoIP_id_by_code(gir->country_code)); return true; } - } else if (d_db_type == GEOIP_CITY_EDITION_REV0 || - d_db_type == GEOIP_CITY_EDITION_REV1) { + } + else if (d_db_type == GEOIP_CITY_EDITION_REV0 || d_db_type == GEOIP_CITY_EDITION_REV1) { std::unique_ptr gir(GeoIP_record_by_addr(d_gi.get(), ip.c_str())); if (gir) { ret = gir->country_code; @@ -171,28 +179,28 @@ public: return false; } - bool queryCountry2V6(string &ret, GeoIPNetmask& gl, const string &ip) override { + bool queryCountry2V6(string& ret, GeoIPNetmask& gl, const string& ip) override + { GeoIPLookup tmp_gl = { .netmask = gl.netmask, }; - if (d_db_type == GEOIP_COUNTRY_EDITION_V6 || - d_db_type == GEOIP_LARGE_COUNTRY_EDITION_V6) { + if (d_db_type == GEOIP_COUNTRY_EDITION_V6 || d_db_type == GEOIP_LARGE_COUNTRY_EDITION_V6) { int id; if ((id = GeoIP_id_by_addr_v6_gl(d_gi.get(), ip.c_str(), &tmp_gl)) > 0) { ret = GeoIP_code_by_id(id); gl.netmask = tmp_gl.netmask; return true; } - } else if (d_db_type == GEOIP_REGION_EDITION_REV0 || - d_db_type == GEOIP_REGION_EDITION_REV1) { + } + else if (d_db_type == GEOIP_REGION_EDITION_REV0 || d_db_type == GEOIP_REGION_EDITION_REV1) { std::unique_ptr gir(GeoIP_region_by_addr_v6_gl(d_gi.get(), ip.c_str(), &tmp_gl)); if (gir) { gl.netmask = tmp_gl.netmask; ret = GeoIP_code_by_id(GeoIP_id_by_code(gir->country_code)); return true; } - } else if (d_db_type == GEOIP_CITY_EDITION_REV0_V6 || - d_db_type == GEOIP_CITY_EDITION_REV1_V6) { + } + else if (d_db_type == GEOIP_CITY_EDITION_REV0_V6 || d_db_type == GEOIP_CITY_EDITION_REV1_V6) { std::unique_ptr gir(GeoIP_record_by_addr_v6(d_gi.get(), ip.c_str())); if (gir) { ret = gir->country_code; @@ -203,31 +211,31 @@ public: return false; } - bool queryContinent(string &ret, GeoIPNetmask& gl, const string &ip) override { + bool queryContinent(string& ret, GeoIPNetmask& gl, const string& ip) override + { GeoIPLookup tmp_gl = { .netmask = gl.netmask, }; - if (d_db_type == GEOIP_COUNTRY_EDITION || - d_db_type == GEOIP_LARGE_COUNTRY_EDITION) { + if (d_db_type == GEOIP_COUNTRY_EDITION || d_db_type == GEOIP_LARGE_COUNTRY_EDITION) { int id; if ((id = GeoIP_id_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl)) > 0) { ret = GeoIP_continent_by_id(id); gl.netmask = tmp_gl.netmask; return true; } - } else if (d_db_type == GEOIP_REGION_EDITION_REV0 || - d_db_type == GEOIP_REGION_EDITION_REV1) { + } + else if (d_db_type == GEOIP_REGION_EDITION_REV0 || d_db_type == GEOIP_REGION_EDITION_REV1) { std::unique_ptr gir(GeoIP_region_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl)); if (gir) { gl.netmask = tmp_gl.netmask; ret = GeoIP_continent_by_id(GeoIP_id_by_code(gir->country_code)); return true; } - } else if (d_db_type == GEOIP_CITY_EDITION_REV0 || - d_db_type == GEOIP_CITY_EDITION_REV1) { + } + else if (d_db_type == GEOIP_CITY_EDITION_REV0 || d_db_type == GEOIP_CITY_EDITION_REV1) { std::unique_ptr gir(GeoIP_record_by_addr(d_gi.get(), ip.c_str())); if (gir) { - ret = ret = GeoIP_continent_by_id(GeoIP_id_by_code(gir->country_code)); + ret = ret = GeoIP_continent_by_id(GeoIP_id_by_code(gir->country_code)); gl.netmask = gir->netmask; return true; } @@ -235,28 +243,28 @@ public: return false; } - bool queryContinentV6(string &ret, GeoIPNetmask& gl, const string &ip) override { + bool queryContinentV6(string& ret, GeoIPNetmask& gl, const string& ip) override + { GeoIPLookup tmp_gl = { .netmask = gl.netmask, }; - if (d_db_type == GEOIP_COUNTRY_EDITION_V6 || - d_db_type == GEOIP_LARGE_COUNTRY_EDITION_V6) { + if (d_db_type == GEOIP_COUNTRY_EDITION_V6 || d_db_type == GEOIP_LARGE_COUNTRY_EDITION_V6) { int id; if ((id = GeoIP_id_by_addr_v6_gl(d_gi.get(), ip.c_str(), &tmp_gl)) > 0) { ret = GeoIP_continent_by_id(id); gl.netmask = tmp_gl.netmask; return true; } - } else if (d_db_type == GEOIP_REGION_EDITION_REV0 || - d_db_type == GEOIP_REGION_EDITION_REV1) { + } + else if (d_db_type == GEOIP_REGION_EDITION_REV0 || d_db_type == GEOIP_REGION_EDITION_REV1) { std::unique_ptr gir(GeoIP_region_by_addr_v6_gl(d_gi.get(), ip.c_str(), &tmp_gl)); if (gir) { gl.netmask = tmp_gl.netmask; ret = GeoIP_continent_by_id(GeoIP_id_by_code(gir->country_code)); return true; } - } else if (d_db_type == GEOIP_CITY_EDITION_REV0_V6 || - d_db_type == GEOIP_CITY_EDITION_REV1_V6) { + } + else if (d_db_type == GEOIP_CITY_EDITION_REV0_V6 || d_db_type == GEOIP_CITY_EDITION_REV1_V6) { std::unique_ptr gir(GeoIP_record_by_addr_v6(d_gi.get(), ip.c_str())); if (gir) { ret = GeoIP_continent_by_id(GeoIP_id_by_code(gir->country_code)); @@ -267,12 +275,12 @@ public: return false; } - bool queryName(string &ret, GeoIPNetmask& gl, const string &ip) override { + bool queryName(string& ret, GeoIPNetmask& gl, const string& ip) override + { GeoIPLookup tmp_gl = { .netmask = gl.netmask, }; - if (d_db_type == GEOIP_ISP_EDITION || - d_db_type == GEOIP_ORG_EDITION) { + if (d_db_type == GEOIP_ISP_EDITION || d_db_type == GEOIP_ORG_EDITION) { char* result = GeoIP_name_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl); if (result != nullptr) { ret = result; @@ -282,17 +290,16 @@ public: ret = boost::replace_all_copy(ret, " ", "-"); return true; } - } return false; } - bool queryNameV6(string &ret, GeoIPNetmask& gl, const string &ip) override { + bool queryNameV6(string& ret, GeoIPNetmask& gl, const string& ip) override + { GeoIPLookup tmp_gl = { .netmask = gl.netmask, }; - if (d_db_type == GEOIP_ISP_EDITION_V6 || - d_db_type == GEOIP_ORG_EDITION_V6) { + if (d_db_type == GEOIP_ISP_EDITION_V6 || d_db_type == GEOIP_ORG_EDITION_V6) { char* result = GeoIP_name_by_addr_v6_gl(d_gi.get(), ip.c_str(), &tmp_gl); if (result != nullptr) { ret = result; @@ -306,7 +313,8 @@ public: return false; } - bool queryASnum(string &ret, GeoIPNetmask& gl, const string &ip) override { + bool queryASnum(string& ret, GeoIPNetmask& gl, const string& ip) override + { GeoIPLookup tmp_gl = { .netmask = gl.netmask, }; @@ -317,7 +325,7 @@ public: vector asnr; free(result); stringtok(asnr, val); - if(asnr.size()>0) { + if (asnr.size() > 0) { gl.netmask = tmp_gl.netmask; ret = asnr[0]; return true; @@ -327,7 +335,8 @@ public: return false; } - bool queryASnumV6(string &ret, GeoIPNetmask& gl, const string &ip) override { + bool queryASnumV6(string& ret, GeoIPNetmask& gl, const string& ip) override + { GeoIPLookup tmp_gl = { .netmask = gl.netmask, }; @@ -338,7 +347,7 @@ public: vector asnr; free(result); stringtok(asnr, val); - if(asnr.size()>0) { + if (asnr.size() > 0) { gl.netmask = tmp_gl.netmask; ret = asnr[0]; return true; @@ -348,23 +357,23 @@ public: return false; } - bool queryRegion(string &ret, GeoIPNetmask& gl, const string &ip) override { + bool queryRegion(string& ret, GeoIPNetmask& gl, const string& ip) override + { GeoIPLookup tmp_gl = { .netmask = gl.netmask, }; - if (d_db_type == GEOIP_REGION_EDITION_REV0 || - d_db_type == GEOIP_REGION_EDITION_REV1) { + if (d_db_type == GEOIP_REGION_EDITION_REV0 || d_db_type == GEOIP_REGION_EDITION_REV1) { std::unique_ptr gir(GeoIP_region_by_addr_gl(d_gi.get(), ip.c_str(), &tmp_gl)); if (gir) { gl.netmask = tmp_gl.netmask; - ret = valueOrEmpty(gir->region); + ret = valueOrEmpty(gir->region); return true; } - } else if (d_db_type == GEOIP_CITY_EDITION_REV0 || - d_db_type == GEOIP_CITY_EDITION_REV1) { + } + else if (d_db_type == GEOIP_CITY_EDITION_REV0 || d_db_type == GEOIP_CITY_EDITION_REV1) { std::unique_ptr gir(GeoIP_record_by_addr(d_gi.get(), ip.c_str())); if (gir) { - ret = valueOrEmpty(gir->region); + ret = valueOrEmpty(gir->region); gl.netmask = gir->netmask; return true; } @@ -372,23 +381,23 @@ public: return false; } - bool queryRegionV6(string &ret, GeoIPNetmask& gl, const string &ip) override { + bool queryRegionV6(string& ret, GeoIPNetmask& gl, const string& ip) override + { GeoIPLookup tmp_gl = { .netmask = gl.netmask, }; - if (d_db_type == GEOIP_REGION_EDITION_REV0 || - d_db_type == GEOIP_REGION_EDITION_REV1) { + if (d_db_type == GEOIP_REGION_EDITION_REV0 || d_db_type == GEOIP_REGION_EDITION_REV1) { std::unique_ptr gir(GeoIP_region_by_addr_v6_gl(d_gi.get(), ip.c_str(), &tmp_gl)); if (gir) { gl.netmask = tmp_gl.netmask; - ret = valueOrEmpty(gir->region); + ret = valueOrEmpty(gir->region); return true; } - } else if (d_db_type == GEOIP_CITY_EDITION_REV0_V6 || - d_db_type == GEOIP_CITY_EDITION_REV1_V6) { + } + else if (d_db_type == GEOIP_CITY_EDITION_REV0_V6 || d_db_type == GEOIP_CITY_EDITION_REV1_V6) { std::unique_ptr gir(GeoIP_record_by_addr_v6(d_gi.get(), ip.c_str())); if (gir) { - ret = valueOrEmpty(gir->region); + ret = valueOrEmpty(gir->region); gl.netmask = gir->netmask; return true; } @@ -396,12 +405,12 @@ public: return false; } - bool queryCity(string &ret, GeoIPNetmask& gl, const string &ip) override { - if (d_db_type == GEOIP_CITY_EDITION_REV0 || - d_db_type == GEOIP_CITY_EDITION_REV1) { + bool queryCity(string& ret, GeoIPNetmask& gl, const string& ip) override + { + if (d_db_type == GEOIP_CITY_EDITION_REV0 || d_db_type == GEOIP_CITY_EDITION_REV1) { std::unique_ptr gir(GeoIP_record_by_addr(d_gi.get(), ip.c_str())); if (gir) { - ret = valueOrEmpty(gir->city); + ret = valueOrEmpty(gir->city); gl.netmask = gir->netmask; return true; } @@ -409,12 +418,12 @@ public: return false; } - bool queryCityV6(string &ret, GeoIPNetmask& gl, const string &ip) override { - if (d_db_type == GEOIP_CITY_EDITION_REV0_V6 || - d_db_type == GEOIP_CITY_EDITION_REV1_V6) { + bool queryCityV6(string& ret, GeoIPNetmask& gl, const string& ip) override + { + if (d_db_type == GEOIP_CITY_EDITION_REV0_V6 || d_db_type == GEOIP_CITY_EDITION_REV1_V6) { std::unique_ptr gir(GeoIP_record_by_addr_v6(d_gi.get(), ip.c_str())); if (gir) { - ret = valueOrEmpty(gir->city); + ret = valueOrEmpty(gir->city); gl.netmask = gir->netmask; return true; } @@ -422,13 +431,11 @@ public: return false; } - bool queryLocationV6(GeoIPNetmask& gl, const string &ip, - double& latitude, double& longitude, - boost::optional& alt, boost::optional& prec) override { - if (d_db_type == GEOIP_REGION_EDITION_REV0 || - d_db_type == GEOIP_REGION_EDITION_REV1 || - d_db_type == GEOIP_CITY_EDITION_REV0_V6 || - d_db_type == GEOIP_CITY_EDITION_REV1_V6) { + bool queryLocationV6(GeoIPNetmask& gl, const string& ip, + double& latitude, double& longitude, + boost::optional& alt, boost::optional& prec) override + { + if (d_db_type == GEOIP_REGION_EDITION_REV0 || d_db_type == GEOIP_REGION_EDITION_REV1 || d_db_type == GEOIP_CITY_EDITION_REV0_V6 || d_db_type == GEOIP_CITY_EDITION_REV1_V6) { std::unique_ptr gir(GeoIP_record_by_addr_v6(d_gi.get(), ip.c_str())); if (gir) { latitude = gir->latitude; @@ -440,13 +447,11 @@ public: return false; } - bool queryLocation(GeoIPNetmask& gl, const string &ip, - double& latitude, double& longitude, - boost::optional& alt, boost::optional& prec) override { - if (d_db_type == GEOIP_REGION_EDITION_REV0 || - d_db_type == GEOIP_REGION_EDITION_REV1 || - d_db_type == GEOIP_CITY_EDITION_REV0 || - d_db_type == GEOIP_CITY_EDITION_REV1) { + bool queryLocation(GeoIPNetmask& gl, const string& ip, + double& latitude, double& longitude, + boost::optional& alt, boost::optional& prec) override + { + if (d_db_type == GEOIP_REGION_EDITION_REV0 || d_db_type == GEOIP_REGION_EDITION_REV1 || d_db_type == GEOIP_CITY_EDITION_REV0 || d_db_type == GEOIP_CITY_EDITION_REV1) { std::unique_ptr gir(GeoIP_record_by_addr(d_gi.get(), ip.c_str())); if (gir) { latitude = gir->latitude; @@ -458,15 +463,17 @@ public: return false; } - ~GeoIPInterfaceDAT() { } + ~GeoIPInterfaceDAT() {} + private: unsigned int d_db_type; unique_ptr d_gi; }; -unique_ptr GeoIPInterface::makeDATInterface(const string &fname, const map& opts) { +unique_ptr GeoIPInterface::makeDATInterface(const string& fname, const map& opts) +{ string mode = "standard"; - const auto &opt = opts.find("mode"); + const auto& opt = opts.find("mode"); if (opt != opts.end()) mode = opt->second; return unique_ptr(new GeoIPInterfaceDAT(fname, mode)); @@ -474,7 +481,8 @@ unique_ptr GeoIPInterface::makeDATInterface(const string &fname, #else -unique_ptr GeoIPInterface::makeDATInterface(const string &fname, const map& opts) { +unique_ptr GeoIPInterface::makeDATInterface(const string& fname, const map& opts) +{ throw PDNSException("libGeoIP support not compiled in"); } diff --git a/modules/geoipbackend/geoipinterface-mmdb.cc b/modules/geoipbackend/geoipinterface-mmdb.cc index 44cb98a324..47cf776555 100644 --- a/modules/geoipbackend/geoipinterface-mmdb.cc +++ b/modules/geoipbackend/geoipinterface-mmdb.cc @@ -29,9 +29,11 @@ #include "maxminddb.h" -class GeoIPInterfaceMMDB : public GeoIPInterface { +class GeoIPInterfaceMMDB : public GeoIPInterface +{ public: - GeoIPInterfaceMMDB(const string &fname, const string &modeStr, const string& language) { + GeoIPInterfaceMMDB(const string& fname, const string& modeStr, const string& language) + { int ec; int flags = 0; if (modeStr == "") @@ -47,12 +49,11 @@ public: if ((ec = MMDB_open(fname.c_str(), flags, &d_s)) < 0) throw PDNSException(string("Cannot open ") + fname + string(": ") + string(MMDB_strerror(ec))); d_lang = language; - g_log<& alt, boost::optional& prec) override { + bool queryLocation(GeoIPNetmask& gl, const string& ip, + double& latitude, double& longitude, + boost::optional& alt, boost::optional& prec) override + { MMDB_entry_data_s data; MMDB_lookup_result_s res; if (!mmdbLookup(ip, false, gl, res)) @@ -204,7 +217,7 @@ public: if (MMDB_get_value(&res.entry, &data, "location", "latitude", NULL) != MMDB_SUCCESS || !data.has_data) return false; latitude = data.double_value; - if (MMDB_get_value(&res.entry, &data, "location", "longitude", NULL) != MMDB_SUCCESS || !data.has_data) + if (MMDB_get_value(&res.entry, &data, "location", "longitude", NULL) != MMDB_SUCCESS || !data.has_data) return false; longitude = data.double_value; if (MMDB_get_value(&res.entry, &data, "location", "accuracy_radius", NULL) != MMDB_SUCCESS || !data.has_data) @@ -213,9 +226,10 @@ public: return true; } - bool queryLocationV6(GeoIPNetmask& gl, const string &ip, - double& latitude, double& longitude, - boost::optional& alt, boost::optional& prec) override { + bool queryLocationV6(GeoIPNetmask& gl, const string& ip, + double& latitude, double& longitude, + boost::optional& alt, boost::optional& prec) override + { MMDB_entry_data_s data; MMDB_lookup_result_s res; if (!mmdbLookup(ip, true, gl, res)) @@ -223,7 +237,7 @@ public: if (MMDB_get_value(&res.entry, &data, "location", "latitude", NULL) != MMDB_SUCCESS || !data.has_data) return false; latitude = data.double_value; - if (MMDB_get_value(&res.entry, &data, "location", "longitude", NULL) != MMDB_SUCCESS || !data.has_data) + if (MMDB_get_value(&res.entry, &data, "location", "longitude", NULL) != MMDB_SUCCESS || !data.has_data) return false; longitude = data.double_value; if (MMDB_get_value(&res.entry, &data, "location", "accuracy_radius", NULL) != MMDB_SUCCESS || !data.has_data) @@ -233,18 +247,20 @@ public: } ~GeoIPInterfaceMMDB() { MMDB_close(&d_s); }; + private: MMDB_s d_s; string d_lang; - bool mmdbLookup(const string &ip, bool v6, GeoIPNetmask& gl, MMDB_lookup_result_s& res) { + bool mmdbLookup(const string& ip, bool v6, GeoIPNetmask& gl, MMDB_lookup_result_s& res) + { int gai_ec = 0, mmdb_ec = 0; res = MMDB_lookup_string(&d_s, ip.c_str(), &gai_ec, &mmdb_ec); - + if (gai_ec != 0) - g_log< GeoIPInterface::makeMMDBInterface(const string &fname, const map& opts) { +unique_ptr GeoIPInterface::makeMMDBInterface(const string& fname, const map& opts) +{ string mode = ""; string language = "en"; - const auto &opt_mode = opts.find("mode"); + const auto& opt_mode = opts.find("mode"); if (opt_mode != opts.end()) mode = opt_mode->second; - const auto &opt_lang = opts.find("language"); + const auto& opt_lang = opts.find("language"); if (opt_lang != opts.end()) language = opt_lang->second; return unique_ptr(new GeoIPInterfaceMMDB(fname, mode, language)); @@ -271,7 +288,8 @@ unique_ptr GeoIPInterface::makeMMDBInterface(const string &fname #else -unique_ptr GeoIPInterface::makeMMDBInterface(const string &fname, const map& opts) { +unique_ptr GeoIPInterface::makeMMDBInterface(const string& fname, const map& opts) +{ throw PDNSException("libmaxminddb support not compiled in"); } diff --git a/modules/geoipbackend/geoipinterface.cc b/modules/geoipbackend/geoipinterface.cc index 0f0f8a2401..aac49eca75 100644 --- a/modules/geoipbackend/geoipinterface.cc +++ b/modules/geoipbackend/geoipinterface.cc @@ -25,7 +25,8 @@ #include "geoipbackend.hh" #include "geoipinterface.hh" -unique_ptr GeoIPInterface::makeInterface(const string& dbStr) { +unique_ptr GeoIPInterface::makeInterface(const string& dbStr) +{ /* parse dbStr */ map opts; vector parts1, parts2; @@ -39,29 +40,32 @@ unique_ptr GeoIPInterface::makeInterface(const string& dbStr) { filename = parts2[0]; size_t pos = filename.find_last_of("."); if (pos != string::npos) - driver = filename.substr(pos+1); + driver = filename.substr(pos + 1); else driver = "unknown"; - } else { + } + else { driver = parts1[0]; stringtok(parts2, parts1[1], ";"); filename = parts2[0]; } if (parts2.size() > 1) { - parts2.erase(parts2.begin(), parts2.begin()+1); - for(const auto &opt: parts2) { - vector kv; - stringtok(kv, opt, "="); - opts[kv[0]] = kv[1]; - } + parts2.erase(parts2.begin(), parts2.begin() + 1); + for (const auto& opt : parts2) { + vector kv; + stringtok(kv, opt, "="); + opts[kv[0]] = kv[1]; + } } if (driver == "dat") { - return makeDATInterface(filename, opts); - } else if (driver == "mmdb") { - return makeMMDBInterface(filename, opts); - } else { - throw PDNSException(string("Unsupported file type '") + driver + string("' (use type: prefix to force type)")); + return makeDATInterface(filename, opts); + } + else if (driver == "mmdb") { + return makeMMDBInterface(filename, opts); + } + else { + throw PDNSException(string("Unsupported file type '") + driver + string("' (use type: prefix to force type)")); } } diff --git a/modules/geoipbackend/geoipinterface.hh b/modules/geoipbackend/geoipinterface.hh index 1c7220b38f..1681d0d944 100644 --- a/modules/geoipbackend/geoipinterface.hh +++ b/modules/geoipbackend/geoipinterface.hh @@ -24,9 +24,11 @@ #include "geoipbackend.hh" -class GeoIPInterface { +class GeoIPInterface +{ public: - enum GeoIPQueryAttribute { + enum GeoIPQueryAttribute + { ASn, City, Continent, @@ -37,31 +39,34 @@ public: Location }; - virtual bool queryCountry(string &ret, GeoIPNetmask& gl, const string &ip) = 0; - virtual bool queryCountryV6(string &ret, GeoIPNetmask& gl, const string &ip) = 0; - virtual bool queryCountry2(string &ret, GeoIPNetmask& gl, const string &ip) = 0; - virtual bool queryCountry2V6(string &ret, GeoIPNetmask& gl, const string &ip) = 0; - virtual bool queryContinent(string &ret, GeoIPNetmask& gl, const string &ip) = 0; - virtual bool queryContinentV6(string &ret, GeoIPNetmask& gl, const string &ip) = 0; - virtual bool queryName(string &ret, GeoIPNetmask& gl, const string &ip) = 0; - virtual bool queryNameV6(string &ret, GeoIPNetmask& gl, const string &ip) = 0; - virtual bool queryASnum(string &ret, GeoIPNetmask& gl, const string &ip) = 0; - virtual bool queryASnumV6(string &ret, GeoIPNetmask& gl, const string &ip) = 0; - virtual bool queryRegion(string &ret, GeoIPNetmask& gl, const string &ip) = 0; - virtual bool queryRegionV6(string &ret, GeoIPNetmask& gl, const string &ip) = 0; - virtual bool queryCity(string &ret, GeoIPNetmask& gl, const string &ip) = 0; - virtual bool queryCityV6(string &ret, GeoIPNetmask& gl, const string &ip) = 0; - virtual bool queryLocation(GeoIPNetmask& gl, const string &ip, - double& latitude, double& longitude, - boost::optional& alt, boost::optional& prec) = 0; - virtual bool queryLocationV6(GeoIPNetmask& gl, const string &ip, - double& latitude, double& longitude, - boost::optional& alt, boost::optional& prec) = 0; + virtual bool queryCountry(string& ret, GeoIPNetmask& gl, const string& ip) = 0; + virtual bool queryCountryV6(string& ret, GeoIPNetmask& gl, const string& ip) = 0; + virtual bool queryCountry2(string& ret, GeoIPNetmask& gl, const string& ip) = 0; + virtual bool queryCountry2V6(string& ret, GeoIPNetmask& gl, const string& ip) = 0; + virtual bool queryContinent(string& ret, GeoIPNetmask& gl, const string& ip) = 0; + virtual bool queryContinentV6(string& ret, GeoIPNetmask& gl, const string& ip) = 0; + virtual bool queryName(string& ret, GeoIPNetmask& gl, const string& ip) = 0; + virtual bool queryNameV6(string& ret, GeoIPNetmask& gl, const string& ip) = 0; + virtual bool queryASnum(string& ret, GeoIPNetmask& gl, const string& ip) = 0; + virtual bool queryASnumV6(string& ret, GeoIPNetmask& gl, const string& ip) = 0; + virtual bool queryRegion(string& ret, GeoIPNetmask& gl, const string& ip) = 0; + virtual bool queryRegionV6(string& ret, GeoIPNetmask& gl, const string& ip) = 0; + virtual bool queryCity(string& ret, GeoIPNetmask& gl, const string& ip) = 0; + virtual bool queryCityV6(string& ret, GeoIPNetmask& gl, const string& ip) = 0; + virtual bool queryLocation(GeoIPNetmask& gl, const string& ip, + double& latitude, double& longitude, + boost::optional& alt, boost::optional& prec) + = 0; + virtual bool queryLocationV6(GeoIPNetmask& gl, const string& ip, + double& latitude, double& longitude, + boost::optional& alt, boost::optional& prec) + = 0; - virtual ~GeoIPInterface() { } + virtual ~GeoIPInterface() {} static unique_ptr makeInterface(const string& dbStr); + private: - static unique_ptr makeMMDBInterface(const string &fname, const map& opts); + static unique_ptr makeMMDBInterface(const string& fname, const map& opts); static unique_ptr makeDATInterface(const string& fname, const map& opts); }; diff --git a/modules/gmysqlbackend/gmysqlbackend.cc b/modules/gmysqlbackend/gmysqlbackend.cc index 7036788bdc..f1c10f7b4b 100644 --- a/modules/gmysqlbackend/gmysqlbackend.cc +++ b/modules/gmysqlbackend/gmysqlbackend.cc @@ -36,77 +36,79 @@ #include "smysql.hh" #include -gMySQLBackend::gMySQLBackend(const string &mode, const string &suffix) : GSQLBackend(mode,suffix) +gMySQLBackend::gMySQLBackend(const string& mode, const string& suffix) : + GSQLBackend(mode, suffix) { try { reconnect(); } - catch(SSqlException &e) { - g_log<= d_parnum) { releaseStatement(); @@ -93,17 +97,20 @@ public: } d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_TINY; d_req_bind[d_paridx].buffer = new char[1]; - *((char*)d_req_bind[d_paridx].buffer) = (value?1:0); + *((char*)d_req_bind[d_paridx].buffer) = (value ? 1 : 0); d_paridx++; return this; } - SSqlStatement* bind(const string& name, int value) { + SSqlStatement* bind(const string& name, int value) + { return bind(name, (long)value); } - SSqlStatement* bind(const string& name, uint32_t value) { + SSqlStatement* bind(const string& name, uint32_t value) + { return bind(name, (unsigned long)value); } - SSqlStatement* bind(const string& name, long value) { + SSqlStatement* bind(const string& name, long value) + { prepareStatement(); if (d_paridx >= d_parnum) { releaseStatement(); @@ -115,7 +122,8 @@ public: d_paridx++; return this; } - SSqlStatement* bind(const string& name, unsigned long value) { + SSqlStatement* bind(const string& name, unsigned long value) + { prepareStatement(); if (d_paridx >= d_parnum) { releaseStatement(); @@ -128,7 +136,8 @@ public: d_paridx++; return this; } - SSqlStatement* bind(const string& name, long long value) { + SSqlStatement* bind(const string& name, long long value) + { prepareStatement(); if (d_paridx >= d_parnum) { releaseStatement(); @@ -140,7 +149,8 @@ public: d_paridx++; return this; } - SSqlStatement* bind(const string& name, unsigned long long value) { + SSqlStatement* bind(const string& name, unsigned long long value) + { prepareStatement(); if (d_paridx >= d_parnum) { releaseStatement(); @@ -153,23 +163,25 @@ public: d_paridx++; return this; } - SSqlStatement* bind(const string& name, const std::string& value) { + SSqlStatement* bind(const string& name, const std::string& value) + { prepareStatement(); if (d_paridx >= d_parnum) { releaseStatement(); throw SSqlException("Attempt to bind more parameters than query has: " + d_query); } d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_STRING; - d_req_bind[d_paridx].buffer = new char[value.size()+1]; + d_req_bind[d_paridx].buffer = new char[value.size() + 1]; d_req_bind[d_paridx].length = new unsigned long[1]; *d_req_bind[d_paridx].length = value.size(); - d_req_bind[d_paridx].buffer_length = *d_req_bind[d_paridx].length+1; - memset(d_req_bind[d_paridx].buffer, 0, value.size()+1); + d_req_bind[d_paridx].buffer_length = *d_req_bind[d_paridx].length + 1; + memset(d_req_bind[d_paridx].buffer, 0, value.size() + 1); value.copy((char*)d_req_bind[d_paridx].buffer, value.size()); d_paridx++; return this; } - SSqlStatement* bindNull(const string& name) { + SSqlStatement* bindNull(const string& name) + { prepareStatement(); if (d_paridx >= d_parnum) { releaseStatement(); @@ -180,13 +192,15 @@ public: return this; } - SSqlStatement* execute() { + SSqlStatement* execute() + { prepareStatement(); - if (!d_stmt) return this; + if (!d_stmt) + return this; if (d_dolog) { - g_log<(mysql_stmt_field_count(d_stmt)))>0) { + if ((d_fnum = static_cast(mysql_stmt_field_count(d_stmt))) > 0) { // prepare for result d_resnum = mysql_stmt_num_rows(d_stmt); - + if (d_resnum > 0 && d_res_bind == nullptr) { MYSQL_RES* meta = mysql_stmt_result_metadata(d_stmt); d_fnum = static_cast(mysql_num_fields(meta)); // ensure correct number of fields d_res_bind = new MYSQL_BIND[d_fnum]; - memset(d_res_bind, 0, sizeof(MYSQL_BIND)*d_fnum); + memset(d_res_bind, 0, sizeof(MYSQL_BIND) * d_fnum); MYSQL_FIELD* fields = mysql_fetch_fields(meta); - for(int i = 0; i < d_fnum; i++) { - unsigned long len = std::max(fields[i].max_length, fields[i].length)+1; - if (len > 128 * 1024) len = 128 * 1024; // LONGTEXT may tell us it needs 4GB! + for (int i = 0; i < d_fnum; i++) { + unsigned long len = std::max(fields[i].max_length, fields[i].length) + 1; + if (len > 128 * 1024) + len = 128 * 1024; // LONGTEXT may tell us it needs 4GB! d_res_bind[i].is_null = new my_bool[1]; d_res_bind[i].error = new my_bool[1]; d_res_bind[i].length = new unsigned long[1]; @@ -230,7 +245,7 @@ public: d_res_bind[i].buffer_length = len; d_res_bind[i].buffer_type = MYSQL_TYPE_STRING; } - + mysql_free_result(meta); } @@ -246,20 +261,22 @@ public: } } - if(d_dolog) - g_log<= 50500 if (d_residx >= d_resnum) { mysql_stmt_free_result(d_stmt); - while(!mysql_stmt_next_result(d_stmt)) { + while (!mysql_stmt_next_result(d_stmt)) { if (mysql_stmt_store_result(d_stmt) != 0) { string error(mysql_stmt_error(d_stmt)); releaseStatement(); @@ -317,43 +335,48 @@ public: } } #endif - return this; + return this; } - SSqlStatement* getResult(result_t& result) { + SSqlStatement* getResult(result_t& result) + { result.clear(); result.reserve(d_resnum); row_t row; - while(hasNextRow()) { + while (hasNextRow()) { nextRow(row); result.push_back(std::move(row)); } - return this; + return this; } - SSqlStatement* reset() { - if (!d_stmt) return this; - int err=0; + SSqlStatement* reset() + { + if (!d_stmt) + return this; + int err = 0; mysql_stmt_free_result(d_stmt); #if MYSQL_VERSION_ID >= 50500 - while((err = mysql_stmt_next_result(d_stmt)) == 0) { + while ((err = mysql_stmt_next_result(d_stmt)) == 0) { mysql_stmt_free_result(d_stmt); } #endif - if (err>0) { + if (err > 0) { string error(mysql_stmt_error(d_stmt)); releaseStatement(); throw SSqlException("Could not get next result from mysql statement: " + d_query + string(": ") + error); } mysql_stmt_reset(d_stmt); if (d_req_bind) { - for(int i=0;i0) { + if (d_parnum > 0) { d_req_bind = new MYSQL_BIND[d_parnum]; - memset(d_req_bind, 0, sizeof(MYSQL_BIND)*d_parnum); + memset(d_req_bind, 0, sizeof(MYSQL_BIND) * d_parnum); } d_prepared = true; } - void releaseStatement() { + void releaseStatement() + { d_prepared = false; if (d_stmt) mysql_stmt_close(d_stmt); d_stmt = nullptr; if (d_req_bind) { - for(int i=0;i l(s_myinitlock); if (d_threadCleanup) { @@ -459,40 +492,41 @@ void SMySQL::connect() #endif #if MYSQL_VERSION_ID >= 50100 - if(d_timeout) { + if (d_timeout) { mysql_options(&d_db, MYSQL_OPT_READ_TIMEOUT, &d_timeout); mysql_options(&d_db, MYSQL_OPT_WRITE_TIMEOUT, &d_timeout); } #endif if (d_setIsolation && (retry == 1)) - mysql_options(&d_db, MYSQL_INIT_COMMAND,"SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"); + mysql_options(&d_db, MYSQL_INIT_COMMAND, "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"); mysql_options(&d_db, MYSQL_READ_DEFAULT_GROUP, d_group.c_str()); if (!mysql_real_connect(&d_db, d_host.empty() ? nullptr : d_host.c_str(), - d_user.empty() ? nullptr : d_user.c_str(), - d_password.empty() ? nullptr : d_password.c_str(), - d_database.empty() ? nullptr : d_database.c_str(), - d_port, - d_msocket.empty() ? nullptr : d_msocket.c_str(), - (d_clientSSL ? CLIENT_SSL : 0) | CLIENT_MULTI_RESULTS)) { + d_user.empty() ? nullptr : d_user.c_str(), + d_password.empty() ? nullptr : d_password.c_str(), + d_database.empty() ? nullptr : d_database.c_str(), + d_port, + d_msocket.empty() ? nullptr : d_msocket.c_str(), + (d_clientSSL ? CLIENT_SSL : 0) | CLIENT_MULTI_RESULTS)) { if (retry == 0) throw sPerrorException("Unable to connect to database"); --retry; - } else { + } + else { if (retry == 0) { mysql_close(&d_db); throw sPerrorException("Please add '(gmysql-)innodb-read-committed=no' to your PowerDNS configuration, and reconsider your storage engine if it does not support transactions."); } - retry=-1; + retry = -1; } } while (retry >= 0); } SMySQL::SMySQL(string database, string host, uint16_t port, string msocket, string user, - string password, string group, bool setIsolation, unsigned int timeout, bool threadCleanup, bool clientSSL): + string password, string group, bool setIsolation, unsigned int timeout, bool threadCleanup, bool clientSSL) : d_database(std::move(database)), d_host(std::move(host)), d_msocket(std::move(msocket)), d_user(std::move(user)), d_password(std::move(password)), d_group(std::move(group)), d_timeout(timeout), d_port(port), d_setIsolation(setIsolation), d_threadCleanup(threadCleanup), d_clientSSL(clientSSL) { connect(); @@ -500,7 +534,7 @@ SMySQL::SMySQL(string database, string host, uint16_t port, string msocket, stri void SMySQL::setLog(bool state) { - s_dolog=state; + s_dolog = state; } SMySQL::~SMySQL() @@ -508,9 +542,9 @@ SMySQL::~SMySQL() mysql_close(&d_db); } -SSqlException SMySQL::sPerrorException(const string &reason) +SSqlException SMySQL::sPerrorException(const string& reason) { - return SSqlException(reason+string(": ERROR ")+std::to_string(mysql_errno(&d_db))+" ("+string(mysql_sqlstate(&d_db))+"): "+mysql_error(&d_db)); + return SSqlException(reason + string(": ERROR ") + std::to_string(mysql_errno(&d_db)) + " (" + string(mysql_sqlstate(&d_db)) + "): " + mysql_error(&d_db)); } std::unique_ptr SMySQL::prepare(const string& query, int nparams) @@ -520,23 +554,26 @@ std::unique_ptr SMySQL::prepare(const string& query, int nparams) void SMySQL::execute(const string& query) { - if(s_dolog) - g_log< prepare(const string& query, int nparams) override; void execute(const string& query) override; @@ -46,6 +46,7 @@ public: void commit() override; void rollback() override; bool isConnectionUsable() override; + private: void connect(); diff --git a/modules/godbcbackend/godbcbackend.cc b/modules/godbcbackend/godbcbackend.cc index 6ef452702e..e61c8dafa1 100644 --- a/modules/godbcbackend/godbcbackend.cc +++ b/modules/godbcbackend/godbcbackend.cc @@ -33,18 +33,16 @@ #include "sodbc.hh" #include "godbcbackend.hh" - // Connects to the database. -gODBCBackend::gODBCBackend (const std::string & mode, const std::string & suffix) : GSQLBackend( mode, suffix ) +gODBCBackend::gODBCBackend(const std::string& mode, const std::string& suffix) : + GSQLBackend(mode, suffix) { - try - { - setDB( new SODBC( getArg( "datasource" ), getArg( "username" ), getArg( "password" ))); + try { + setDB(new SODBC(getArg("datasource"), getArg("username"), getArg("password"))); } - catch( SSqlException & e ) - { - g_log< -static bool realTestResult( SQLRETURN result, SQLSMALLINT type, SQLHANDLE handle, const std::string & message, std::string & errorMessage) +static bool realTestResult(SQLRETURN result, SQLSMALLINT type, SQLHANDLE handle, const std::string& message, std::string& errorMessage) { // cerr<<"result = "< d_req_bind; - SSqlStatement* bind(const string& name, ODBCParam& p) { + SSqlStatement* bind(const string& name, ODBCParam& p) + { prepareStatement(); d_req_bind.push_back(p); SQLRETURN result = SQLBindParameter( - d_statement, // StatementHandle, - d_paridx+1, // ParameterNumber, - SQL_PARAM_INPUT, // InputOutputType, - p.ValueType, // ValueType, - p.ParameterType, // ParameterType, - 0, // ColumnSize, - 0, // DecimalDigits, - p.ParameterValuePtr, // ParameterValuePtr, - 0, // BufferLength, - p.LenPtr // StrLen_or_IndPtr + d_statement, // StatementHandle, + d_paridx + 1, // ParameterNumber, + SQL_PARAM_INPUT, // InputOutputType, + p.ValueType, // ValueType, + p.ParameterType, // ParameterType, + 0, // ColumnSize, + 0, // DecimalDigits, + p.ParameterValuePtr, // ParameterValuePtr, + 0, // BufferLength, + p.LenPtr // StrLen_or_IndPtr ); - testResult( result, SQL_HANDLE_STMT, d_statement, "Could not bind parameter."); + testResult(result, SQL_HANDLE_STMT, d_statement, "Could not bind parameter."); d_paridx++; return this; } - SSqlStatement* bind(const string& name, bool value) { prepareStatement(); return bind(name, (uint32_t)value); } + SSqlStatement* bind(const string& name, bool value) + { + prepareStatement(); + return bind(name, (uint32_t)value); + } - SSqlStatement* bind(const string& name, long value) { prepareStatement(); return bind(name, (unsigned long)value); } + SSqlStatement* bind(const string& name, long value) + { + prepareStatement(); + return bind(name, (unsigned long)value); + } - SSqlStatement* bind(const string& name, int value) { prepareStatement(); return bind(name, (uint32_t)value); } + SSqlStatement* bind(const string& name, int value) + { + prepareStatement(); + return bind(name, (uint32_t)value); + } - SSqlStatement* bind(const string& name, long long value) { prepareStatement(); return bind(name, (unsigned long long)value); } + SSqlStatement* bind(const string& name, long long value) + { + prepareStatement(); + return bind(name, (unsigned long long)value); + } - SSqlStatement* bind(const string& name, uint32_t value) { + SSqlStatement* bind(const string& name, uint32_t value) + { prepareStatement(); ODBCParam p; - p.ParameterValuePtr = new UDWORD {value}; - p.LenPtr = new SQLLEN {sizeof(UDWORD)}; + p.ParameterValuePtr = new UDWORD{value}; + p.LenPtr = new SQLLEN{sizeof(UDWORD)}; p.ParameterType = SQL_INTEGER; p.ValueType = SQL_INTEGER; return bind(name, p); } - SSqlStatement* bind(const string& name, unsigned long value) { + SSqlStatement* bind(const string& name, unsigned long value) + { prepareStatement(); ODBCParam p; - p.ParameterValuePtr = new ULONG {value}; - p.LenPtr = new SQLLEN {sizeof(ULONG)}; + p.ParameterValuePtr = new ULONG{value}; + p.LenPtr = new SQLLEN{sizeof(ULONG)}; p.ParameterType = SQL_INTEGER; p.ValueType = SQL_INTEGER; return bind(name, p); } - SSqlStatement* bind(const string& name, unsigned long long value) { + SSqlStatement* bind(const string& name, unsigned long long value) + { prepareStatement(); ODBCParam p; - p.ParameterValuePtr = new unsigned long long {value}; - p.LenPtr = new SQLLEN {sizeof(unsigned long long)}; + p.ParameterValuePtr = new unsigned long long{value}; + p.LenPtr = new SQLLEN{sizeof(unsigned long long)}; p.ParameterType = SQL_BIGINT; p.ValueType = SQL_C_UBIGINT; return bind(name, p); } - SSqlStatement* bind(const string& name, const std::string& value) { + SSqlStatement* bind(const string& name, const std::string& value) + { // cerr<<"asked to bind string "< (d_parnum+1)) throw SSqlException("Trying to bind too many parameters."); + if (d_req_bind.size() > (d_parnum + 1)) + throw SSqlException("Trying to bind too many parameters."); prepareStatement(); ODBCParam p; - p.ParameterValuePtr = (char*) new char[value.size()+1]; + p.ParameterValuePtr = (char*)new char[value.size() + 1]; value.copy((char*)p.ParameterValuePtr, value.size()); - ((char*)p.ParameterValuePtr)[value.size()]=0; - p.LenPtr=new SQLLEN; - *(p.LenPtr)=value.size(); + ((char*)p.ParameterValuePtr)[value.size()] = 0; + p.LenPtr = new SQLLEN; + *(p.LenPtr) = value.size(); p.ParameterType = SQL_VARCHAR; p.ValueType = SQL_C_CHAR; return bind(name, p); } - SSqlStatement* bindNull(const string& name) { - if(d_req_bind.size() > (d_parnum+1)) throw SSqlException("Trying to bind too many parameters."); + SSqlStatement* bindNull(const string& name) + { + if (d_req_bind.size() > (d_parnum + 1)) + throw SSqlException("Trying to bind too many parameters."); prepareStatement(); ODBCParam p; p.ParameterValuePtr = NULL; - p.LenPtr=new SQLLEN; - *(p.LenPtr)=SQL_NULL_DATA; + p.LenPtr = new SQLLEN; + *(p.LenPtr) = SQL_NULL_DATA; p.ParameterType = SQL_VARCHAR; p.ValueType = SQL_C_CHAR; @@ -189,19 +212,19 @@ public: SQLRETURN result; // cerr<<"execute("<(d_parnum)) { releaseStatement(); @@ -293,24 +330,23 @@ private: bool d_dolog; bool d_prepared; int d_residx; - size_t d_paridx,d_parnum; + size_t d_paridx, d_parnum; SQLRETURN d_result; SQLHDBC d_conn; - SQLHSTMT d_statement; //!< Database statement handle. + SQLHSTMT d_statement; //!< Database statement handle. //! Column type. struct column_t { - SQLSMALLINT m_type; //!< Type of the column. - SQLULEN m_size; //!< Column size. - SQLPOINTER m_pData; //!< Pointer to the memory where to store the data. - bool m_canBeNull; //!< Can this column be null? + SQLSMALLINT m_type; //!< Type of the column. + SQLULEN m_size; //!< Column size. + SQLPOINTER m_pData; //!< Pointer to the memory where to store the data. + bool m_canBeNull; //!< Can this column be null? }; //! Column info. SQLSMALLINT m_columncount; - }; SSqlStatement* SODBCStatement::nextRow(row_t& row) @@ -322,19 +358,17 @@ SSqlStatement* SODBCStatement::nextRow(row_t& row) result = d_result; // cerr<<"at start of nextRow, previous SQLFetch result is "< SQL_NULL_DATA) - strres = std::string(reinterpret_cast(coldata), std::min(sizeof(coldata)-1,len)); // do not use nil byte + strres = std::string(reinterpret_cast(coldata), std::min(sizeof(coldata) - 1, len)); // do not use nil byte row.push_back(strres); } @@ -343,80 +377,77 @@ SSqlStatement* SODBCStatement::nextRow(row_t& row) // cerr<<"SQLFetch"<( SQL_OV_ODBC3 ), 0 ); - testResult( result, SQL_HANDLE_ENV, m_environment, "Could not set the ODBC version." ); + result = SQLSetEnvAttr(m_environment, SQL_ATTR_ODBC_VERSION, reinterpret_cast(SQL_OV_ODBC3), 0); + testResult(result, SQL_HANDLE_ENV, m_environment, "Could not set the ODBC version."); // Allocate connection handle. - result = SQLAllocHandle( SQL_HANDLE_DBC, m_environment, &m_connection ); - testResult( result, SQL_HANDLE_ENV, m_environment, "Could not allocate a connection handle." ); + result = SQLAllocHandle(SQL_HANDLE_DBC, m_environment, &m_connection); + testResult(result, SQL_HANDLE_ENV, m_environment, "Could not allocate a connection handle."); // Connect to the database. - char *l_dsn = strdup( dsn.c_str()); - char *l_username = strdup( username.c_str()); - char *l_password = strdup( password.c_str()); - - result = SQLConnect( m_connection, - reinterpret_cast< SQLTCHAR * >( l_dsn ), dsn.length(), - reinterpret_cast< SQLTCHAR * >( l_username ), username.length(), - reinterpret_cast< SQLTCHAR * >( l_password ), password.length()); + char* l_dsn = strdup(dsn.c_str()); + char* l_username = strdup(username.c_str()); + char* l_password = strdup(password.c_str()); - free( l_dsn ); - free( l_username ); - free( l_password ); + result = SQLConnect(m_connection, + reinterpret_cast(l_dsn), dsn.length(), + reinterpret_cast(l_username), username.length(), + reinterpret_cast(l_password), password.length()); - testResult( result, SQL_HANDLE_DBC, m_connection, "Could not connect to ODBC datasource." ); + free(l_dsn); + free(l_username); + free(l_password); + testResult(result, SQL_HANDLE_DBC, m_connection, "Could not connect to ODBC datasource."); - m_busy = false; - m_log = false; + m_busy = false; + m_log = false; } - // Destructor. -SODBC::~SODBC( void ) +SODBC::~SODBC(void) { // Disconnect from database and free all used resources. // SQLFreeHandle( SQL_HANDLE_STMT, m_statement ); - SQLDisconnect( m_connection ); + SQLDisconnect(m_connection); - SQLFreeHandle( SQL_HANDLE_DBC, m_connection ); - SQLFreeHandle( SQL_HANDLE_ENV, m_environment ); + SQLFreeHandle(SQL_HANDLE_DBC, m_connection); + SQLFreeHandle(SQL_HANDLE_ENV, m_environment); // Free all allocated column memory. // for ( int i = 0; i < m_columnInfo.size(); i++ ) @@ -427,7 +458,7 @@ SODBC::~SODBC( void ) } // Executes a command. -void SODBC::execute( const std::string & command ) +void SODBC::execute(const std::string& command) { SODBCStatement stmt(command, m_log, 0, m_connection); @@ -435,15 +466,15 @@ void SODBC::execute( const std::string & command ) } // Sets the log state. -void SODBC::setLog( bool state ) +void SODBC::setLog(bool state) { m_log = state; } // Returns an exception. -SSqlException SODBC::sPerrorException( const std::string & reason ) +SSqlException SODBC::sPerrorException(const std::string& reason) { - return SSqlException( reason ); + return SSqlException(reason); } std::unique_ptr SODBC::prepare(const string& query, int nparams) @@ -451,37 +482,41 @@ std::unique_ptr SODBC::prepare(const string& query, int nparams) return std::unique_ptr(new SODBCStatement(query, m_log, nparams, m_connection)); } - -void SODBC::startTransaction() { +void SODBC::startTransaction() +{ // cerr<<"starting transaction"< prepare(const string& query, int nparams) override; void execute(const string& query) override; @@ -70,6 +67,5 @@ public: void commit() override; //! Returns an exception. - SSqlException sPerrorException( const std::string & reason ) override; - + SSqlException sPerrorException(const std::string& reason) override; }; diff --git a/modules/gpgsqlbackend/gpgsqlbackend.cc b/modules/gpgsqlbackend/gpgsqlbackend.cc index 273cb15364..7a2ad91ab7 100644 --- a/modules/gpgsqlbackend/gpgsqlbackend.cc +++ b/modules/gpgsqlbackend/gpgsqlbackend.cc @@ -36,24 +36,25 @@ #include #include -gPgSQLBackend::gPgSQLBackend(const string &mode, const string &suffix) : GSQLBackend(mode,suffix) +gPgSQLBackend::gPgSQLBackend(const string& mode, const string& suffix) : + GSQLBackend(mode, suffix) { try { setDB(new SPgSQL(getArg("dbname"), - getArg("host"), - getArg("port"), - getArg("user"), - getArg("password"), - getArg("extra-connection-parameters"), - mustDo("prepared-statements"))); + getArg("host"), + getArg("port"), + getArg("user"), + getArg("password"), + getArg("extra-connection-parameters"), + mustDo("prepared-statements"))); } - catch(SSqlException &e) { - g_log< -class SPgSQLStatement: public SSqlStatement +class SPgSQLStatement : public SSqlStatement { public: - SPgSQLStatement(const string& query, bool dolog, int nparams, SPgSQL* db, unsigned int nstatement) { + SPgSQLStatement(const string& query, bool dolog, int nparams, SPgSQL* db, unsigned int nstatement) + { d_query = query; d_dolog = dolog; d_parent = db; @@ -50,42 +51,50 @@ public: SSqlStatement* bind(const string& name, unsigned long value) { return bind(name, std::to_string(value)); } SSqlStatement* bind(const string& name, long long value) { return bind(name, std::to_string(value)); } SSqlStatement* bind(const string& name, unsigned long long value) { return bind(name, std::to_string(value)); } - SSqlStatement* bind(const string& name, const std::string& value) { + SSqlStatement* bind(const string& name, const std::string& value) + { prepareStatement(); allocate(); - if (d_paridx>=d_nparams) { + if (d_paridx >= d_nparams) { releaseStatement(); throw SSqlException("Attempt to bind more parameters than query has: " + d_query); } - paramValues[d_paridx] = new char[value.size()+1]; - memset(paramValues[d_paridx], 0, sizeof(char)*(value.size()+1)); + paramValues[d_paridx] = new char[value.size() + 1]; + memset(paramValues[d_paridx], 0, sizeof(char) * (value.size() + 1)); value.copy(paramValues[d_paridx], value.size()); paramLengths[d_paridx] = value.size(); d_paridx++; return this; } - SSqlStatement* bindNull(const string& name) { prepareStatement(); d_paridx++; return this; } // these are set null in allocate() - SSqlStatement* execute() { + SSqlStatement* bindNull(const string& name) + { + prepareStatement(); + d_paridx++; + return this; + } // these are set null in allocate() + SSqlStatement* execute() + { prepareStatement(); if (d_dolog) { - g_log<= PQntuples(d_res_set)) { PQclear(d_res_set); d_res_set = nullptr; @@ -117,8 +128,8 @@ public: if (PQftype(d_res_set, 0) == 1790) { // REFCURSOR #if PG_VERSION_NUM > 90000 // PQescapeIdentifier was added to libpq in postgresql 9.0 - char *val = PQgetvalue(d_res_set, d_cur_set++, 0); - char *portal = PQescapeIdentifier(d_db(), val, strlen(val)); + char* val = PQgetvalue(d_res_set, d_cur_set++, 0); + char* portal = PQescapeIdentifier(d_db(), val, strlen(val)); string cmd = string("FETCH ALL FROM \"") + string(portal) + string("\""); PQfreemem(portal); #else @@ -127,12 +138,13 @@ public: #endif // execute FETCH if (d_dolog) { - g_log<=d_resnum || !d_res) return this; + if (d_residx >= d_resnum || !d_res) + return this; row.reserve(PQnfields(d_res)); - for(i=0;idb(); } - void releaseStatement() { + void releaseStatement() + { d_prepared = false; reset(); if (!d_stmt.empty()) { string cmd = string("DEALLOCATE " + d_stmt); - PGresult *res = PQexec(d_db(), cmd.c_str()); + PGresult* res = PQexec(d_db(), cmd.c_str()); PQclear(res); d_stmt.clear(); } } - void prepareStatement() { - if (d_prepared) return; + void prepareStatement() + { + if (d_prepared) + return; if (d_parent->usePrepared()) { // prepare a statement; name must be unique per session (using d_nstatement to ensure this). this->d_stmt = string("stmt") + std::to_string(d_nstatement); @@ -249,26 +277,28 @@ private: d_prepared = true; } - void allocate() { - if (paramValues != nullptr) return; - paramValues = new char*[d_nparams]; - paramLengths = new int[d_nparams]; - memset(paramValues, 0, sizeof(char*)*d_nparams); - memset(paramLengths, 0, sizeof(int)*d_nparams); + void allocate() + { + if (paramValues != nullptr) + return; + paramValues = new char*[d_nparams]; + paramLengths = new int[d_nparams]; + memset(paramValues, 0, sizeof(char*) * d_nparams); + memset(paramLengths, 0, sizeof(int) * d_nparams); } string d_query; string d_stmt; - SPgSQL *d_parent; - PGresult *d_res_set{nullptr}; - PGresult *d_res{nullptr}; + SPgSQL* d_parent; + PGresult* d_res_set{nullptr}; + PGresult* d_res{nullptr}; bool d_dolog; DTime d_dtime; // only used if d_dolog is set bool d_prepared{false}; int d_nparams; int d_paridx{0}; - char **paramValues{nullptr}; - int *paramLengths{nullptr}; + char** paramValues{nullptr}; + int* paramLengths{nullptr}; int d_residx{0}; int d_resnum{0}; int d_cur_set{0}; @@ -277,17 +307,17 @@ private: bool SPgSQL::s_dolog; -static string escapeForPQparam(const string &v) +static string escapeForPQparam(const string& v) { string ret = v; boost::replace_all(ret, "\\", "\\\\"); boost::replace_all(ret, "'", "\\'"); - return string("'")+ret+string("'"); + return string("'") + ret + string("'"); } -SPgSQL::SPgSQL(const string &database, const string &host, const string& port, const string &user, - const string &password, const string &extra_connection_parameters, const bool use_prepared) +SPgSQL::SPgSQL(const string& database, const string& host, const string& port, const string& user, + const string& password, const string& extra_connection_parameters, const bool use_prepared) { d_db = nullptr; d_in_trx = false; @@ -295,37 +325,37 @@ SPgSQL::SPgSQL(const string &database, const string &host, const string& port, c d_nstatements = 0; if (!database.empty()) - d_connectstr+="dbname="+escapeForPQparam(database); + d_connectstr += "dbname=" + escapeForPQparam(database); if (!user.empty()) - d_connectstr+=" user="+escapeForPQparam(user); + d_connectstr += " user=" + escapeForPQparam(user); - if(!host.empty()) - d_connectstr+=" host="+escapeForPQparam(host); + if (!host.empty()) + d_connectstr += " host=" + escapeForPQparam(host); - if(!port.empty()) - d_connectstr+=" port="+escapeForPQparam(port); + if (!port.empty()) + d_connectstr += " port=" + escapeForPQparam(port); - if(!extra_connection_parameters.empty()) - d_connectstr+=" " + extra_connection_parameters; + if (!extra_connection_parameters.empty()) + d_connectstr += " " + extra_connection_parameters; - d_connectlogstr=d_connectstr; + d_connectlogstr = d_connectstr; - if(!password.empty()) { - d_connectlogstr+=" password="; - d_connectstr+=" password="+escapeForPQparam(password); + if (!password.empty()) { + d_connectlogstr += " password="; + d_connectstr += " password=" + escapeForPQparam(password); } d_use_prepared = use_prepared; - d_db=PQconnectdb(d_connectstr.c_str()); + d_db = PQconnectdb(d_connectstr.c_str()); - if (!d_db || PQstatus(d_db)==CONNECTION_BAD) { + if (!d_db || PQstatus(d_db) == CONNECTION_BAD) { try { - throw sPerrorException("Unable to connect to database, connect string: "+d_connectlogstr); + throw sPerrorException("Unable to connect to database, connect string: " + d_connectlogstr); } - catch(...) { - if(d_db) + catch (...) { + if (d_db) PQfinish(d_db); d_db = 0; throw; @@ -335,7 +365,7 @@ SPgSQL::SPgSQL(const string &database, const string &host, const string& port, c void SPgSQL::setLog(bool state) { - s_dolog=state; + s_dolog = state; } SPgSQL::~SPgSQL() @@ -343,9 +373,9 @@ SPgSQL::~SPgSQL() PQfinish(d_db); } -SSqlException SPgSQL::sPerrorException(const string &reason) +SSqlException SPgSQL::sPerrorException(const string& reason) { - return SSqlException(reason+string(": ")+(d_db ? PQerrorMessage(d_db) : "no connection")); + return SSqlException(reason + string(": ") + (d_db ? PQerrorMessage(d_db) : "no connection")); } void SPgSQL::execute(const string& query) @@ -365,17 +395,20 @@ std::unique_ptr SPgSQL::prepare(const string& query, int nparams) return std::unique_ptr(new SPgSQLStatement(query, s_dolog, nparams, this, d_nstatements)); } -void SPgSQL::startTransaction() { +void SPgSQL::startTransaction() +{ execute("begin"); d_in_trx = true; } -void SPgSQL::commit() { +void SPgSQL::commit() +{ execute("commit"); d_in_trx = false; } -void SPgSQL::rollback() { +void SPgSQL::rollback() +{ execute("rollback"); d_in_trx = false; } diff --git a/modules/gpgsqlbackend/spgsql.hh b/modules/gpgsqlbackend/spgsql.hh index aea85c4221..7e6dd5b696 100644 --- a/modules/gpgsqlbackend/spgsql.hh +++ b/modules/gpgsqlbackend/spgsql.hh @@ -27,13 +27,13 @@ class SPgSQL : public SSql { public: - SPgSQL(const string &database, const string &host="", const string& port="", - const string &user="", const string &password="", - const string &extra_connection_parameters="", const bool use_prepared = true); + SPgSQL(const string& database, const string& host = "", const string& port = "", + const string& user = "", const string& password = "", + const string& extra_connection_parameters = "", const bool use_prepared = true); ~SPgSQL(); - - SSqlException sPerrorException(const string &reason) override; + + SSqlException sPerrorException(const string& reason) override; void setLog(bool state) override; unique_ptr prepare(const string& query, int nparams) override; void execute(const string& query) override; diff --git a/modules/gsqlite3backend/gsqlite3backend.cc b/modules/gsqlite3backend/gsqlite3backend.cc index 7a66238c7f..b9670f4ab6 100644 --- a/modules/gsqlite3backend/gsqlite3backend.cc +++ b/modules/gsqlite3backend/gsqlite3backend.cc @@ -39,68 +39,67 @@ #include // Connects to the database. -gSQLite3Backend::gSQLite3Backend( const std::string & mode, const std::string & suffix ) : GSQLBackend( mode, suffix ) +gSQLite3Backend::gSQLite3Backend(const std::string& mode, const std::string& suffix) : + GSQLBackend(mode, suffix) { - try - { - SSQLite3 *ptr = new SSQLite3( getArg( "database" ), getArg( "pragma-journal-mode") ); + try { + SSQLite3* ptr = new SSQLite3(getArg("database"), getArg("pragma-journal-mode")); setDB(ptr); allocateStatements(); - if(!getArg("pragma-synchronous").empty()) { - ptr->execute("PRAGMA synchronous="+getArg("pragma-synchronous")); + if (!getArg("pragma-synchronous").empty()) { + ptr->execute("PRAGMA synchronous=" + getArg("pragma-synchronous")); } if (mustDo("pragma-foreign-keys")) { ptr->execute("PRAGMA foreign_keys = 1"); } - } - catch( SSqlException & e ) - { + } + catch (SSqlException& e) { g_log << Logger::Error << mode << ": connection failed: " << e.txtReason() << std::endl; - throw PDNSException( "Unable to launch " + mode + " connection: " + e.txtReason()); + throw PDNSException("Unable to launch " + mode + " connection: " + e.txtReason()); } - g_log << Logger::Info << mode << ": connection to '"< hosts; - - try - { + try { d_qname.clear(); d_pldap = NULL; d_authenticator = NULL; - d_qlog = arg().mustDo( "query-logging" ); - d_default_ttl = arg().asNum( "default-ttl" ); + d_qlog = arg().mustDo("query-logging"); + d_default_ttl = arg().asNum("default-ttl"); d_myname = "[LdapBackend]"; d_in_list = false; - setArgPrefix( "ldap" + suffix ); + setArgPrefix("ldap" + suffix); d_getdn = false; - d_reconnect_attempts = getArgAsNum( "reconnect-attempts" ); + d_reconnect_attempts = getArgAsNum("reconnect-attempts"); d_list_fcnt = &LdapBackend::list_simple; d_lookup_fcnt = &LdapBackend::lookup_simple; - if( getArg( "method" ) == "tree" ) - { + if (getArg("method") == "tree") { d_lookup_fcnt = &LdapBackend::lookup_tree; } - if( getArg( "method" ) == "strict" || mustDo( "disable-ptrrecord" ) ) - { + if (getArg("method") == "strict" || mustDo("disable-ptrrecord")) { d_list_fcnt = &LdapBackend::list_strict; d_lookup_fcnt = &LdapBackend::lookup_strict; } - stringtok( hosts, getArg( "host" ), ", " ); + stringtok(hosts, getArg("host"), ", "); idx = ldap_host_index++ % hosts.size(); hoststr = hosts[idx]; - for( i = 1; i < hosts.size(); i++ ) - { - hoststr += " " + hosts[ ( idx + i ) % hosts.size() ]; + for (i = 1; i < hosts.size(); i++) { + hoststr += " " + hosts[(idx + i) % hosts.size()]; } g_log << Logger::Info << d_myname << " LDAP servers = " << hoststr << endl; - d_pldap = new PowerLDAP( hoststr.c_str(), LDAP_PORT, mustDo( "starttls" ), getArgAsNum( "timeout" ) ); - d_pldap->setOption( LDAP_OPT_DEREF, LDAP_DEREF_ALWAYS ); + d_pldap = new PowerLDAP(hoststr.c_str(), LDAP_PORT, mustDo("starttls"), getArgAsNum("timeout")); + d_pldap->setOption(LDAP_OPT_DEREF, LDAP_DEREF_ALWAYS); - string bindmethod = getArg( "bindmethod" ); - if ( bindmethod == "gssapi" ) { - setenv( "KRB5CCNAME", getArg( "krb5-ccache" ).c_str(), 1 ); - d_authenticator = new LdapGssapiAuthenticator( getArg( "krb5-keytab" ), getArg( "krb5-ccache" ), getArgAsNum( "timeout" ) ); + string bindmethod = getArg("bindmethod"); + if (bindmethod == "gssapi") { + setenv("KRB5CCNAME", getArg("krb5-ccache").c_str(), 1); + d_authenticator = new LdapGssapiAuthenticator(getArg("krb5-keytab"), getArg("krb5-ccache"), getArgAsNum("timeout")); } else { - d_authenticator = new LdapSimpleAuthenticator( getArg( "binddn" ), getArg( "secret" ), getArgAsNum( "timeout" ) ); + d_authenticator = new LdapSimpleAuthenticator(getArg("binddn"), getArg("secret"), getArgAsNum("timeout")); } - d_pldap->bind( d_authenticator ); + d_pldap->bind(d_authenticator); g_log << Logger::Notice << d_myname << " Ldap connection succeeded" << endl; return; } - catch( LDAPTimeout < ) - { + catch (LDAPTimeout& lt) { g_log << Logger::Error << d_myname << " Ldap connection to server failed because of timeout" << endl; } - catch( LDAPException &le ) - { + catch (LDAPException& le) { g_log << Logger::Error << d_myname << " Ldap connection to server failed: " << le.what() << endl; } - catch( std::exception &e ) - { + catch (std::exception& e) { g_log << Logger::Error << d_myname << " Caught STL exception: " << e.what() << endl; } - if( d_pldap != NULL ) { delete( d_pldap ); } - throw PDNSException( "Unable to connect to ldap server" ); + if (d_pldap != NULL) { + delete (d_pldap); + } + throw PDNSException("Unable to connect to ldap server"); } - - LdapBackend::~LdapBackend() { d_search.reset(); // This is necessary otherwise d_pldap will get deleted first and - // we may hang in SearchResult::~SearchResult() waiting for the - // current operation to be abandoned - delete( d_pldap ); - delete( d_authenticator ); + // we may hang in SearchResult::~SearchResult() waiting for the + // current operation to be abandoned + delete (d_pldap); + delete (d_authenticator); g_log << Logger::Notice << d_myname << " Ldap connection closed" << endl; } - - bool LdapBackend::reconnect() { int attempts = d_reconnect_attempts; bool connected = false; - while ( !connected && attempts > 0 ) { + while (!connected && attempts > 0) { g_log << Logger::Debug << d_myname << " Reconnection attempts left: " << attempts << endl; connected = d_pldap->connect(); - if ( !connected ) - Utility::usleep( 250 ); + if (!connected) + Utility::usleep(250); --attempts; } - if ( connected ) - d_pldap->bind( d_authenticator ); + if (connected) + d_pldap->bind(d_authenticator); return connected; } +void LdapBackend::extract_common_attributes(DNSResult& result) +{ + if (d_result.count("dNSTTL") && !d_result["dNSTTL"].empty()) { + char* endptr; + uint32_t ttl = (uint32_t)strtol(d_result["dNSTTL"][0].c_str(), &endptr, 10); -void LdapBackend::extract_common_attributes( DNSResult &result ) { - if ( d_result.count( "dNSTTL" ) && !d_result["dNSTTL"].empty() ) { - char *endptr; - uint32_t ttl = (uint32_t) strtol( d_result["dNSTTL"][0].c_str(), &endptr, 10 ); - - if ( *endptr != '\0' ) { + if (*endptr != '\0') { // NOTE: this will not give the entry for which the TTL was off. // TODO: improve this. // - Check how d_getdn is used, because if it's never false then we @@ -159,12 +149,12 @@ void LdapBackend::extract_common_attributes( DNSResult &result ) { } // We have to erase the attribute, otherwise this will mess up the records retrieval later. - d_result.erase( "dNSTTL" ); + d_result.erase("dNSTTL"); } - if ( d_result.count( "modifyTimestamp" ) && !d_result["modifyTimestamp"].empty() ) { + if (d_result.count("modifyTimestamp") && !d_result["modifyTimestamp"].empty()) { time_t tstamp = 0; - if ( ( tstamp = str2tstamp( d_result["modifyTimestamp"][0] ) ) == 0 ) { + if ((tstamp = str2tstamp(d_result["modifyTimestamp"][0])) == 0) { // Same note as above, we don't know which entry failed here g_log << Logger::Warning << d_myname << " Invalid modifyTimestamp for " << d_qname << ": " << d_result["modifyTimestamp"][0] << endl; } @@ -173,27 +163,27 @@ void LdapBackend::extract_common_attributes( DNSResult &result ) { } // Here too we have to erase this attribute. - d_result.erase( "modifyTimestamp" ); + d_result.erase("modifyTimestamp"); } } - -void LdapBackend::extract_entry_results( const DNSName& domain, const DNSResult& result_template, QType qtype ) { - std:: string attrname, qstr; +void LdapBackend::extract_entry_results(const DNSName& domain, const DNSResult& result_template, QType qtype) +{ + std::string attrname, qstr; QType qt; bool has_records = false; - for ( const auto& attribute : d_result ) { + for (const auto& attribute : d_result) { // Find if we're dealing with a record attribute - if ( attribute.first.length() > 6 && attribute.first.compare( attribute.first.length() - 6, 6, "Record" ) == 0 ) { + if (attribute.first.length() > 6 && attribute.first.compare(attribute.first.length() - 6, 6, "Record") == 0) { has_records = true; attrname = attribute.first; // extract qtype string from ldap attribute name by removing the 'Record' suffix. - qstr = attrname.substr( 0, attrname.length() - 6 ); - qt = toUpper( qstr ); + qstr = attrname.substr(0, attrname.length() - 6); + qt = toUpper(qstr); - for ( const auto& value : attribute.second ) { - if(qtype != qt && qtype != QType::ANY) { + for (const auto& value : attribute.second) { + if (qtype != qt && qtype != QType::ANY) { continue; } @@ -206,123 +196,115 @@ void LdapBackend::extract_entry_results( const DNSName& domain, const DNSResult& // Now let's see if we have some PDNS record data // TTL - if ( d_result.count( "PdnsRecordTTL" ) && !d_result["PdnsRecordTTL"].empty() ) { - for ( const auto& rdata : d_result["PdnsRecordTTL"] ) { + if (d_result.count("PdnsRecordTTL") && !d_result["PdnsRecordTTL"].empty()) { + for (const auto& rdata : d_result["PdnsRecordTTL"]) { std::string qtype2; - std::size_t pos = rdata.find_first_of( '|', 0 ); - if ( pos == std::string::npos ) + std::size_t pos = rdata.find_first_of('|', 0); + if (pos == std::string::npos) continue; - qtype2 = rdata.substr( 0, pos ); - if ( qtype2 != QType( local_result.qtype ).getName() ) + qtype2 = rdata.substr(0, pos); + if (qtype2 != QType(local_result.qtype).getName()) continue; - local_result.ttl = pdns_stou( rdata.substr( pos + 1 ) ); + local_result.ttl = pdns_stou(rdata.substr(pos + 1)); } } // Not authoritative - if ( d_result.count( "PdnsRecordNoAuth" ) && !d_result["PdnsRecordNoAuth"].empty() ) { - for ( const auto& rdata : d_result["PdnsRecordNoAuth"] ) { - if ( rdata == QType( local_result.qtype ).getName() ) + if (d_result.count("PdnsRecordNoAuth") && !d_result["PdnsRecordNoAuth"].empty()) { + for (const auto& rdata : d_result["PdnsRecordNoAuth"]) { + if (rdata == QType(local_result.qtype).getName()) local_result.auth = false; } } // Ordername - if ( d_result.count( "PdnsRecordOrdername" ) && !d_result["PdnsRecordOrdername"].empty() ) { + if (d_result.count("PdnsRecordOrdername") && !d_result["PdnsRecordOrdername"].empty()) { std::string defaultOrdername; - for ( const auto& rdata : d_result["PdnsRecordOrdername"] ) { + for (const auto& rdata : d_result["PdnsRecordOrdername"]) { std::string qtype2; - std::size_t pos = rdata.find_first_of( '|', 0 ); - if ( pos == std::string::npos ) { + std::size_t pos = rdata.find_first_of('|', 0); + if (pos == std::string::npos) { // This is the default ordername for all records in this entry defaultOrdername = rdata; continue; } - qtype2 = rdata.substr( 0, pos ); - if ( qtype2 != QType( local_result.qtype ).getName() ) + qtype2 = rdata.substr(0, pos); + if (qtype2 != QType(local_result.qtype).getName()) continue; - local_result.ordername = rdata.substr( pos + 1 ); + local_result.ordername = rdata.substr(pos + 1); } - if ( local_result.ordername.empty() && !defaultOrdername.empty() ) + if (local_result.ordername.empty() && !defaultOrdername.empty()) local_result.ordername = defaultOrdername; } - d_results_cache.push_back( local_result ); + d_results_cache.push_back(local_result); } } } - if ( !has_records ) { + if (!has_records) { // This is an ENT DNSResult local_result = result_template; local_result.qname = domain; - if ( !d_result.count( "PdnsRecordOrdername" ) || d_result["PdnsRecordOrdername"].empty() ) { + if (!d_result.count("PdnsRecordOrdername") || d_result["PdnsRecordOrdername"].empty()) { // An ENT with an order name is authoritative local_result.auth = false; } - d_results_cache.push_back( local_result ); + d_results_cache.push_back(local_result); } } - class LdapFactory : public BackendFactory { - public: - - LdapFactory() : BackendFactory( "ldap" ) {} - - void declareArguments( const string &suffix="" ) override - { - declare( suffix, "host", "One or more LDAP server with ports or LDAP URIs (separated by spaces)","ldap://127.0.0.1:389/" ); - declare( suffix, "starttls", "Use TLS to encrypt connection (unused for LDAP URIs)", "no" ); - declare( suffix, "basedn", "Search root in ldap tree (must be set)","" ); - declare( suffix, "basedn-axfr-override", "Override base dn for AXFR subtree search", "no" ); - declare( suffix, "bindmethod", "Bind method to use (simple or gssapi)", "simple" ); - declare( suffix, "binddn", "User dn for non anonymous binds","" ); - declare( suffix, "secret", "User password for non anonymous binds", "" ); - declare( suffix, "krb5-keytab", "The keytab to use for GSSAPI authentication", "" ); - declare( suffix, "krb5-ccache", "The credentials cache used for GSSAPI authentication", "" ); - declare( suffix, "timeout", "Seconds before connecting to server fails", "5" ); - declare( suffix, "method", "How to search entries (simple, strict or tree)", "simple" ); - declare( suffix, "filter-axfr", "LDAP filter for limiting AXFR results", "(:target:)" ); - declare( suffix, "filter-lookup", "LDAP filter for limiting IP or name lookups", "(:target:)" ); - declare( suffix, "disable-ptrrecord", "Deprecated, use ldap-method=strict instead", "no" ); - declare( suffix, "reconnect-attempts", "Number of attempts to re-establish a lost LDAP connection", "5" ); - } +public: + LdapFactory() : + BackendFactory("ldap") {} + void declareArguments(const string& suffix = "") override + { + declare(suffix, "host", "One or more LDAP server with ports or LDAP URIs (separated by spaces)", "ldap://127.0.0.1:389/"); + declare(suffix, "starttls", "Use TLS to encrypt connection (unused for LDAP URIs)", "no"); + declare(suffix, "basedn", "Search root in ldap tree (must be set)", ""); + declare(suffix, "basedn-axfr-override", "Override base dn for AXFR subtree search", "no"); + declare(suffix, "bindmethod", "Bind method to use (simple or gssapi)", "simple"); + declare(suffix, "binddn", "User dn for non anonymous binds", ""); + declare(suffix, "secret", "User password for non anonymous binds", ""); + declare(suffix, "krb5-keytab", "The keytab to use for GSSAPI authentication", ""); + declare(suffix, "krb5-ccache", "The credentials cache used for GSSAPI authentication", ""); + declare(suffix, "timeout", "Seconds before connecting to server fails", "5"); + declare(suffix, "method", "How to search entries (simple, strict or tree)", "simple"); + declare(suffix, "filter-axfr", "LDAP filter for limiting AXFR results", "(:target:)"); + declare(suffix, "filter-lookup", "LDAP filter for limiting IP or name lookups", "(:target:)"); + declare(suffix, "disable-ptrrecord", "Deprecated, use ldap-method=strict instead", "no"); + declare(suffix, "reconnect-attempts", "Number of attempts to re-establish a lost LDAP connection", "5"); + } - DNSBackend* make( const string &suffix="" ) override - { - return new LdapBackend( suffix ); - } + DNSBackend* make(const string& suffix = "") override + { + return new LdapBackend(suffix); + } }; - - - - class LdapLoader { - LdapFactory factory; - - public: + LdapFactory factory; - LdapLoader() - { - BackendMakers().report( &factory ); - g_log << Logger::Info << "[ldapbackend] This is the ldap backend version " VERSION +public: + LdapLoader() + { + BackendMakers().report(&factory); + g_log << Logger::Info << "[ldapbackend] This is the ldap backend version " VERSION #ifndef REPRODUCIBLE - << " (" __DATE__ " " __TIME__ ")" + << " (" __DATE__ " " __TIME__ ")" #endif - << " reporting" << endl; - } + << " reporting" << endl; + } }; - static LdapLoader ldaploader; diff --git a/modules/ldapbackend/ldapbackend.hh b/modules/ldapbackend/ldapbackend.hh index 61b2f46148..747c6c7e8e 100644 --- a/modules/ldapbackend/ldapbackend.hh +++ b/modules/ldapbackend/ldapbackend.hh @@ -41,7 +41,6 @@ #include "powerldap.hh" #include "utils.hh" - using std::string; using std::vector; @@ -52,7 +51,7 @@ class LdapAuthenticator; * Types which aren't active are currently not supported by PDNS */ -__attribute__ ((unused)) static const char* ldap_attrany[] = { +__attribute__((unused)) static const char* ldap_attrany[] = { "associatedDomain", "dNSTTL", "ALIASRecord", @@ -66,18 +65,18 @@ __attribute__ ((unused)) static const char* ldap_attrany[] = { "tXTRecord", "rPRecord", "aFSDBRecord", -// "SigRecord", + // "SigRecord", "KeyRecord", -// "gPosRecord", + // "gPosRecord", "aAAARecord", "lOCRecord", "sRVRecord", "nAPTRRecord", "kXRecord", "certRecord", -// "a6Record", + // "a6Record", "dNameRecord", -// "aPLRecord", + // "aPLRecord", "dSRecord", "sSHFPRecord", "iPSecKeyRecord", @@ -105,83 +104,79 @@ __attribute__ ((unused)) static const char* ldap_attrany[] = { "PdnsRecordTTL", "PdnsRecordAuth", "PdnsRecordOrdername", - NULL -}; - - + NULL}; class LdapBackend : public DNSBackend { - string d_myname; - - bool d_qlog; - uint32_t d_default_ttl; - int d_reconnect_attempts; - - bool d_getdn; - PowerLDAP::SearchResult::Ptr d_search; - PowerLDAP::sentry_t d_result; - bool d_in_list; - - struct DNSResult { - QType qtype; - DNSName qname; - uint32_t ttl; - time_t lastmod; - std::string value; - bool auth; - std::string ordername; - - DNSResult() - : ttl( 0 ), lastmod( 0 ), value( "" ), auth( true ), ordername( "" ) - { - } - }; - std::list d_results_cache; - - DNSName d_qname; - QType d_qtype; - - PowerLDAP* d_pldap; - LdapAuthenticator *d_authenticator; - - bool (LdapBackend::*d_list_fcnt)( const DNSName&, int ); - void (LdapBackend::*d_lookup_fcnt)( const QType&, const DNSName&, DNSPacket*, int ); - - bool list_simple( const DNSName& target, int domain_id ); - bool list_strict( const DNSName& target, int domain_id ); - - void lookup_simple( const QType& qtype, const DNSName& qdomain, DNSPacket* p, int zoneid ); - void lookup_strict( const QType& qtype, const DNSName& qdomain, DNSPacket* p, int zoneid ); - void lookup_tree( const QType& qtype, const DNSName& qdomain, DNSPacket* p, int zoneid ); - - bool reconnect(); - - // Extracts common attributes from the current result stored in d_result and sets them in the given DNSResult. - // This will modify d_result by removing attributes that may interfere with the records extraction later. - void extract_common_attributes( DNSResult &result ); - - // Extract LDAP attributes for the current result stored in d_result and create a new DNSResult that will - // be appended in the results cache. The result parameter is used as a template that will be copied for - // each result extracted from the entry. - // The given domain will be added as the qname attribute of the result. - // The qtype parameter is used to filter extracted results. - void extract_entry_results( const DNSName& domain, const DNSResult& result, QType qtype ); - - public: - - LdapBackend( const string &suffix="" ); - ~LdapBackend(); - - // Native backend - bool list( const DNSName& target, int domain_id, bool include_disabled=false ) override; - void lookup( const QType& qtype, const DNSName& qdomain, int zoneid, DNSPacket* p = nullptr ) override; - bool get( DNSResourceRecord& rr ) override; - - bool getDomainInfo( const DNSName& domain, DomainInfo& di, bool getSerial=true ) override; - - // Master backend - void getUpdatedMasters( vector* domains ) override; - void setNotified( uint32_t id, uint32_t serial ) override; + string d_myname; + + bool d_qlog; + uint32_t d_default_ttl; + int d_reconnect_attempts; + + bool d_getdn; + PowerLDAP::SearchResult::Ptr d_search; + PowerLDAP::sentry_t d_result; + bool d_in_list; + + struct DNSResult + { + QType qtype; + DNSName qname; + uint32_t ttl; + time_t lastmod; + std::string value; + bool auth; + std::string ordername; + + DNSResult() : + ttl(0), lastmod(0), value(""), auth(true), ordername("") + { + } + }; + std::list d_results_cache; + + DNSName d_qname; + QType d_qtype; + + PowerLDAP* d_pldap; + LdapAuthenticator* d_authenticator; + + bool (LdapBackend::*d_list_fcnt)(const DNSName&, int); + void (LdapBackend::*d_lookup_fcnt)(const QType&, const DNSName&, DNSPacket*, int); + + bool list_simple(const DNSName& target, int domain_id); + bool list_strict(const DNSName& target, int domain_id); + + void lookup_simple(const QType& qtype, const DNSName& qdomain, DNSPacket* p, int zoneid); + void lookup_strict(const QType& qtype, const DNSName& qdomain, DNSPacket* p, int zoneid); + void lookup_tree(const QType& qtype, const DNSName& qdomain, DNSPacket* p, int zoneid); + + bool reconnect(); + + // Extracts common attributes from the current result stored in d_result and sets them in the given DNSResult. + // This will modify d_result by removing attributes that may interfere with the records extraction later. + void extract_common_attributes(DNSResult& result); + + // Extract LDAP attributes for the current result stored in d_result and create a new DNSResult that will + // be appended in the results cache. The result parameter is used as a template that will be copied for + // each result extracted from the entry. + // The given domain will be added as the qname attribute of the result. + // The qtype parameter is used to filter extracted results. + void extract_entry_results(const DNSName& domain, const DNSResult& result, QType qtype); + +public: + LdapBackend(const string& suffix = ""); + ~LdapBackend(); + + // Native backend + bool list(const DNSName& target, int domain_id, bool include_disabled = false) override; + void lookup(const QType& qtype, const DNSName& qdomain, int zoneid, DNSPacket* p = nullptr) override; + bool get(DNSResourceRecord& rr) override; + + bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial = true) override; + + // Master backend + void getUpdatedMasters(vector* domains) override; + void setNotified(uint32_t id, uint32_t serial) override; }; - diff --git a/modules/ldapbackend/ldaputils.cc b/modules/ldapbackend/ldaputils.cc index 13c929da3f..b3ee9f111d 100644 --- a/modules/ldapbackend/ldaputils.cc +++ b/modules/ldapbackend/ldaputils.cc @@ -1,46 +1,42 @@ #include "ldaputils.hh" #include -void ldapSetOption( LDAP *conn, int option, void *value ) +void ldapSetOption(LDAP* conn, int option, void* value) { - if( ldap_set_option( conn, option, value ) != LDAP_OPT_SUCCESS ) - { - throw LDAPException( "Unable to set option" ); + if (ldap_set_option(conn, option, value) != LDAP_OPT_SUCCESS) { + throw LDAPException("Unable to set option"); } } -void ldapGetOption( LDAP *conn, int option, void *value ) +void ldapGetOption(LDAP* conn, int option, void* value) { - if( ldap_get_option( conn, option, value ) != LDAP_OPT_SUCCESS ) - { - throw LDAPException( "Unable to get option" ); + if (ldap_get_option(conn, option, value) != LDAP_OPT_SUCCESS) { + throw LDAPException("Unable to get option"); } } -std::string ldapGetError( LDAP *conn, int code ) +std::string ldapGetError(LDAP* conn, int code) { - if ( code == -1 ) - ldapGetOption( conn, LDAP_OPT_ERROR_NUMBER, &code ); - return std::string( ldap_err2string( code ) ); + if (code == -1) + ldapGetOption(conn, LDAP_OPT_ERROR_NUMBER, &code); + return std::string(ldap_err2string(code)); } -int ldapWaitResult( LDAP *conn, int msgid, int timeout, LDAPMessage** result ) +int ldapWaitResult(LDAP* conn, int msgid, int timeout, LDAPMessage** result) { struct timeval tv; LDAPMessage* res; - tv.tv_sec = timeout; tv.tv_usec = 0; - int rc = ldap_result( conn, msgid, LDAP_MSG_ONE, &tv, &res ); + int rc = ldap_result(conn, msgid, LDAP_MSG_ONE, &tv, &res); - if ( rc == -1 || rc == 0 ) + if (rc == -1 || rc == 0) return rc; - if( result == NULL ) - { - ldap_msgfree( res ); + if (result == NULL) { + ldap_msgfree(res); return rc; } diff --git a/modules/ldapbackend/ldaputils.hh b/modules/ldapbackend/ldaputils.hh index 5b1bc7a218..3ed3a57539 100644 --- a/modules/ldapbackend/ldaputils.hh +++ b/modules/ldapbackend/ldaputils.hh @@ -24,11 +24,10 @@ #include #include -void ldapSetOption( LDAP *conn, int option, void *value ); +void ldapSetOption(LDAP* conn, int option, void* value); -void ldapGetOption( LDAP *conn, int option, void *value ); +void ldapGetOption(LDAP* conn, int option, void* value); -std::string ldapGetError( LDAP *conn, int code ); - -int ldapWaitResult( LDAP *conn, int msgid, int timeout, LDAPMessage** result = NULL ); +std::string ldapGetError(LDAP* conn, int code); +int ldapWaitResult(LDAP* conn, int msgid, int timeout, LDAPMessage** result = NULL); diff --git a/modules/ldapbackend/master.cc b/modules/ldapbackend/master.cc index c83b573984..9a4847803c 100644 --- a/modules/ldapbackend/master.cc +++ b/modules/ldapbackend/master.cc @@ -24,137 +24,119 @@ #include "ldapbackend.hh" #include - -void LdapBackend::getUpdatedMasters( vector* domains ) +void LdapBackend::getUpdatedMasters(vector* domains) { string filter; PowerLDAP::SearchResult::Ptr search; PowerLDAP::sentry_t result; const char* attronly[] = { "associatedDomain", - NULL - }; + NULL}; - try - { + try { // First get all domains on which we are master. - filter = strbind( ":target:", "&(SOARecord=*)(PdnsDomainId=*)", getArg( "filter-axfr" ) ); - search = d_pldap->search( getArg( "basedn" ), LDAP_SCOPE_SUBTREE, filter, attronly ); + filter = strbind(":target:", "&(SOARecord=*)(PdnsDomainId=*)", getArg("filter-axfr")); + search = d_pldap->search(getArg("basedn"), LDAP_SCOPE_SUBTREE, filter, attronly); } - catch( LDAPTimeout < ) - { + catch (LDAPTimeout& lt) { g_log << Logger::Warning << d_myname << " Unable to search LDAP directory: " << lt.what() << endl; - throw DBException( "LDAP server timeout" ); + throw DBException("LDAP server timeout"); } - catch( LDAPNoConnection &lnc ) - { + catch (LDAPNoConnection& lnc) { g_log << Logger::Warning << d_myname << " Connection to LDAP lost, trying to reconnect" << endl; - if ( reconnect() ) - this->getUpdatedMasters( domains ); + if (reconnect()) + this->getUpdatedMasters(domains); else - throw PDNSException( "Failed to reconnect to LDAP server" ); + throw PDNSException("Failed to reconnect to LDAP server"); } - catch( LDAPException &le ) - { + catch (LDAPException& le) { g_log << Logger::Error << d_myname << " Unable to search LDAP directory: " << le.what() << endl; - throw PDNSException( "LDAP server unreachable" ); // try to reconnect to another server + throw PDNSException("LDAP server unreachable"); // try to reconnect to another server } - catch( std::exception &e ) - { - throw DBException( "STL exception" ); + catch (std::exception& e) { + throw DBException("STL exception"); } - while( search->getNext( result ) ) { - if( !result.count( "associatedDomain" ) || result["associatedDomain"].empty() ) + while (search->getNext(result)) { + if (!result.count("associatedDomain") || result["associatedDomain"].empty()) continue; DomainInfo di; - if ( !getDomainInfo( DNSName( result["associatedDomain"][0] ), di ) ) + if (!getDomainInfo(DNSName(result["associatedDomain"][0]), di)) continue; - if( di.notified_serial < di.serial ) - domains->push_back( di ); + if (di.notified_serial < di.serial) + domains->push_back(di); } } - - -void LdapBackend::setNotified( uint32_t id, uint32_t serial ) +void LdapBackend::setNotified(uint32_t id, uint32_t serial) { string filter; PowerLDAP::SearchResult::Ptr search; PowerLDAP::sresult_t results; PowerLDAP::sentry_t entry; - const char* attronly[] = { "associatedDomain", NULL }; + const char* attronly[] = {"associatedDomain", NULL}; - try - { + try { // Try to find the notified domain - filter = strbind( ":target:", "PdnsDomainId=" + std::to_string( id ), getArg( "filter-axfr" ) ); - search = d_pldap->search( getArg( "basedn" ), LDAP_SCOPE_SUBTREE, filter, attronly ); - search->getAll( results, true ); + filter = strbind(":target:", "PdnsDomainId=" + std::to_string(id), getArg("filter-axfr")); + search = d_pldap->search(getArg("basedn"), LDAP_SCOPE_SUBTREE, filter, attronly); + search->getAll(results, true); } - catch( LDAPTimeout < ) - { + catch (LDAPTimeout& lt) { g_log << Logger::Warning << d_myname << " Unable to search LDAP directory: " << lt.what() << endl; - throw DBException( "LDAP server timeout" ); + throw DBException("LDAP server timeout"); } - catch( LDAPNoConnection &lnc ) - { + catch (LDAPNoConnection& lnc) { g_log << Logger::Warning << d_myname << " Connection to LDAP lost, trying to reconnect" << endl; - if ( reconnect() ) - this->setNotified( id, serial ); + if (reconnect()) + this->setNotified(id, serial); else - throw PDNSException( "Failed to reconnect to LDAP server" ); + throw PDNSException("Failed to reconnect to LDAP server"); } - catch( LDAPException &le ) - { + catch (LDAPException& le) { g_log << Logger::Error << d_myname << " Unable to search LDAP directory: " << le.what() << endl; - throw PDNSException( "LDAP server unreachable" ); // try to reconnect to another server + throw PDNSException("LDAP server unreachable"); // try to reconnect to another server } - catch( std::exception &e ) - { - throw DBException( "STL exception" ); + catch (std::exception& e) { + throw DBException("STL exception"); } - if ( results.empty() ) - throw PDNSException( "No results found when trying to update domain notified_serial for ID " + std::to_string( id ) ); + if (results.empty()) + throw PDNSException("No results found when trying to update domain notified_serial for ID " + std::to_string(id)); entry = results.front(); string dn = entry["dn"][0]; - string serialStr = std::to_string( serial ); - LDAPMod *mods[2]; + string serialStr = std::to_string(serial); + LDAPMod* mods[2]; LDAPMod mod; - char *vals[2]; + char* vals[2]; mod.mod_op = LDAP_MOD_REPLACE; mod.mod_type = (char*)"PdnsDomainNotifiedSerial"; - vals[0] = const_cast( serialStr.c_str() ); + vals[0] = const_cast(serialStr.c_str()); vals[1] = NULL; mod.mod_values = vals; mods[0] = &mod; mods[1] = NULL; - try - { - d_pldap->modify( dn, mods ); + try { + d_pldap->modify(dn, mods); } - catch( LDAPNoConnection &lnc ) - { + catch (LDAPNoConnection& lnc) { g_log << Logger::Warning << d_myname << " Connection to LDAP lost, trying to reconnect" << endl; - if ( reconnect() ) - this->setNotified( id, serial ); + if (reconnect()) + this->setNotified(id, serial); else - throw PDNSException( "Failed to reconnect to LDAP server" ); + throw PDNSException("Failed to reconnect to LDAP server"); } - catch( LDAPException &le ) - { + catch (LDAPException& le) { g_log << Logger::Error << d_myname << " Unable to search LDAP directory: " << le.what() << endl; - throw PDNSException( "LDAP server unreachable" ); // try to reconnect to another server + throw PDNSException("LDAP server unreachable"); // try to reconnect to another server } - catch( std::exception &e ) - { - throw DBException( "STL exception" ); + catch (std::exception& e) { + throw DBException("STL exception"); } } diff --git a/modules/ldapbackend/native.cc b/modules/ldapbackend/native.cc index 2c9bac2014..bb86ea67c3 100644 --- a/modules/ldapbackend/native.cc +++ b/modules/ldapbackend/native.cc @@ -24,67 +24,56 @@ #include "ldapbackend.hh" #include - -bool LdapBackend::list( const DNSName& target, int domain_id, bool include_disabled ) +bool LdapBackend::list(const DNSName& target, int domain_id, bool include_disabled) { - try - { + try { d_in_list = true; d_qname = target; d_qtype = QType::ANY; d_results_cache.clear(); - return (this->*d_list_fcnt)( target, domain_id ); + return (this->*d_list_fcnt)(target, domain_id); } - catch( LDAPTimeout < ) - { + catch (LDAPTimeout& lt) { g_log << Logger::Warning << d_myname << " Unable to get zone " << target << " from LDAP directory: " << lt.what() << endl; - throw DBException( "LDAP server timeout" ); + throw DBException("LDAP server timeout"); } - catch( LDAPNoConnection &lnc ) - { + catch (LDAPNoConnection& lnc) { g_log << Logger::Warning << d_myname << " Connection to LDAP lost, trying to reconnect" << endl; - if ( reconnect() ) - this->list( target, domain_id ); + if (reconnect()) + this->list(target, domain_id); else - throw PDNSException( "Failed to reconnect to LDAP server" ); + throw PDNSException("Failed to reconnect to LDAP server"); } - catch( LDAPException &le ) - { + catch (LDAPException& le) { g_log << Logger::Error << d_myname << " Unable to get zone " << target << " from LDAP directory: " << le.what() << endl; - throw PDNSException( "LDAP server unreachable" ); // try to reconnect to another server + throw PDNSException("LDAP server unreachable"); // try to reconnect to another server } - catch( std::exception &e ) - { + catch (std::exception& e) { g_log << Logger::Error << d_myname << " Caught STL exception for target " << target << ": " << e.what() << endl; - throw DBException( "STL exception" ); + throw DBException("STL exception"); } return false; } - - -bool LdapBackend::list_simple( const DNSName& target, int domain_id ) +bool LdapBackend::list_simple(const DNSName& target, int domain_id) { string dn; string filter; string qesc; - - dn = getArg( "basedn" ); - qesc = toLower( d_pldap->escape( target.toStringRootDot() ) ); + dn = getArg("basedn"); + qesc = toLower(d_pldap->escape(target.toStringRootDot())); // search for SOARecord of target - filter = strbind( ":target:", "&(associatedDomain=" + qesc + ")(sOARecord=*)", getArg( "filter-axfr" ) ); - PowerLDAP::SearchResult::Ptr search = d_pldap->search( dn, LDAP_SCOPE_SUBTREE, filter, (const char**) ldap_attrany ); - if ( !search->getNext( d_result, true ) ) + filter = strbind(":target:", "&(associatedDomain=" + qesc + ")(sOARecord=*)", getArg("filter-axfr")); + PowerLDAP::SearchResult::Ptr search = d_pldap->search(dn, LDAP_SCOPE_SUBTREE, filter, (const char**)ldap_attrany); + if (!search->getNext(d_result, true)) return false; - if( d_result.count( "dn" ) && !d_result["dn"].empty() ) - { - if( !mustDo( "basedn-axfr-override" ) ) - { + if (d_result.count("dn") && !d_result["dn"].empty()) { + if (!mustDo("basedn-axfr-override")) { dn = d_result["dn"][0]; } } @@ -93,217 +82,195 @@ bool LdapBackend::list_simple( const DNSName& target, int domain_id ) DNSResult soa_result; soa_result.ttl = d_default_ttl; soa_result.lastmod = 0; - this->extract_common_attributes( soa_result ); - this->extract_entry_results( d_qname, soa_result, QType(uint16_t(QType::ANY)) ); + this->extract_common_attributes(soa_result); + this->extract_entry_results(d_qname, soa_result, QType(uint16_t(QType::ANY))); - filter = strbind( ":target:", "associatedDomain=*." + qesc, getArg( "filter-axfr" ) ); + filter = strbind(":target:", "associatedDomain=*." + qesc, getArg("filter-axfr")); g_log << Logger::Debug << d_myname << " Search = basedn: " << dn << ", filter: " << filter << endl; - d_search = d_pldap->search( dn, LDAP_SCOPE_SUBTREE, filter, (const char**) ldap_attrany ); + d_search = d_pldap->search(dn, LDAP_SCOPE_SUBTREE, filter, (const char**)ldap_attrany); return true; } - -bool LdapBackend::list_strict( const DNSName& target, int domain_id ) +bool LdapBackend::list_strict(const DNSName& target, int domain_id) { - if( target.isPartOf(DNSName("in-addr.arpa")) || target.isPartOf(DNSName("ip6.arpa")) ) - { + if (target.isPartOf(DNSName("in-addr.arpa")) || target.isPartOf(DNSName("ip6.arpa"))) { g_log << Logger::Warning << d_myname << " Request for reverse zone AXFR, but this is not supported in strict mode" << endl; - return false; // AXFR isn't supported in strict mode. Use simple mode and additional PTR records + return false; // AXFR isn't supported in strict mode. Use simple mode and additional PTR records } - return list_simple( target, domain_id ); + return list_simple(target, domain_id); } - - -void LdapBackend::lookup( const QType &qtype, const DNSName &qname, int zoneid, DNSPacket *dnspkt ) +void LdapBackend::lookup(const QType& qtype, const DNSName& qname, int zoneid, DNSPacket* dnspkt) { - try - { + try { d_in_list = false; d_qname = qname; d_qtype = qtype; d_results_cache.clear(); - if( d_qlog ) { g_log.log( "Query: '" + qname.toStringRootDot() + "|" + qtype.getName() + "'", Logger::Error ); } - (this->*d_lookup_fcnt)( qtype, qname, dnspkt, zoneid ); + if (d_qlog) { + g_log.log("Query: '" + qname.toStringRootDot() + "|" + qtype.getName() + "'", Logger::Error); + } + (this->*d_lookup_fcnt)(qtype, qname, dnspkt, zoneid); } - catch( LDAPTimeout < ) - { + catch (LDAPTimeout& lt) { g_log << Logger::Warning << d_myname << " Unable to search LDAP directory: " << lt.what() << endl; - throw DBException( "LDAP server timeout" ); + throw DBException("LDAP server timeout"); } - catch( LDAPNoConnection &lnc ) - { + catch (LDAPNoConnection& lnc) { g_log << Logger::Warning << d_myname << " Connection to LDAP lost, trying to reconnect" << endl; - if ( reconnect() ) - this->lookup( qtype, qname, zoneid, dnspkt ); + if (reconnect()) + this->lookup(qtype, qname, zoneid, dnspkt); else - throw PDNSException( "Failed to reconnect to LDAP server" ); + throw PDNSException("Failed to reconnect to LDAP server"); } - catch( LDAPException &le ) - { + catch (LDAPException& le) { g_log << Logger::Error << d_myname << " Unable to search LDAP directory: " << le.what() << endl; - throw PDNSException( "LDAP server unreachable" ); // try to reconnect to another server + throw PDNSException("LDAP server unreachable"); // try to reconnect to another server } - catch( std::exception &e ) - { + catch (std::exception& e) { g_log << Logger::Error << d_myname << " Caught STL exception for qname " << qname << ": " << e.what() << endl; - throw DBException( "STL exception" ); + throw DBException("STL exception"); } } - - -void LdapBackend::lookup_simple( const QType &qtype, const DNSName &qname, DNSPacket *dnspkt, int zoneid ) +void LdapBackend::lookup_simple(const QType& qtype, const DNSName& qname, DNSPacket* dnspkt, int zoneid) { string filter, attr, qesc; - const char** attributes = ldap_attrany + 1; // skip associatedDomain - const char* attronly[] = { NULL, "dNSTTL", "modifyTimestamp", "PdnsRecordTTL", "PdnsRecordAuth", "PdnsRecordOrdername", NULL }; - + const char** attributes = ldap_attrany + 1; // skip associatedDomain + const char* attronly[] = {NULL, "dNSTTL", "modifyTimestamp", "PdnsRecordTTL", "PdnsRecordAuth", "PdnsRecordOrdername", NULL}; - qesc = toLower( d_pldap->escape( qname.toStringRootDot() ) ); + qesc = toLower(d_pldap->escape(qname.toStringRootDot())); filter = "associatedDomain=" + qesc; - if( qtype.getCode() != QType::ANY ) - { + if (qtype.getCode() != QType::ANY) { attr = qtype.getName() + "Record"; filter = "&(" + filter + ")(" + attr + "=*)"; attronly[0] = attr.c_str(); attributes = attronly; } - filter = strbind( ":target:", filter, getArg( "filter-lookup" ) ); + filter = strbind(":target:", filter, getArg("filter-lookup")); - g_log << Logger::Debug << d_myname << " Search = basedn: " << getArg( "basedn" ) << ", filter: " << filter << ", qtype: " << qtype.getName() << endl; - d_search = d_pldap->search( getArg( "basedn" ), LDAP_SCOPE_SUBTREE, filter, attributes ); + g_log << Logger::Debug << d_myname << " Search = basedn: " << getArg("basedn") << ", filter: " << filter << ", qtype: " << qtype.getName() << endl; + d_search = d_pldap->search(getArg("basedn"), LDAP_SCOPE_SUBTREE, filter, attributes); } - - -void LdapBackend::lookup_strict( const QType &qtype, const DNSName &qname, DNSPacket *dnspkt, int zoneid ) +void LdapBackend::lookup_strict(const QType& qtype, const DNSName& qname, DNSPacket* dnspkt, int zoneid) { int len; vector parts; string filter, attr, qesc; - const char** attributes = ldap_attrany + 1; // skip associatedDomain - const char* attronly[] = { NULL, "dNSTTL", "modifyTimestamp", "PdnsRecordTTL", "PdnsRecordAuth", "PdnsRecordOrdername", NULL }; + const char** attributes = ldap_attrany + 1; // skip associatedDomain + const char* attronly[] = {NULL, "dNSTTL", "modifyTimestamp", "PdnsRecordTTL", "PdnsRecordAuth", "PdnsRecordOrdername", NULL}; - - qesc = toLower( d_pldap->escape( qname.toStringRootDot() ) ); - stringtok( parts, qesc, "." ); + qesc = toLower(d_pldap->escape(qname.toStringRootDot())); + stringtok(parts, qesc, "."); len = qesc.length(); - if( parts.size() == 6 && len > 13 && qesc.substr( len - 13, 13 ) == ".in-addr.arpa" ) // IPv4 reverse lookups + if (parts.size() == 6 && len > 13 && qesc.substr(len - 13, 13) == ".in-addr.arpa") // IPv4 reverse lookups { - filter = "aRecord=" + ptr2ip4( parts ); + filter = "aRecord=" + ptr2ip4(parts); attronly[0] = "associatedDomain"; attributes = attronly; } - else if( parts.size() == 34 && len > 9 && ( qesc.substr( len - 9, 9 ) == ".ip6.arpa" ) ) // IPv6 reverse lookups + else if (parts.size() == 34 && len > 9 && (qesc.substr(len - 9, 9) == ".ip6.arpa")) // IPv6 reverse lookups { - filter = "aAAARecord=" + ptr2ip6( parts ); + filter = "aAAARecord=" + ptr2ip6(parts); attronly[0] = "associatedDomain"; attributes = attronly; } - else // IPv4 and IPv6 lookups + else // IPv4 and IPv6 lookups { filter = "associatedDomain=" + qesc; } - if( qtype.getCode() != QType::ANY ) - { + if (qtype.getCode() != QType::ANY) { attr = qtype.getName() + "Record"; filter = "&(" + filter + ")(" + attr + "=*)"; attronly[0] = attr.c_str(); attributes = attronly; } - filter = strbind( ":target:", filter, getArg( "filter-lookup" ) ); + filter = strbind(":target:", filter, getArg("filter-lookup")); - g_log << Logger::Debug << d_myname << " Search = basedn: " << getArg( "basedn" ) << ", filter: " << filter << ", qtype: " << qtype.getName() << endl; - d_search = d_pldap->search( getArg( "basedn" ), LDAP_SCOPE_SUBTREE, filter, attributes ); + g_log << Logger::Debug << d_myname << " Search = basedn: " << getArg("basedn") << ", filter: " << filter << ", qtype: " << qtype.getName() << endl; + d_search = d_pldap->search(getArg("basedn"), LDAP_SCOPE_SUBTREE, filter, attributes); } - - -void LdapBackend::lookup_tree( const QType &qtype, const DNSName &qname, DNSPacket *dnspkt, int zoneid ) +void LdapBackend::lookup_tree(const QType& qtype, const DNSName& qname, DNSPacket* dnspkt, int zoneid) { string filter, attr, qesc, dn; - const char** attributes = ldap_attrany + 1; // skip associatedDomain - const char* attronly[] = { NULL, "dNSTTL", "modifyTimestamp", "PdnsRecordTTL", "PdnsRecordAuth", "PdnsRecordOrdername", NULL }; + const char** attributes = ldap_attrany + 1; // skip associatedDomain + const char* attronly[] = {NULL, "dNSTTL", "modifyTimestamp", "PdnsRecordTTL", "PdnsRecordAuth", "PdnsRecordOrdername", NULL}; vector parts; - - qesc = toLower( d_pldap->escape( qname.toStringRootDot() ) ); + qesc = toLower(d_pldap->escape(qname.toStringRootDot())); filter = "associatedDomain=" + qesc; - if( qtype.getCode() != QType::ANY ) - { + if (qtype.getCode() != QType::ANY) { attr = qtype.getName() + "Record"; filter = "&(" + filter + ")(" + attr + "=*)"; attronly[0] = attr.c_str(); attributes = attronly; } - filter = strbind( ":target:", filter, getArg( "filter-lookup" ) ); + filter = strbind(":target:", filter, getArg("filter-lookup")); - stringtok( parts, toLower( qname.toString() ), "." ); - for(auto i = parts.crbegin(); i != parts.crend(); i++ ) - { + stringtok(parts, toLower(qname.toString()), "."); + for (auto i = parts.crbegin(); i != parts.crend(); i++) { dn = "dc=" + *i + "," + dn; } - g_log << Logger::Debug << d_myname << " Search = basedn: " << dn + getArg( "basedn" ) << ", filter: " << filter << ", qtype: " << qtype.getName() << endl; - d_search = d_pldap->search( dn + getArg( "basedn" ), LDAP_SCOPE_BASE, filter, attributes ); + g_log << Logger::Debug << d_myname << " Search = basedn: " << dn + getArg("basedn") << ", filter: " << filter << ", qtype: " << qtype.getName() << endl; + d_search = d_pldap->search(dn + getArg("basedn"), LDAP_SCOPE_BASE, filter, attributes); } - -bool LdapBackend::get( DNSResourceRecord &rr ) +bool LdapBackend::get(DNSResourceRecord& rr) { - if ( d_results_cache.empty() ) { - while ( d_results_cache.empty() ) { + if (d_results_cache.empty()) { + while (d_results_cache.empty()) { bool exhausted = false; bool valid_entry_found = false; - while ( !valid_entry_found && !exhausted ) { + while (!valid_entry_found && !exhausted) { try { - exhausted = !d_search->getNext( d_result, true ); + exhausted = !d_search->getNext(d_result, true); } - catch( LDAPException &le ) - { + catch (LDAPException& le) { g_log << Logger::Error << d_myname << " Failed to get next result: " << le.what() << endl; - throw PDNSException( "Get next result impossible" ); + throw PDNSException("Get next result impossible"); } - if ( !exhausted ) { - if ( !d_in_list ) { + if (!exhausted) { + if (!d_in_list) { // All entries are valid here valid_entry_found = true; } else { // If we're called after list() then the entry *must* contain // associatedDomain, otherwise let's just skip it - if ( d_result.count( "associatedDomain" ) ) + if (d_result.count("associatedDomain")) valid_entry_found = true; } } } - if ( exhausted ) { + if (exhausted) { break; } DNSResult result_template; result_template.ttl = d_default_ttl; result_template.lastmod = 0; - this->extract_common_attributes( result_template ); + this->extract_common_attributes(result_template); std::vector associatedDomains; - if ( d_result.count( "associatedDomain" ) ) { - if ( d_in_list ) { + if (d_result.count("associatedDomain")) { + if (d_in_list) { // We can have more than one associatedDomain in the entry, so for each of them we have to check // that they are indeed under the domain we've been asked to list (nothing enforces this, so you // can have one associatedDomain set to "host.first-domain.com" and another one set to @@ -312,10 +279,10 @@ bool LdapBackend::get( DNSResourceRecord &rr ) // and the others above we've already cleaned it's just a matter of iterating over them. unsigned int axfrqlen = d_qname.toStringRootDot().length(); - for ( auto i = d_result["associatedDomain"].begin(); i != d_result["associatedDomain"].end(); ++i ) { + for (auto i = d_result["associatedDomain"].begin(); i != d_result["associatedDomain"].end(); ++i) { // Sanity checks: is this associatedDomain attribute under the requested domain? - if ( i->size() >= axfrqlen && i->substr( i->size() - axfrqlen, axfrqlen ) == d_qname.toStringRootDot() ) - associatedDomains.push_back( *i ); + if (i->size() >= axfrqlen && i->substr(i->size() - axfrqlen, axfrqlen) == d_qname.toStringRootDot()) + associatedDomains.push_back(*i); } } else { @@ -325,16 +292,16 @@ bool LdapBackend::get( DNSResourceRecord &rr ) } } - if ( d_in_list ) { - for ( const auto& domain : associatedDomains ) - this->extract_entry_results( DNSName( domain ), result_template, QType(uint16_t(QType::ANY)) ); + if (d_in_list) { + for (const auto& domain : associatedDomains) + this->extract_entry_results(DNSName(domain), result_template, QType(uint16_t(QType::ANY))); } else { - this->extract_entry_results( d_qname, result_template, QType(uint16_t(QType::ANY)) ); + this->extract_entry_results(d_qname, result_template, QType(uint16_t(QType::ANY))); } } - if ( d_results_cache.empty() ) + if (d_results_cache.empty()) return false; } @@ -351,8 +318,7 @@ bool LdapBackend::get( DNSResourceRecord &rr ) return true; } - -bool LdapBackend::getDomainInfo( const DNSName& domain, DomainInfo& di, bool getSerial ) +bool LdapBackend::getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial) { string filter; SOAData sd; @@ -364,74 +330,67 @@ bool LdapBackend::getDomainInfo( const DNSName& domain, DomainInfo& di, bool get "PdnsDomainLastCheck", "PdnsDomainMaster", "PdnsDomainType", - NULL - }; + NULL}; - try - { + try { // search for SOARecord of domain - filter = "(&(associatedDomain=" + toLower( d_pldap->escape( domain.toStringRootDot() ) ) + ")(SOARecord=*))"; - d_search = d_pldap->search( getArg( "basedn" ), LDAP_SCOPE_SUBTREE, filter, attronly ); - if (!d_search->getNext( result )) { + filter = "(&(associatedDomain=" + toLower(d_pldap->escape(domain.toStringRootDot())) + ")(SOARecord=*))"; + d_search = d_pldap->search(getArg("basedn"), LDAP_SCOPE_SUBTREE, filter, attronly); + if (!d_search->getNext(result)) { return false; } } - catch( LDAPTimeout < ) - { + catch (LDAPTimeout& lt) { g_log << Logger::Warning << d_myname << " Unable to search LDAP directory: " << lt.what() << endl; - throw DBException( "LDAP server timeout" ); + throw DBException("LDAP server timeout"); } - catch( LDAPNoConnection &lnc ) - { + catch (LDAPNoConnection& lnc) { g_log << Logger::Warning << d_myname << " Connection to LDAP lost, trying to reconnect" << endl; - if ( reconnect() ) - this->getDomainInfo( domain, di ); + if (reconnect()) + this->getDomainInfo(domain, di); else - throw PDNSException( "Failed to reconnect to LDAP server" ); + throw PDNSException("Failed to reconnect to LDAP server"); } - catch( LDAPException &le ) - { + catch (LDAPException& le) { g_log << Logger::Error << d_myname << " Unable to search LDAP directory: " << le.what() << endl; - throw PDNSException( "LDAP server unreachable" ); // try to reconnect to another server + throw PDNSException("LDAP server unreachable"); // try to reconnect to another server } - catch( std::exception &e ) - { - throw DBException( "STL exception" ); + catch (std::exception& e) { + throw DBException("STL exception"); } - if( result.count( "sOARecord" ) && !result["sOARecord"].empty() ) - { + if (result.count("sOARecord") && !result["sOARecord"].empty()) { sd.serial = 0; - fillSOAData( result["sOARecord"][0], sd ); + fillSOAData(result["sOARecord"][0], sd); - if ( result.count( "PdnsDomainId" ) && !result["PdnsDomainId"].empty() ) - di.id = std::stoi( result["PdnsDomainId"][0] ); + if (result.count("PdnsDomainId") && !result["PdnsDomainId"].empty()) + di.id = std::stoi(result["PdnsDomainId"][0]); else di.id = 0; di.serial = sd.serial; di.zone = DNSName(domain); - if( result.count( "PdnsDomainLastCheck" ) && !result["PdnsDomainLastCheck"].empty() ) - di.last_check = pdns_stou( result["PdnsDomainLastCheck"][0] ); + if (result.count("PdnsDomainLastCheck") && !result["PdnsDomainLastCheck"].empty()) + di.last_check = pdns_stou(result["PdnsDomainLastCheck"][0]); else di.last_check = 0; - if ( result.count( "PdnsDomainNotifiedSerial" ) && !result["PdnsDomainNotifiedSerial"].empty() ) - di.notified_serial = pdns_stou( result["PdnsDomainNotifiedSerial"][0] ); + if (result.count("PdnsDomainNotifiedSerial") && !result["PdnsDomainNotifiedSerial"].empty()) + di.notified_serial = pdns_stou(result["PdnsDomainNotifiedSerial"][0]); else di.notified_serial = 0; - if ( result.count( "PdnsDomainMaster" ) && !result["PdnsDomainMaster"].empty() ) { - for(const auto &m : result["PdnsDomainMaster"]) + if (result.count("PdnsDomainMaster") && !result["PdnsDomainMaster"].empty()) { + for (const auto& m : result["PdnsDomainMaster"]) di.masters.emplace_back(m, 53); } - if ( result.count( "PdnsDomainType" ) && !result["PdnsDomainType"].empty() ) { + if (result.count("PdnsDomainType") && !result["PdnsDomainType"].empty()) { string kind = result["PdnsDomainType"][0]; - if ( kind == "master" ) + if (kind == "master") di.kind = DomainInfo::Master; - else if ( kind == "slave" ) + else if (kind == "slave") di.kind = DomainInfo::Slave; else di.kind = DomainInfo::Native; diff --git a/modules/ldapbackend/powerldap.cc b/modules/ldapbackend/powerldap.cc index a2c1a5353f..fc5af43c0c 100644 --- a/modules/ldapbackend/powerldap.cc +++ b/modules/ldapbackend/powerldap.cc @@ -30,22 +30,19 @@ #include "pdns/misc.hh" #include - -PowerLDAP::SearchResult::SearchResult( int msgid, LDAP* ld ) - : d_ld( ld ), d_msgid( msgid ), d_finished( false ) +PowerLDAP::SearchResult::SearchResult(int msgid, LDAP* ld) : + d_ld(ld), d_msgid(msgid), d_finished(false) { } - PowerLDAP::SearchResult::~SearchResult() { - if ( !d_finished ) - ldap_abandon_ext( d_ld, d_msgid, NULL, NULL ); // We don't really care about the return code as there's - // not much we can do now + if (!d_finished) + ldap_abandon_ext(d_ld, d_msgid, NULL, NULL); // We don't really care about the return code as there's + // not much we can do now } - -bool PowerLDAP::SearchResult::getNext( PowerLDAP::sentry_t& entry, bool dn, int timeout ) +bool PowerLDAP::SearchResult::getNext(PowerLDAP::sentry_t& entry, bool dn, int timeout) { int i; char* attr; @@ -55,94 +52,84 @@ bool PowerLDAP::SearchResult::getNext( PowerLDAP::sentry_t& entry, bool dn, int LDAPMessage* result = NULL; LDAPMessage* object; - while ( !d_finished && result == NULL ) { - i = ldapWaitResult( d_ld, d_msgid, 5, &result ); - switch ( i ) { - case -1: - int err_code; - ldapGetOption( d_ld, LDAP_OPT_ERROR_NUMBER, &err_code ); - if ( err_code == LDAP_SERVER_DOWN || err_code == LDAP_CONNECT_ERROR ) - throw LDAPNoConnection(); - else - throw LDAPException( "Error waiting for LDAP result: " + ldapGetError( d_ld, err_code ) ); - break; - case 0: - throw LDAPTimeout(); - break; - case LDAP_NO_SUCH_OBJECT: - return false; - case LDAP_RES_SEARCH_REFERENCE: - ldap_msgfree( result ); - result = NULL; - break; - case LDAP_RES_SEARCH_RESULT: - d_finished = true; - ldap_msgfree( result ); - break; - case LDAP_RES_SEARCH_ENTRY: - // Yay! - break; + while (!d_finished && result == NULL) { + i = ldapWaitResult(d_ld, d_msgid, 5, &result); + switch (i) { + case -1: + int err_code; + ldapGetOption(d_ld, LDAP_OPT_ERROR_NUMBER, &err_code); + if (err_code == LDAP_SERVER_DOWN || err_code == LDAP_CONNECT_ERROR) + throw LDAPNoConnection(); + else + throw LDAPException("Error waiting for LDAP result: " + ldapGetError(d_ld, err_code)); + break; + case 0: + throw LDAPTimeout(); + break; + case LDAP_NO_SUCH_OBJECT: + return false; + case LDAP_RES_SEARCH_REFERENCE: + ldap_msgfree(result); + result = NULL; + break; + case LDAP_RES_SEARCH_RESULT: + d_finished = true; + ldap_msgfree(result); + break; + case LDAP_RES_SEARCH_ENTRY: + // Yay! + break; } } - if ( d_finished ) + if (d_finished) return false; - if( ( object = ldap_first_entry( d_ld, result ) ) == NULL ) - { - ldap_msgfree( result ); - throw LDAPException( "Couldn't get first result entry: " + ldapGetError( d_ld, -1 ) ); + if ((object = ldap_first_entry(d_ld, result)) == NULL) { + ldap_msgfree(result); + throw LDAPException("Couldn't get first result entry: " + ldapGetError(d_ld, -1)); } entry.clear(); - if( dn ) - { - attr = ldap_get_dn( d_ld, object ); - values.push_back( string( attr ) ); - ldap_memfree( attr ); + if (dn) { + attr = ldap_get_dn(d_ld, object); + values.push_back(string(attr)); + ldap_memfree(attr); entry["dn"] = values; } - if( ( attr = ldap_first_attribute( d_ld, object, &ber ) ) != NULL ) - { - do - { - if( ( berval = ldap_get_values_len( d_ld, object, attr ) ) != NULL ) - { + if ((attr = ldap_first_attribute(d_ld, object, &ber)) != NULL) { + do { + if ((berval = ldap_get_values_len(d_ld, object, attr)) != NULL) { values.clear(); - for( i = 0; i < ldap_count_values_len( berval ); i++ ) - { - values.push_back( berval[i]->bv_val ); // use berval[i]->bv_len for non string values? + for (i = 0; i < ldap_count_values_len(berval); i++) { + values.push_back(berval[i]->bv_val); // use berval[i]->bv_len for non string values? } entry[attr] = values; - ldap_value_free_len( berval ); + ldap_value_free_len(berval); } - ldap_memfree( attr ); - } - while( ( attr = ldap_next_attribute( d_ld, object, ber ) ) != NULL ); + ldap_memfree(attr); + } while ((attr = ldap_next_attribute(d_ld, object, ber)) != NULL); - ber_free( ber, 0 ); + ber_free(ber, 0); } - ldap_msgfree( result ); + ldap_msgfree(result); return true; } - -void PowerLDAP::SearchResult::getAll( PowerLDAP::sresult_t& results, bool dn, int timeout ) +void PowerLDAP::SearchResult::getAll(PowerLDAP::sresult_t& results, bool dn, int timeout) { PowerLDAP::sentry_t entry; - while( getNext( entry, dn, timeout ) ) - { - results.push_back( entry ); + while (getNext(entry, dn, timeout)) { + results.push_back(entry); } } - -PowerLDAP::PowerLDAP( const string& hosts, uint16_t port, bool tls, int timeout ) +PowerLDAP::PowerLDAP(const string& hosts, uint16_t port, bool tls, int timeout) { d_ld = 0; d_hosts = hosts; @@ -156,93 +143,78 @@ void PowerLDAP::ensureConnect() { int err; - if(d_ld) { - ldap_unbind_ext( d_ld, NULL, NULL ); + if (d_ld) { + ldap_unbind_ext(d_ld, NULL, NULL); } #ifdef HAVE_LDAP_INITIALIZE - if( ( err = ldap_initialize( &d_ld, d_hosts.c_str() ) ) != LDAP_SUCCESS ) - { + if ((err = ldap_initialize(&d_ld, d_hosts.c_str())) != LDAP_SUCCESS) { string ldapuris; vector uris; - stringtok( uris, d_hosts ); + stringtok(uris, d_hosts); - for( size_t i = 0; i < uris.size(); i++ ) - { + for (size_t i = 0; i < uris.size(); i++) { ldapuris += " ldap://" + uris[i]; } - if( ( err = ldap_initialize( &d_ld, ldapuris.c_str() ) ) != LDAP_SUCCESS ) - { - throw LDAPException( "Error initializing LDAP connection to '" + ldapuris + ": " + getError( err ) ); + if ((err = ldap_initialize(&d_ld, ldapuris.c_str())) != LDAP_SUCCESS) { + throw LDAPException("Error initializing LDAP connection to '" + ldapuris + ": " + getError(err)); } } #else - if( ( d_ld = ldap_init( d_hosts.c_str(), d_port ) ) == NULL ) - { - throw LDAPException( "Error initializing LDAP connection to '" + d_hosts + "': " + string( strerror( errno ) ) ); + if ((d_ld = ldap_init(d_hosts.c_str(), d_port)) == NULL) { + throw LDAPException("Error initializing LDAP connection to '" + d_hosts + "': " + string(strerror(errno))); } #endif int protocol = LDAP_VERSION3; - if( ldap_set_option( d_ld, LDAP_OPT_PROTOCOL_VERSION, &protocol ) != LDAP_OPT_SUCCESS ) - { + if (ldap_set_option(d_ld, LDAP_OPT_PROTOCOL_VERSION, &protocol) != LDAP_OPT_SUCCESS) { protocol = LDAP_VERSION2; - if( ldap_set_option( d_ld, LDAP_OPT_PROTOCOL_VERSION, &protocol ) != LDAP_OPT_SUCCESS ) - { - ldap_unbind_ext( d_ld, NULL, NULL ); - throw LDAPException( "Couldn't set protocol version to LDAPv3 or LDAPv2" ); + if (ldap_set_option(d_ld, LDAP_OPT_PROTOCOL_VERSION, &protocol) != LDAP_OPT_SUCCESS) { + ldap_unbind_ext(d_ld, NULL, NULL); + throw LDAPException("Couldn't set protocol version to LDAPv3 or LDAPv2"); } } - if( d_tls && ( err = ldap_start_tls_s( d_ld, NULL, NULL ) ) != LDAP_SUCCESS ) - { - ldap_unbind_ext( d_ld, NULL, NULL ); - throw LDAPException( "Couldn't perform STARTTLS: " + getError( err ) ); + if (d_tls && (err = ldap_start_tls_s(d_ld, NULL, NULL)) != LDAP_SUCCESS) { + ldap_unbind_ext(d_ld, NULL, NULL); + throw LDAPException("Couldn't perform STARTTLS: " + getError(err)); } } - PowerLDAP::~PowerLDAP() { - ldap_unbind_ext( d_ld, NULL, NULL ); + ldap_unbind_ext(d_ld, NULL, NULL); } - bool PowerLDAP::connect() { - try - { + try { ensureConnect(); return true; } - catch( LDAPException &le ) - { + catch (LDAPException& le) { return false; } } - -void PowerLDAP::setOption( int option, int value ) +void PowerLDAP::setOption(int option, int value) { - ldapSetOption( d_ld, option, (void*) &value ); + ldapSetOption(d_ld, option, (void*)&value); } - -void PowerLDAP::getOption( int option, int *value ) +void PowerLDAP::getOption(int option, int* value) { - ldapGetOption( d_ld, option, (void*) value ); + ldapGetOption(d_ld, option, (void*)value); } - -void PowerLDAP::bind( LdapAuthenticator* authenticator ) +void PowerLDAP::bind(LdapAuthenticator* authenticator) { - if ( !authenticator->authenticate( d_ld ) ) - throw LDAPException( "Failed to bind to LDAP server: " + authenticator->getError() ); + if (!authenticator->authenticate(d_ld)) + throw LDAPException("Failed to bind to LDAP server: " + authenticator->getError()); } - -void PowerLDAP::bind( const string& ldapbinddn, const string& ldapsecret, int method) +void PowerLDAP::bind(const string& ldapbinddn, const string& ldapsecret, int method) { int msgid; @@ -250,95 +222,86 @@ void PowerLDAP::bind( const string& ldapbinddn, const string& ldapsecret, int me int rc; struct berval passwd; - passwd.bv_val = (char *)ldapsecret.c_str(); - passwd.bv_len = strlen( passwd.bv_val ); + passwd.bv_val = (char*)ldapsecret.c_str(); + passwd.bv_len = strlen(passwd.bv_val); - if( ( rc = ldap_sasl_bind( d_ld, ldapbinddn.c_str(), LDAP_SASL_SIMPLE, &passwd, NULL, NULL, &msgid ) ) != LDAP_SUCCESS ) - { - throw LDAPException( "Failed to bind to LDAP server: " + getError( rc ) ); + if ((rc = ldap_sasl_bind(d_ld, ldapbinddn.c_str(), LDAP_SASL_SIMPLE, &passwd, NULL, NULL, &msgid)) != LDAP_SUCCESS) { + throw LDAPException("Failed to bind to LDAP server: " + getError(rc)); } #else - if( ( msgid = ldap_bind( d_ld, ldapbinddn.c_str(), ldapsecret.c_str(), method ) ) == -1 ) - { - throw LDAPException( "Failed to bind to LDAP server: " + getError( msgid ) ); + if ((msgid = ldap_bind(d_ld, ldapbinddn.c_str(), ldapsecret.c_str(), method)) == -1) { + throw LDAPException("Failed to bind to LDAP server: " + getError(msgid)); } #endif - ldapWaitResult( d_ld, msgid, d_timeout, NULL ); + ldapWaitResult(d_ld, msgid, d_timeout, NULL); } - /** * Deprecated, use PowerLDAP::bind() instead */ -void PowerLDAP::simpleBind( const string& ldapbinddn, const string& ldapsecret ) +void PowerLDAP::simpleBind(const string& ldapbinddn, const string& ldapsecret) { - this->bind( ldapbinddn, ldapsecret, LDAP_AUTH_SIMPLE ); + this->bind(ldapbinddn, ldapsecret, LDAP_AUTH_SIMPLE); } - -void PowerLDAP::add( const string &dn, LDAPMod *mods[] ) +void PowerLDAP::add(const string& dn, LDAPMod* mods[]) { int rc; - rc = ldap_add_ext_s( d_ld, dn.c_str(), mods, NULL, NULL ); - if ( rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR ) + rc = ldap_add_ext_s(d_ld, dn.c_str(), mods, NULL, NULL); + if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR) throw LDAPNoConnection(); - else if ( rc != LDAP_SUCCESS ) - throw LDAPException( "Error adding LDAP entry " + dn + ": " + getError( rc ) ); + else if (rc != LDAP_SUCCESS) + throw LDAPException("Error adding LDAP entry " + dn + ": " + getError(rc)); } - -void PowerLDAP::modify( const string &dn, LDAPMod *mods[], LDAPControl **scontrols, LDAPControl **ccontrols ) +void PowerLDAP::modify(const string& dn, LDAPMod* mods[], LDAPControl** scontrols, LDAPControl** ccontrols) { int rc; - rc = ldap_modify_ext_s( d_ld, dn.c_str(), mods, scontrols, ccontrols ); - if ( rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR ) + rc = ldap_modify_ext_s(d_ld, dn.c_str(), mods, scontrols, ccontrols); + if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR) throw LDAPNoConnection(); - else if ( rc != LDAP_SUCCESS ) - throw LDAPException( "Error modifying LDAP entry " + dn + ": " + getError( rc ) ); + else if (rc != LDAP_SUCCESS) + throw LDAPException("Error modifying LDAP entry " + dn + ": " + getError(rc)); } - -void PowerLDAP::del( const string& dn ) +void PowerLDAP::del(const string& dn) { int rc; - rc = ldap_delete_ext_s( d_ld, dn.c_str(), NULL, NULL ); - if ( rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR ) + rc = ldap_delete_ext_s(d_ld, dn.c_str(), NULL, NULL); + if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR) throw LDAPNoConnection(); - else if ( rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT ) - throw LDAPException( "Error deleting LDAP entry " + dn + ": " + getError( rc ) ); + else if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT) + throw LDAPException("Error deleting LDAP entry " + dn + ": " + getError(rc)); } - -PowerLDAP::SearchResult::Ptr PowerLDAP::search( const string& base, int scope, const string& filter, const char** attr ) +PowerLDAP::SearchResult::Ptr PowerLDAP::search(const string& base, int scope, const string& filter, const char** attr) { int msgid, rc; - if ( ( rc = ldap_search_ext( d_ld, base.c_str(), scope, filter.c_str(), const_cast (attr), 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &msgid ) ) ) { - throw LDAPException( "Starting LDAP search: " + getError( rc ) ); + if ((rc = ldap_search_ext(d_ld, base.c_str(), scope, filter.c_str(), const_cast(attr), 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &msgid))) { + throw LDAPException("Starting LDAP search: " + getError(rc)); } - return SearchResult::Ptr( new SearchResult( msgid, d_ld ) ); + return SearchResult::Ptr(new SearchResult(msgid, d_ld)); } - /** * Function waits for a result, returns its type and optionally stores the result. * If the result is returned, the caller is responsible for freeing it with * ldap_msgfree! */ -int PowerLDAP::waitResult( int msgid, LDAPMessage** result ) +int PowerLDAP::waitResult(int msgid, LDAPMessage** result) { - return ldapWaitResult( d_ld, msgid, d_timeout, result ); + return ldapWaitResult(d_ld, msgid, d_timeout, result); } - -bool PowerLDAP::getSearchEntry( int msgid, sentry_t& entry, bool dn ) +bool PowerLDAP::getSearchEntry(int msgid, sentry_t& entry, bool dn) { int i; char* attr; @@ -349,119 +312,101 @@ bool PowerLDAP::getSearchEntry( int msgid, sentry_t& entry, bool dn ) LDAPMessage* object; bool hasResult = false; - while ( !hasResult ) { - i = waitResult( msgid, &result ); + while (!hasResult) { + i = waitResult(msgid, &result); // Here we deliberately ignore LDAP_RES_SEARCH_REFERENCE as we don't follow them. // Instead we get the next result. // If the function returned an error (i <= 0) we'll deal with after this loop too. - if ( i == LDAP_RES_SEARCH_ENTRY || i == LDAP_RES_SEARCH_RESULT || i <= 0 ) + if (i == LDAP_RES_SEARCH_ENTRY || i == LDAP_RES_SEARCH_RESULT || i <= 0) hasResult = true; } - if ( i == -1 ) { + if (i == -1) { // Error while retrieving the message int err_code; - ldapGetOption( d_ld, LDAP_OPT_ERROR_NUMBER, &err_code ); - if ( err_code == LDAP_SERVER_DOWN || err_code == LDAP_CONNECT_ERROR ) + ldapGetOption(d_ld, LDAP_OPT_ERROR_NUMBER, &err_code); + if (err_code == LDAP_SERVER_DOWN || err_code == LDAP_CONNECT_ERROR) throw LDAPNoConnection(); else - throw LDAPException( "PowerLDAP::getSearchEntry(): Error when retrieving LDAP result: " + getError( err_code ) ); + throw LDAPException("PowerLDAP::getSearchEntry(): Error when retrieving LDAP result: " + getError(err_code)); } - if ( i == 0 ) { + if (i == 0) { // Timeout expired before the message could be retrieved throw LDAPTimeout(); } - if ( i == LDAP_RES_SEARCH_RESULT ) { + if (i == LDAP_RES_SEARCH_RESULT) { // We're done with this request - ldap_msgfree( result ); + ldap_msgfree(result); return false; } - if( ( object = ldap_first_entry( d_ld, result ) ) == NULL ) - { - ldap_msgfree( result ); - throw LDAPException( "Couldn't get first result entry: " + getError() ); + if ((object = ldap_first_entry(d_ld, result)) == NULL) { + ldap_msgfree(result); + throw LDAPException("Couldn't get first result entry: " + getError()); } entry.clear(); - if( dn ) - { - attr = ldap_get_dn( d_ld, object ); - values.push_back( string( attr ) ); - ldap_memfree( attr ); + if (dn) { + attr = ldap_get_dn(d_ld, object); + values.push_back(string(attr)); + ldap_memfree(attr); entry["dn"] = values; } - if( ( attr = ldap_first_attribute( d_ld, object, &ber ) ) != NULL ) - { - do - { - if( ( berval = ldap_get_values_len( d_ld, object, attr ) ) != NULL ) - { + if ((attr = ldap_first_attribute(d_ld, object, &ber)) != NULL) { + do { + if ((berval = ldap_get_values_len(d_ld, object, attr)) != NULL) { values.clear(); - for( i = 0; i < ldap_count_values_len( berval ); i++ ) - { - values.push_back( berval[i]->bv_val ); // use berval[i]->bv_len for non string values? + for (i = 0; i < ldap_count_values_len(berval); i++) { + values.push_back(berval[i]->bv_val); // use berval[i]->bv_len for non string values? } entry[attr] = values; - ldap_value_free_len( berval ); + ldap_value_free_len(berval); } - ldap_memfree( attr ); - } - while( ( attr = ldap_next_attribute( d_ld, object, ber ) ) != NULL ); + ldap_memfree(attr); + } while ((attr = ldap_next_attribute(d_ld, object, ber)) != NULL); - ber_free( ber, 0 ); + ber_free(ber, 0); } - ldap_msgfree( result ); + ldap_msgfree(result); return true; } - -void PowerLDAP::getSearchResults( int msgid, sresult_t& result, bool dn ) +void PowerLDAP::getSearchResults(int msgid, sresult_t& result, bool dn) { sentry_t entry; result.clear(); - while( getSearchEntry( msgid, entry, dn ) ) - { - result.push_back( entry ); + while (getSearchEntry(msgid, entry, dn)) { + result.push_back(entry); } } - -const string PowerLDAP::getError( int rc ) +const string PowerLDAP::getError(int rc) { - return ldapGetError( d_ld, rc ); + return ldapGetError(d_ld, rc); } - -const string PowerLDAP::escape( const string& str ) +const string PowerLDAP::escape(const string& str) { string a; string::const_iterator i; char tmp[4]; - for( i = str.begin(); i != str.end(); i++ ) - { - // RFC4515 3 - if( (unsigned char)*i == '*' || - (unsigned char)*i == '(' || - (unsigned char)*i == ')' || - (unsigned char)*i == '\\' || - (unsigned char)*i == '\0' || - (unsigned char)*i > 127) - { - snprintf(tmp, sizeof(tmp), "\\%02x", (unsigned char)*i); - - a += tmp; - } - else - a += *i; + for (i = str.begin(); i != str.end(); i++) { + // RFC4515 3 + if ((unsigned char)*i == '*' || (unsigned char)*i == '(' || (unsigned char)*i == ')' || (unsigned char)*i == '\\' || (unsigned char)*i == '\0' || (unsigned char)*i > 127) { + snprintf(tmp, sizeof(tmp), "\\%02x", (unsigned char)*i); + + a += tmp; + } + else + a += *i; } return a; diff --git a/modules/ldapbackend/powerldap.hh b/modules/ldapbackend/powerldap.hh index 4c7e8ff2c0..af970d0d43 100644 --- a/modules/ldapbackend/powerldap.hh +++ b/modules/ldapbackend/powerldap.hh @@ -42,57 +42,57 @@ class LdapAuthenticator; class PowerLDAP { + LDAP* d_ld; + string d_hosts; + int d_port; + bool d_tls; + int d_timeout; + + const string getError(int rc = -1); + int waitResult(int msgid = LDAP_RES_ANY, LDAPMessage** result = NULL); + void ensureConnect(); + +public: + typedef map> sentry_t; + typedef vector sresult_t; + + class SearchResult + { LDAP* d_ld; - string d_hosts; - int d_port; - bool d_tls; - int d_timeout; + int d_msgid; + bool d_finished; - const string getError( int rc = -1 ); - int waitResult( int msgid = LDAP_RES_ANY, LDAPMessage** result = NULL ); - void ensureConnect(); + SearchResult(const SearchResult& other); + SearchResult& operator=(const SearchResult& other); public: - typedef map > sentry_t; - typedef vector sresult_t; - - class SearchResult { - LDAP* d_ld; - int d_msgid; - bool d_finished; - - SearchResult( const SearchResult& other ); - SearchResult& operator=( const SearchResult& other ); - - public: - typedef std::unique_ptr Ptr; - - SearchResult( int msgid, LDAP* ld ); - ~SearchResult(); - - bool getNext( PowerLDAP::sentry_t& entry, bool dn = false, int timeout = 5 ); - void getAll( PowerLDAP::sresult_t& results, bool dn = false, int timeout = 5 ); - }; - - PowerLDAP( const string& hosts, uint16_t port, bool tls, int timeout ); - ~PowerLDAP(); - - bool connect(); - - void getOption( int option, int* value ); - void setOption( int option, int value ); - - void bind( LdapAuthenticator *authenticator ); - void bind( const string& ldapbinddn = "", const string& ldapsecret = "", int method = LDAP_AUTH_SIMPLE ); - void simpleBind( const string& ldapbinddn = "", const string& ldapsecret = "" ); - SearchResult::Ptr search( const string& base, int scope, const string& filter, const char** attr = 0 ); - void add( const string &dn, LDAPMod *mods[] ); - void modify( const string& dn, LDAPMod *mods[], LDAPControl **scontrols = 0, LDAPControl **ccontrols = 0 ); - void del( const string& dn ); - - bool getSearchEntry( int msgid, sentry_t& entry, bool dn = false ); - void getSearchResults( int msgid, sresult_t& result, bool dn = false ); - - static const string escape( const string& tobe ); -}; + typedef std::unique_ptr Ptr; + + SearchResult(int msgid, LDAP* ld); + ~SearchResult(); + + bool getNext(PowerLDAP::sentry_t& entry, bool dn = false, int timeout = 5); + void getAll(PowerLDAP::sresult_t& results, bool dn = false, int timeout = 5); + }; + PowerLDAP(const string& hosts, uint16_t port, bool tls, int timeout); + ~PowerLDAP(); + + bool connect(); + + void getOption(int option, int* value); + void setOption(int option, int value); + + void bind(LdapAuthenticator* authenticator); + void bind(const string& ldapbinddn = "", const string& ldapsecret = "", int method = LDAP_AUTH_SIMPLE); + void simpleBind(const string& ldapbinddn = "", const string& ldapsecret = ""); + SearchResult::Ptr search(const string& base, int scope, const string& filter, const char** attr = 0); + void add(const string& dn, LDAPMod* mods[]); + void modify(const string& dn, LDAPMod* mods[], LDAPControl** scontrols = 0, LDAPControl** ccontrols = 0); + void del(const string& dn); + + bool getSearchEntry(int msgid, sentry_t& entry, bool dn = false); + void getSearchResults(int msgid, sresult_t& result, bool dn = false); + + static const string escape(const string& tobe); +}; diff --git a/modules/ldapbackend/utils.hh b/modules/ldapbackend/utils.hh index 7fc99fbb7e..a2dbad5093 100644 --- a/modules/ldapbackend/utils.hh +++ b/modules/ldapbackend/utils.hh @@ -32,19 +32,16 @@ using std::string; using std::vector; - -inline string ptr2ip4( vector& parts ) +inline string ptr2ip4(vector& parts) { string ip; parts.pop_back(); parts.pop_back(); - ip = parts.back(); parts.pop_back(); - while( !parts.empty() ) - { + while (!parts.empty()) { ip += "." + parts.back(); parts.pop_back(); } @@ -52,41 +49,34 @@ inline string ptr2ip4( vector& parts ) return ip; } - -inline string ptr2ip6( vector& parts ) +inline string ptr2ip6(vector& parts) { int i = 0; string ip; - parts.pop_back(); parts.pop_back(); - while( i < 3 && parts.size() > 1 && parts.back() == "0" ) - { + while (i < 3 && parts.size() > 1 && parts.back() == "0") { parts.pop_back(); i++; } - while( i++ < 4 && !parts.empty() ) - { + while (i++ < 4 && !parts.empty()) { ip += parts.back(); parts.pop_back(); } - while( !parts.empty() ) - { + while (!parts.empty()) { i = 0; ip += ":"; - while( i < 3 && parts.size() > 1 && parts.back() == "0" ) - { + while (i < 3 && parts.size() > 1 && parts.back() == "0") { parts.pop_back(); i++; } - while( i++ < 4 && !parts.empty() ) - { + while (i++ < 4 && !parts.empty()) { ip += parts.back(); parts.pop_back(); } @@ -95,36 +85,31 @@ inline string ptr2ip6( vector& parts ) return ip; } - -inline string ip2ptr4( const string& ip ) +inline string ip2ptr4(const string& ip) { string ptr; vector parts; - stringtok( parts, ip, "." ); - while( !parts.empty() ) - { - ptr += parts.back() + "."; + stringtok(parts, ip, "."); + while (!parts.empty()) { + ptr += parts.back() + "."; parts.pop_back(); } return ptr + "in-addr.arpa"; } - -inline string ip2ptr6( const string& ip ) +inline string ip2ptr6(const string& ip) { string ptr, part, defstr; vector parts; - stringtok( parts, ip, ":" ); - while( !parts.empty() ) - { + stringtok(parts, ip, ":"); + while (!parts.empty()) { defstr = "0.0.0.0."; part = parts.back(); - while( part.length() < 4 ) - { + while (part.length() < 4) { part = "0" + part; } @@ -139,15 +124,12 @@ inline string ip2ptr6( const string& ip ) return ptr + "ip6.arpa"; } - -inline string strbind( const string& search, const string& replace, string subject ) +inline string strbind(const string& search, const string& replace, string subject) { size_t pos = 0; - - while( ( pos = subject.find( search, pos ) ) != string::npos ) - { - subject.replace( pos, search.size(), replace ); + while ((pos = subject.find(search, pos)) != string::npos) { + subject.replace(pos, search.size(), replace); pos += replace.size(); } @@ -158,18 +140,16 @@ inline string strbind( const string& search, const string& replace, string subje * Convert a LDAP time string to a time_t. Return 0 if unable to convert */ -inline time_t str2tstamp( const string& str ) +inline time_t str2tstamp(const string& str) { char* tmp; struct tm tm; - tmp = strptime( str.c_str(), "%Y%m%d%H%M%SZ", &tm ); + tmp = strptime(str.c_str(), "%Y%m%d%H%M%SZ", &tm); - if( tmp != NULL && *tmp == 0 ) - { - return Utility::timegm( &tm ); + if (tmp != NULL && *tmp == 0) { + return Utility::timegm(&tm); } return 0; } - diff --git a/modules/lmdbbackend/lmdbbackend.cc b/modules/lmdbbackend/lmdbbackend.cc index 48bb226e00..bb8bc590a4 100644 --- a/modules/lmdbbackend/lmdbbackend.cc +++ b/modules/lmdbbackend/lmdbbackend.cc @@ -63,26 +63,26 @@ LMDBBackend::LMDBBackend(const std::string& suffix) throw std::runtime_error("LMDB backend does not suport multiple instances"); } - setArgPrefix("lmdb"+suffix); - + setArgPrefix("lmdb" + suffix); + string syncMode = toLower(getArg("sync-mode")); - if(syncMode == "nosync") + if (syncMode == "nosync") d_asyncFlag = MDB_NOSYNC; - else if(syncMode == "nometasync") + else if (syncMode == "nometasync") d_asyncFlag = MDB_NOMETASYNC; - else if(syncMode == "mapasync") + else if (syncMode == "mapasync") d_asyncFlag = MDB_MAPASYNC; - else if(syncMode.empty() || syncMode == "sync") + else if (syncMode.empty() || syncMode == "sync") d_asyncFlag = 0; else - throw std::runtime_error("Unknown sync mode "+syncMode+" requested for LMDB backend"); + throw std::runtime_error("Unknown sync mode " + syncMode + " requested for LMDB backend"); d_tdomains = std::make_shared(getMDBEnv(getArg("filename").c_str(), MDB_NOSUBDIR | d_asyncFlag, 0600), "domains"); d_tmeta = std::make_shared(d_tdomains->getEnv(), "metadata"); d_tkdb = std::make_shared(d_tdomains->getEnv(), "keydata"); d_ttsig = std::make_shared(d_tdomains->getEnv(), "tsig"); - + auto pdnsdbi = d_tdomains->getEnv()->openDB("pdns", MDB_CREATE); if (s_first) { @@ -92,22 +92,22 @@ LMDBBackend::LMDBBackend(const std::string& suffix) uint32_t schemaversion = 1; MDBOutVal _schemaversion; - if(!txn->get(pdnsdbi, "schemaversion", _schemaversion)) { + if (!txn->get(pdnsdbi, "schemaversion", _schemaversion)) { schemaversion = _schemaversion.get(); } if (schemaversion != SCHEMAVERSION) { if (getArgAsNum("schema-version") != SCHEMAVERSION) { - throw std::runtime_error("Expected LMDB schema version "+std::to_string(SCHEMAVERSION)+" but got "+std::to_string(schemaversion)); + throw std::runtime_error("Expected LMDB schema version " + std::to_string(SCHEMAVERSION) + " but got " + std::to_string(schemaversion)); } txn->put(pdnsdbi, "schemaversion", SCHEMAVERSION); } MDBOutVal shards; - if(!txn->get(pdnsdbi, "shards", shards)) { + if (!txn->get(pdnsdbi, "shards", shards)) { s_shards = shards.get(); - if(s_shards != atoi(getArg("shards").c_str())) { - g_log << Logger::Warning<<"Note: configured number of lmdb shards ("< -void save(Archive & ar, const DNSName& g, const unsigned int version) +namespace boost { - if(!g.empty()) { - std::string tmp = g.toDNSStringLC(); // g++ 4.8 woes - ar & tmp; - } - else - ar & ""; -} - -template -void load(Archive & ar, DNSName& g, const unsigned int version) +namespace serialization { - string tmp; - ar & tmp; - if(tmp.empty()) - g = DNSName(); - else - g = DNSName(tmp.c_str(), tmp.size(), 0, false); -} -template -void save(Archive & ar, const QType& g, const unsigned int version) -{ - uint16_t tmp = g.getCode(); // g++ 4.8 woes - ar & tmp; -} + template + void save(Archive& ar, const DNSName& g, const unsigned int version) + { + if (!g.empty()) { + std::string tmp = g.toDNSStringLC(); // g++ 4.8 woes + ar& tmp; + } + else + ar & ""; + } -template -void load(Archive & ar, QType& g, const unsigned int version) -{ - uint16_t tmp; - ar & tmp; - g = QType(tmp); -} - -template -void serialize(Archive & ar, DomainInfo& g, const unsigned int version) -{ - ar & g.zone; - ar & g.last_check; - ar & g.account; - ar & g.masters; - ar & g.id; - ar & g.notified_serial; - ar & g.kind; -} + template + void load(Archive& ar, DNSName& g, const unsigned int version) + { + string tmp; + ar& tmp; + if (tmp.empty()) + g = DNSName(); + else + g = DNSName(tmp.c_str(), tmp.size(), 0, false); + } -template -void serialize(Archive & ar, LMDBBackend::DomainMeta& g, const unsigned int version) -{ - ar & g.domain & g.key & g.value; -} + template + void save(Archive& ar, const QType& g, const unsigned int version) + { + uint16_t tmp = g.getCode(); // g++ 4.8 woes + ar& tmp; + } -template -void save(Archive & ar, const LMDBBackend::KeyDataDB& g, const unsigned int version) -{ - ar & g.domain & g.content & g.flags & g.active & g.published; -} + template + void load(Archive& ar, QType& g, const unsigned int version) + { + uint16_t tmp; + ar& tmp; + g = QType(tmp); + } -template -void load(Archive & ar, LMDBBackend::KeyDataDB& g, const unsigned int version) -{ - ar & g.domain & g.content & g.flags & g.active; - if (version >= 1) { - ar & g.published; - } else { - g.published = true; + template + void serialize(Archive& ar, DomainInfo& g, const unsigned int version) + { + ar& g.zone; + ar& g.last_check; + ar& g.account; + ar& g.masters; + ar& g.id; + ar& g.notified_serial; + ar& g.kind; } -} + template + void serialize(Archive& ar, LMDBBackend::DomainMeta& g, const unsigned int version) + { + ar& g.domain& g.key& g.value; + } -template -void serialize(Archive & ar, TSIGKey& g, const unsigned int version) -{ - ar & g.name; - ar & g.algorithm; // this is the ordername - ar & g.key; -} + template + void save(Archive& ar, const LMDBBackend::KeyDataDB& g, const unsigned int version) + { + ar& g.domain& g.content& g.flags& g.active& g.published; + } + + template + void load(Archive& ar, LMDBBackend::KeyDataDB& g, const unsigned int version) + { + ar& g.domain& g.content& g.flags& g.active; + if (version >= 1) { + ar& g.published; + } + else { + g.published = true; + } + } + template + void serialize(Archive& ar, TSIGKey& g, const unsigned int version) + { + ar& g.name; + ar& g.algorithm; // this is the ordername + ar& g.key; + } - } // namespace serialization } // namespace boost @@ -226,14 +224,14 @@ BOOST_SERIALIZATION_SPLIT_FREE(QType); BOOST_SERIALIZATION_SPLIT_FREE(LMDBBackend::KeyDataDB); BOOST_IS_BITWISE_SERIALIZABLE(ComboAddress); -template<> +template <> std::string serToString(const DNSResourceRecord& rr) { // only does content, ttl, auth std::string ret; uint16_t len = rr.content.length(); - ret.reserve(2+len+8); - + ret.reserve(2 + len + 8); + ret.assign((const char*)&len, 2); ret += rr.content; ret.append((const char*)&rr.ttl, 4); @@ -243,11 +241,11 @@ std::string serToString(const DNSResourceRecord& rr) return ret; } -template<> +template <> std::string serToString(const vector& rrs) { std::string ret; - for(const auto& rr: rrs) { + for (const auto& rr : rrs) { ret += serToString(rr); } @@ -258,7 +256,7 @@ static inline size_t serOneRRFromString(const string_view& str, DNSResourceRecor { uint16_t len; memcpy(&len, &str[0], 2); - rr.content.assign(&str[2], len); // len bytes + rr.content.assign(&str[2], len); // len bytes memcpy(&rr.ttl, &str[2] + len, 4); rr.auth = str[2 + len + 4]; rr.disabled = str[2 + len + 4 + 2]; @@ -267,13 +265,13 @@ static inline size_t serOneRRFromString(const string_view& str, DNSResourceRecor return 2 + len + 7; } -template<> +template <> void serFromString(const string_view& str, DNSResourceRecord& rr) { serOneRRFromString(str, rr); } -template<> +template <> void serFromString(const string_view& str, vector& rrs) { auto str_copy = str; @@ -293,13 +291,12 @@ static std::string serializeContent(uint16_t qtype, const DNSName& domain, const static std::shared_ptr deserializeContentZR(uint16_t qtype, const DNSName& qname, const std::string& content) { - if(qtype == QType::A && content.size() == 4) { + if (qtype == QType::A && content.size() == 4) { return std::make_shared(*((uint32_t*)content.c_str())); } return DNSRecordContent::deserialize(qname, qtype, content); } - /* design. If you ask a question without a zone id, we lookup the best zone id for you, and answer from that. This is different than other backends, but I can't see why it would not work. @@ -323,12 +320,13 @@ void LMDBBackend::deleteDomainRecords(RecordsRWTransaction& txn, uint32_t domain auto cursor = txn.txn->getCursor(txn.db->dbi); MDBOutVal key, val; // cout<<"Match: "<().rfind(match, 0) == 0) { - if(qtype == QType::ANY || co.getQType(key.get()) == qtype) + if (!cursor.lower_bound(match, key, val)) { + while (key.get().rfind(match, 0) == 0) { + if (qtype == QType::ANY || co.getQType(key.get()) == qtype) cursor.del(); - if(cursor.next(key, val)) break; - } + if (cursor.next(key, val)) + break; + } } } @@ -344,26 +342,26 @@ void LMDBBackend::deleteDomainRecords(RecordsRWTransaction& txn, uint32_t domain */ -bool LMDBBackend::startTransaction(const DNSName &domain, int domain_id) +bool LMDBBackend::startTransaction(const DNSName& domain, int domain_id) { // cout <<"startTransaction("<getROTransaction(); DomainInfo di; real_id = rotxn.get<0>(domain, di); // cout<<"real_id = "<= 0) { + if (domain_id >= 0) { deleteDomainRecords(*d_rwtxn, domain_id); } @@ -388,7 +386,7 @@ bool LMDBBackend::abortTransaction() } // d_rwtxn must be set here -bool LMDBBackend::feedRecord(const DNSResourceRecord &r, const DNSName &ordername, bool ordernameIsNSEC3) +bool LMDBBackend::feedRecord(const DNSResourceRecord& r, const DNSName& ordername, bool ordernameIsNSEC3) { DNSResourceRecord rr(r); rr.qname.makeUsRelative(d_transactiondomain); @@ -400,19 +398,19 @@ bool LMDBBackend::feedRecord(const DNSResourceRecord &r, const DNSName &ordernam string rrs; MDBOutVal _rrs; - if(!d_rwtxn->txn->get(d_rwtxn->db->dbi, matchName, _rrs)) { + if (!d_rwtxn->txn->get(d_rwtxn->db->dbi, matchName, _rrs)) { rrs = _rrs.get(); } - + rrs += serToString(rr); d_rwtxn->txn->put(d_rwtxn->db->dbi, matchName, rrs); - if(ordernameIsNSEC3 && !ordername.empty()) { + if (ordernameIsNSEC3 && !ordername.empty()) { MDBOutVal val; - if(d_rwtxn->txn->get(d_rwtxn->db->dbi, co(r.domain_id, rr.qname, QType::NSEC3), val)) { + if (d_rwtxn->txn->get(d_rwtxn->db->dbi, co(r.domain_id, rr.qname, QType::NSEC3), val)) { rr.ttl = 0; - rr.content=rr.qname.toDNSStringLC(); + rr.content = rr.qname.toDNSStringLC(); rr.auth = 0; string ser = serToString(rr); d_rwtxn->txn->put(d_rwtxn->db->dbi, co(r.domain_id, ordername, QType::NSEC3), ser); @@ -426,12 +424,12 @@ bool LMDBBackend::feedRecord(const DNSResourceRecord &r, const DNSName &ordernam return true; } -bool LMDBBackend::feedEnts(int domain_id, map& nonterm) +bool LMDBBackend::feedEnts(int domain_id, map& nonterm) { DNSResourceRecord rr; rr.ttl = 0; compoundOrdername co; - for(const auto& nt: nonterm) { + for (const auto& nt : nonterm) { rr.qname = nt.first.makeRelative(d_transactiondomain); rr.auth = nt.second; rr.disabled = true; @@ -442,13 +440,13 @@ bool LMDBBackend::feedEnts(int domain_id, map& nonterm) return true; } -bool LMDBBackend::feedEnts3(int domain_id, const DNSName &domain, map &nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) +bool LMDBBackend::feedEnts3(int domain_id, const DNSName& domain, map& nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) { string ser; DNSName ordername; DNSResourceRecord rr; compoundOrdername co; - for(const auto& nt: nonterm) { + for (const auto& nt : nonterm) { rr.qname = nt.first.makeRelative(domain); rr.ttl = 0; rr.auth = nt.second; @@ -456,13 +454,13 @@ bool LMDBBackend::feedEnts3(int domain_id, const DNSName &domain, maptxn->put(d_rwtxn->db->dbi, co(domain_id, rr.qname, 0), ser); - if(!narrow && rr.auth) { + if (!narrow && rr.auth) { rr.content = rr.qname.toDNSString(); rr.auth = false; rr.disabled = false; ser = serToString(rr); - ordername=DNSName(toBase32Hex(hashQNameWithSalt(ns3prc, nt.first))); + ordername = DNSName(toBase32Hex(hashQNameWithSalt(ns3prc, nt.first))); d_rwtxn->txn->put(d_rwtxn->db->dbi, co(domain_id, ordername, QType::NSEC3), ser); rr.ttl = 1; @@ -474,14 +472,13 @@ bool LMDBBackend::feedEnts3(int domain_id, const DNSName &domain, map& rrset) { // zonk qname/qtype within domain_id (go through qname, check domain_id && qtype) shared_ptr txn; bool needCommit = false; - if(d_rwtxn && d_transactiondomainid==domain_id) { + if (d_rwtxn && d_transactiondomainid == domain_id) { txn = d_rwtxn; // cout<<"Reusing open transaction"<txn->getCursor(txn->db->dbi); MDBOutVal key, val; - string match =co(domain_id, qname.makeRelative(di.zone), qt.getCode()); - if(!cursor.find(match, key, val)) { + string match = co(domain_id, qname.makeRelative(di.zone), qt.getCode()); + if (!cursor.find(match, key, val)) { cursor.del(); } - if(!rrset.empty()) { + if (!rrset.empty()) { vector adjustedRRSet; - for(auto rr : rrset) { + for (auto rr : rrset) { rr.content = serializeContent(rr.qtype.getCode(), rr.qname, rr.content); rr.qname.makeUsRelative(di.zone); adjustedRRSet.push_back(rr); @@ -514,7 +511,7 @@ bool LMDBBackend::replaceRRSet(uint32_t domain_id, const DNSName& qname, const Q txn->txn->put(txn->db->dbi, match, serToString(adjustedRRSet)); } - if(needCommit) + if (needCommit) txn->txn->commit(); return true; @@ -523,10 +520,10 @@ bool LMDBBackend::replaceRRSet(uint32_t domain_id, const DNSName& qname, const Q // tempting to templatize these two functions but the pain is not worth it std::shared_ptr LMDBBackend::getRecordsRWTransaction(uint32_t id) { - auto& shard =d_trecords[id % s_shards]; - if(!shard.env) { - shard.env = getMDBEnv( (getArg("filename")+"-"+std::to_string(id % s_shards)).c_str(), - MDB_NOSUBDIR | d_asyncFlag, 0600); + auto& shard = d_trecords[id % s_shards]; + if (!shard.env) { + shard.env = getMDBEnv((getArg("filename") + "-" + std::to_string(id % s_shards)).c_str(), + MDB_NOSUBDIR | d_asyncFlag, 0600); shard.dbi = shard.env->openDB("records", MDB_CREATE); } auto ret = std::make_shared(shard.env->getRWTransaction()); @@ -537,21 +534,22 @@ std::shared_ptr LMDBBackend::getRecordsRWTran std::shared_ptr LMDBBackend::getRecordsROTransaction(uint32_t id, std::shared_ptr rwtxn) { - auto& shard =d_trecords[id % s_shards]; - if(!shard.env) { + auto& shard = d_trecords[id % s_shards]; + if (!shard.env) { if (rwtxn) { throw DBException("attempting to start nested transaction without open parent env"); } - shard.env = getMDBEnv( (getArg("filename")+"-"+std::to_string(id % s_shards)).c_str(), - MDB_NOSUBDIR | d_asyncFlag, 0600); + shard.env = getMDBEnv((getArg("filename") + "-" + std::to_string(id % s_shards)).c_str(), + MDB_NOSUBDIR | d_asyncFlag, 0600); shard.dbi = shard.env->openDB("records", MDB_CREATE); } - + if (rwtxn) { auto ret = std::make_shared(rwtxn->txn->getROTransaction()); ret->db = std::make_shared(shard); return ret; - } else { + } + else { auto ret = std::make_shared(shard.env->getROTransaction()); ret->db = std::make_shared(shard); return ret; @@ -560,30 +558,30 @@ std::shared_ptr LMDBBackend::getRecordsROTran bool LMDBBackend::upgradeToSchemav3() { - g_log << Logger::Warning<<"Upgrading LMDB schema"<openDB("records", MDB_CREATE | MDB_DUPSORT); - auto txn = oldShard.env->getROTransaction(); + auto txn = oldShard.env->getROTransaction(); auto cursor = txn->getROCursor(oldShard.dbi); - newShard.env = getMDBEnv( (filename).c_str(), - MDB_NOSUBDIR | d_asyncFlag, 0600); + newShard.env = getMDBEnv((filename).c_str(), + MDB_NOSUBDIR | d_asyncFlag, 0600); newShard.dbi = newShard.env->openDB("records", MDB_CREATE); - auto newTxn = newShard.env->getRWTransaction(); + auto newTxn = newShard.env->getRWTransaction(); MDBOutVal key, val; if (cursor.first(key, val) != 0) { @@ -594,7 +592,7 @@ bool LMDBBackend::upgradeToSchemav3() } string_view currentKey; string value; - for(;;) { + for (;;) { auto newKey = key.get(); if (currentKey.compare(newKey) != 0) { if (value.size() > 0) { @@ -604,7 +602,7 @@ bool LMDBBackend::upgradeToSchemav3() value = ""; } value += val.get(); - if (cursor.next(key, val) != 0){ + if (cursor.next(key, val) != 0) { if (value.size() > 0) { newTxn->put(newShard.dbi, currentKey, value); } @@ -620,18 +618,18 @@ bool LMDBBackend::upgradeToSchemav3() return true; } -bool LMDBBackend::deleteDomain(const DNSName &domain) +bool LMDBBackend::deleteDomain(const DNSName& domain) { auto doms = d_tdomains->getRWTransaction(); DomainInfo di; - auto id = doms.get<0>(domain, di); - if(!id) + auto id = doms.get<0>(domain, di); + if (!id) return false; - + shared_ptr txn; bool needCommit = false; - if(d_rwtxn && d_transactiondomainid == id) { + if (d_rwtxn && d_transactiondomainid == id) { txn = d_rwtxn; // cout<<"Reusing open transaction"<txn->getCursor(txn->db->dbi); MDBOutVal key, val; - if(!cursor.find(match, key, val)) { + if (!cursor.find(match, key, val)) { do { cursor.del(); - } while(!cursor.next(key, val) && key.get().rfind(match, 0) == 0); + } while (!cursor.next(key, val) && key.get().rfind(match, 0) == 0); } - if(needCommit) + if (needCommit) txn->txn->commit(); - + doms.commit(); return true; } -bool LMDBBackend::list(const DNSName &target, int id, bool include_disabled) +bool LMDBBackend::list(const DNSName& target, int id, bool include_disabled) { DomainInfo di; { auto dtxn = d_tdomains->getROTransaction(); - if((di.id = dtxn.get<0>(target, di))) + if ((di.id = dtxn.get<0>(target, di))) ; // cout<<"Found domain "<lower_bound(d_matchkey, key, val) || key.get().rfind(d_matchkey, 0) != 0) { + if (d_getcursor->lower_bound(d_matchkey, key, val) || key.get().rfind(d_matchkey, 0) != 0) { // cout<<"Found nothing for list"<getROTransaction(); - + do { zoneId = rotxn.get<0>(hunt, di); } while (!zoneId && type != QType::SOA && hunt.chopOff()); - if(zoneId <= 0) { + if (zoneId <= 0) { // cout << "Did not find zone for "<< qdomain<getROTransaction().get(zoneId, di)) { + if (!d_tdomains->getROTransaction().get(zoneId, di)) { // cout<<"Could not find a zone with id "<(d_rotxn->txn->getCursor(d_rotxn->db->dbi)); MDBOutVal key, val; - if(type.getCode() == QType::ANY) { + if (type.getCode() == QType::ANY) { d_matchkey = co(zoneId, relqname); } else { - d_matchkey= co(zoneId, relqname, type.getCode()); + d_matchkey = co(zoneId, relqname, type.getCode()); } - - if(d_getcursor->lower_bound(d_matchkey, key, val) || key.get().rfind(d_matchkey, 0) != 0) { + + if (d_getcursor->lower_bound(d_matchkey, key, val) || key.get().rfind(d_matchkey, 0) != 0) { d_getcursor.reset(); - if(d_dolog) { - g_log<(); rr.dr.d_type = compoundOrdername::getQType(key).getCode(); - if(rr.dr.d_type == QType::NSEC3) { + if (rr.dr.d_type == QType::NSEC3) { // Hit a magic NSEC3 skipping - if(d_getcursor->next(d_currentKey, d_currentVal) || d_currentKey.get().rfind(d_matchkey, 0) != 0) { + if (d_getcursor->next(d_currentKey, d_currentVal) || d_currentKey.get().rfind(d_matchkey, 0) != 0) { d_getcursor.reset(); } continue; @@ -786,7 +782,8 @@ bool LMDBBackend::get(DNSZoneRecord& rr) serFromString(d_currentVal.get(), d_currentrrset); d_currentrrsetpos = 0; - } else { + } + else { key = d_currentKey.get(); } @@ -800,13 +797,14 @@ bool LMDBBackend::get(DNSZoneRecord& rr) rr.dr.d_content = deserializeContentZR(rr.dr.d_type, rr.dr.d_name, drr.content); rr.auth = drr.auth; - if(d_currentrrsetpos >= d_currentrrset.size()) { + if (d_currentrrsetpos >= d_currentrrset.size()) { d_currentrrset.clear(); - if(d_getcursor->next(d_currentKey, d_currentVal) || d_currentKey.get().rfind(d_matchkey, 0) != 0) { + if (d_getcursor->next(d_currentKey, d_currentVal) || d_currentKey.get().rfind(d_matchkey, 0) != 0) { d_getcursor.reset(); } } - } catch (const std::exception &e) { + } + catch (const std::exception& e) { throw PDNSException(e.what()); } @@ -816,11 +814,10 @@ bool LMDBBackend::get(DNSZoneRecord& rr) return true; } - bool LMDBBackend::get(DNSResourceRecord& rr) { DNSZoneRecord dzr; - if(!get(dzr)) { + if (!get(dzr)) { return false; } @@ -834,27 +831,26 @@ bool LMDBBackend::get(DNSResourceRecord& rr) return true; } - -bool LMDBBackend::getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial) +bool LMDBBackend::getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial) { auto txn = d_tdomains->getROTransaction(); - if(!(di.id=txn.get<0>(domain, di))) + if (!(di.id = txn.get<0>(domain, di))) return false; di.backend = this; di.serial = 0; - if(getSerial) { + if (getSerial) { auto txn2 = getRecordsROTransaction(di.id); compoundOrdername co; MDBOutVal val; - if(!txn2->txn->get(txn2->db->dbi, co(di.id, g_rootdnsname, QType::SOA), val)) { + if (!txn2->txn->get(txn2->db->dbi, co(di.id, g_rootdnsname, QType::SOA), val)) { DNSResourceRecord rr; serFromString(val.get(), rr); - if(rr.content.size() >= 5 * sizeof(uint32_t)) { + if (rr.content.size() >= 5 * sizeof(uint32_t)) { uint32_t serial; // a SOA has five 32 bit fields, the first of which is the serial // there are two variable length names before the serial, so we calculate from the back @@ -867,7 +863,6 @@ bool LMDBBackend::getDomainInfo(const DNSName &domain, DomainInfo &di, bool getS return true; } - int LMDBBackend::genChangeDomain(const DNSName& domain, std::function func) { auto txn = d_tdomains->getRWTransaction(); @@ -877,7 +872,7 @@ int LMDBBackend::genChangeDomain(const DNSName& domain, std::function(domain, di); func(di); txn.put(di, id); - + txn.commit(); return true; } @@ -888,62 +883,59 @@ int LMDBBackend::genChangeDomain(uint32_t id, std::function f auto txn = d_tdomains->getRWTransaction(); - if(!txn.get(id , di)) + if (!txn.get(id, di)) return false; - + func(di); - + txn.put(di, id); txn.commit(); return true; } - -bool LMDBBackend::setKind(const DNSName &domain, const DomainInfo::DomainKind kind) +bool LMDBBackend::setKind(const DNSName& domain, const DomainInfo::DomainKind kind) { return genChangeDomain(domain, [kind](DomainInfo& di) { - di.kind = kind; - }); + di.kind = kind; + }); } -bool LMDBBackend::setAccount(const DNSName &domain, const std::string& account) +bool LMDBBackend::setAccount(const DNSName& domain, const std::string& account) { return genChangeDomain(domain, [account](DomainInfo& di) { - di.account = account; - }); + di.account = account; + }); } - void LMDBBackend::setFresh(uint32_t domain_id) { genChangeDomain(domain_id, [](DomainInfo& di) { - di.last_check = time(0); - }); + di.last_check = time(0); + }); } void LMDBBackend::setNotified(uint32_t domain_id, uint32_t serial) { genChangeDomain(domain_id, [serial](DomainInfo& di) { - di.serial = serial; - }); + di.serial = serial; + }); } - -bool LMDBBackend::setMasters(const DNSName &domain, const vector &masters) +bool LMDBBackend::setMasters(const DNSName& domain, const vector& masters) { return genChangeDomain(domain, [&masters](DomainInfo& di) { - di.masters = masters; - }); + di.masters = masters; + }); } -bool LMDBBackend::createDomain(const DNSName &domain, const DomainInfo::DomainKind kind, const vector &masters, const string &account) +bool LMDBBackend::createDomain(const DNSName& domain, const DomainInfo::DomainKind kind, const vector& masters, const string& account) { DomainInfo di; auto txn = d_tdomains->getRWTransaction(); - if(txn.get<0>(domain, di)) { - throw DBException("Domain '"+domain.toLogString()+"' exists already"); + if (txn.get<0>(domain, di)) { + throw DBException("Domain '" + domain.toLogString() + "' exists already"); } di.zone = domain; @@ -957,29 +949,30 @@ bool LMDBBackend::createDomain(const DNSName &domain, const DomainInfo::DomainKi return true; } -void LMDBBackend::getAllDomains(vector *domains, bool include_disabled) +void LMDBBackend::getAllDomains(vector* domains, bool include_disabled) { compoundOrdername co; MDBOutVal val; domains->clear(); auto txn = d_tdomains->getROTransaction(); - for(auto iter = txn.begin(); iter != txn.end(); ++iter) { - DomainInfo di=*iter; + for (auto iter = txn.begin(); iter != txn.end(); ++iter) { + DomainInfo di = *iter; di.id = iter.getID(); auto txn2 = getRecordsROTransaction(iter.getID()); - if(!txn2->txn->get(txn2->db->dbi, co(di.id, g_rootdnsname, QType::SOA), val)) { + if (!txn2->txn->get(txn2->db->dbi, co(di.id, g_rootdnsname, QType::SOA), val)) { DNSResourceRecord rr; serFromString(val.get(), rr); - if(rr.content.size() >= 5 * sizeof(uint32_t)) { + if (rr.content.size() >= 5 * sizeof(uint32_t)) { uint32_t serial; // a SOA has five 32 bit fields, the first of which is the serial // there are two variable length names before the serial, so we calculate from the back memcpy(&serial, &rr.content[rr.content.size() - (5 * sizeof(uint32_t))], sizeof(serial)); di.serial = ntohl(serial); } - } else if(!include_disabled) { + } + else if (!include_disabled) { continue; } di.backend = this; @@ -994,22 +987,22 @@ void LMDBBackend::getUnfreshSlaveInfos(vector* domains) auto txn = d_tdomains->getROTransaction(); time_t now = time(0); - for(auto iter = txn.begin(); iter != txn.end(); ++iter) { - if(iter->kind != DomainInfo::Slave) + for (auto iter = txn.begin(); iter != txn.end(); ++iter) { + if (iter->kind != DomainInfo::Slave) continue; auto txn2 = getRecordsROTransaction(iter.getID()); compoundOrdername co; MDBOutVal val; uint32_t serial = 0; - if(!txn2->txn->get(txn2->db->dbi, co(iter.getID(), g_rootdnsname, QType::SOA), val)) { + if (!txn2->txn->get(txn2->db->dbi, co(iter.getID(), g_rootdnsname, QType::SOA), val)) { DNSResourceRecord rr; serFromString(val.get(), rr); struct soatimes st; - - memcpy(&st, &rr.content[rr.content.size()-sizeof(soatimes)], sizeof(soatimes)); - if((time_t)(iter->last_check + ntohl(st.refresh)) >= now) { // still fresh + memcpy(&st, &rr.content[rr.content.size() - sizeof(soatimes)], sizeof(soatimes)); + + if ((time_t)(iter->last_check + ntohl(st.refresh)) >= now) { // still fresh continue; // try next domain } // cout << di.last_check <<" + " < = " << now << "\n"; @@ -1017,9 +1010,9 @@ void LMDBBackend::getUnfreshSlaveInfos(vector* domains) } else { // cout << "Could not find SOA for "<zone<<" with id "<* domains) // cout<<"END of getUnfreshSlaveInfos"< >& meta) +bool LMDBBackend::getAllDomainMetadata(const DNSName& name, std::map>& meta) { meta.clear(); auto txn = d_tmeta->getROTransaction(); auto range = txn.equal_range<0>(name); - - for(auto& iter = range.first; iter != range.second; ++iter) { + + for (auto& iter = range.first; iter != range.second; ++iter) { meta[iter->key].push_back(iter->value); } return true; @@ -1047,25 +1040,24 @@ bool LMDBBackend::setDomainMetadata(const DNSName& name, const std::string& kind auto range = txn.equal_range<0>(name); - for(auto& iter = range.first; iter != range.second; ++iter) { - if(iter-> key == kind) + for (auto& iter = range.first; iter != range.second; ++iter) { + if (iter->key == kind) iter.del(); } - for(const auto& m : meta) { + for (const auto& m : meta) { DomainMeta dm{name, kind, m}; txn.put(dm); } txn.commit(); return true; - } bool LMDBBackend::getDomainKeys(const DNSName& name, std::vector& keys) { auto txn = d_tkdb->getROTransaction(); auto range = txn.equal_range<0>(name); - for(auto& iter = range.first; iter != range.second; ++iter) { + for (auto& iter = range.first; iter != range.second; ++iter) { KeyData kd{iter->content, iter.getID(), iter->flags, iter->active, iter->published}; keys.push_back(kd); } @@ -1077,8 +1069,8 @@ bool LMDBBackend::removeDomainKey(const DNSName& name, unsigned int id) { auto txn = d_tkdb->getRWTransaction(); KeyDataDB kdb; - if(txn.get(id, kdb)) { - if(kdb.domain == name) { + if (txn.get(id, kdb)) { + if (kdb.domain == name) { txn.del(id); txn.commit(); return true; @@ -1094,7 +1086,7 @@ bool LMDBBackend::addDomainKey(const DNSName& name, const KeyData& key, int64_t& KeyDataDB kdb{name, key.content, key.flags, key.active, key.published}; id = txn.put(kdb); txn.commit(); - + return true; } @@ -1102,12 +1094,11 @@ bool LMDBBackend::activateDomainKey(const DNSName& name, unsigned int id) { auto txn = d_tkdb->getRWTransaction(); KeyDataDB kdb; - if(txn.get(id, kdb)) { - if(kdb.domain == name) { - txn.modify(id, [](KeyDataDB& kdbarg) - { - kdbarg.active = true; - }); + if (txn.get(id, kdb)) { + if (kdb.domain == name) { + txn.modify(id, [](KeyDataDB& kdbarg) { + kdbarg.active = true; + }); txn.commit(); return true; } @@ -1121,12 +1112,11 @@ bool LMDBBackend::deactivateDomainKey(const DNSName& name, unsigned int id) { auto txn = d_tkdb->getRWTransaction(); KeyDataDB kdb; - if(txn.get(id, kdb)) { - if(kdb.domain == name) { - txn.modify(id, [](KeyDataDB& kdbarg) - { - kdbarg.active = false; - }); + if (txn.get(id, kdb)) { + if (kdb.domain == name) { + txn.modify(id, [](KeyDataDB& kdbarg) { + kdbarg.active = false; + }); txn.commit(); return true; } @@ -1139,12 +1129,11 @@ bool LMDBBackend::publishDomainKey(const DNSName& name, unsigned int id) { auto txn = d_tkdb->getRWTransaction(); KeyDataDB kdb; - if(txn.get(id, kdb)) { - if(kdb.domain == name) { - txn.modify(id, [](KeyDataDB& kdbarg) - { - kdbarg.published = true; - }); + if (txn.get(id, kdb)) { + if (kdb.domain == name) { + txn.modify(id, [](KeyDataDB& kdbarg) { + kdbarg.published = true; + }); txn.commit(); return true; } @@ -1158,12 +1147,11 @@ bool LMDBBackend::unpublishDomainKey(const DNSName& name, unsigned int id) { auto txn = d_tkdb->getRWTransaction(); KeyDataDB kdb; - if(txn.get(id, kdb)) { - if(kdb.domain == name) { - txn.modify(id, [](KeyDataDB& kdbarg) - { - kdbarg.published = false; - }); + if (txn.get(id, kdb)) { + if (kdb.domain == name) { + txn.modify(id, [](KeyDataDB& kdbarg) { + kdbarg.published = false; + }); txn.commit(); return true; } @@ -1172,18 +1160,17 @@ bool LMDBBackend::unpublishDomainKey(const DNSName& name, unsigned int id) return true; } - -bool LMDBBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) +bool LMDBBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) { // cout << __PRETTY_FUNCTION__<< ": "<getROTransaction().get(id, di)) { + if (!d_tdomains->getROTransaction().get(id, di)) { // domain does not exist, tough luck return false; } // cout <<"Zone: "<()) != id) { + for (;;) { + if (co.getDomainID(key.get()) != id) { //cout<<"Last record also not part of this zone!"<()) == QType::NSEC3) { + + if (co.getQType(key.get()) == QType::NSEC3) { serFromString(val.get(), rr); - if(!rr.ttl) // the kind of NSEC3 we need + if (!rr.ttl) // the kind of NSEC3 we need break; } - if(cursor.prev(key, val)) { + if (cursor.prev(key, val)) { // hit beginning of database, again means something is wrong with it return false; } @@ -1219,18 +1206,18 @@ bool LMDBBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna unhashed = DNSName(rr.content.c_str(), rr.content.size(), 0, false) + di.zone; // now to find after .. at the beginning of the zone - if(cursor.lower_bound(co(id), key, val)) { + if (cursor.lower_bound(co(id), key, val)) { // cout<<"hit end of zone find when we shouldn't"<()) == QType::NSEC3) { + for (;;) { + if (co.getQType(key.get()) == QType::NSEC3) { serFromString(val.get(), rr); - if(!rr.ttl) + if (!rr.ttl) break; } - if(cursor.next(key, val) || co.getDomainID(key.get()) != id) { + if (cursor.next(key, val) || co.getDomainID(key.get()) != id) { // cout<<"hit end of zone or database when we shouldn't"<()) <()); - if(before == qname) { + if (before == qname) { // cout << "Ended up on exact right node" << endl; before = co.getQName(key.get()); // unhashed should be correct now, maybe check? - if(cursor.next(key, val)) { + if (cursor.next(key, val)) { // xxx should find first hash now - if(cursor.lower_bound(co(id), key, val)) { + if (cursor.lower_bound(co(id), key, val)) { // cout<<"hit end of zone find when we shouldn't for id "<()) == QType::NSEC3) { + for (;;) { + if (co.getQType(key.get()) == QType::NSEC3) { serFromString(val.get(), rr); - if(!rr.ttl) + if (!rr.ttl) break; } - - if(cursor.next(key, val) || co.getDomainID(key.get()) != id) { + + if (cursor.next(key, val) || co.getDomainID(key.get()) != id) { // cout<<"hit end of zone or database when we shouldn't" << __LINE__<()).canonCompare(qname) && co.getQType(key.get()) == QType::NSEC3) { + int count = 0; + for (;;) { + if (co.getQName(key.get()).canonCompare(qname) && co.getQType(key.get()) == QType::NSEC3) { // cout<<"Potentially stopping traverse at "<< co.getQName(key.get()) <<", " << (co.getQName(key.get()).canonCompare(qname))<()) != id) { + for (;;) { + if (co.getDomainID(key.get()) != id) { //cout<<"Last record also not part of this zone!"<()) == QType::NSEC3) { + + if (co.getQType(key.get()) == QType::NSEC3) { serFromString(val.get(), rr); - if(!rr.ttl) // the kind of NSEC3 we need + if (!rr.ttl) // the kind of NSEC3 we need break; } - if(cursor.prev(key, val)) { + if (cursor.prev(key, val)) { // hit beginning of database, again means something is wrong with it return false; } @@ -1318,19 +1305,19 @@ bool LMDBBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna // cout <<"Should still find 'after'!"<()) == QType::NSEC3) { + for (;;) { + if (co.getQType(key.get()) == QType::NSEC3) { serFromString(val.get(), rr); - if(!rr.ttl) + if (!rr.ttl) break; } - - if(cursor.next(key, val)) { + + if (cursor.next(key, val)) { // means database is wrong, nothing we can do // cout<<"hit end of zone when we shouldn't 2"<()); - // cout<<"returning: before="<()) != id ) { + for (int count = 0;; ++count) { + if ((count && cursor.next(key, val)) || co.getDomainID(key.get()) != id) { // cout <<"Hit end of database or zone, finding first hash then in zone "<()) == QType::NSEC3) { + for (;;) { + if (co.getQType(key.get()) == QType::NSEC3) { serFromString(val.get(), rr); - if(!rr.ttl) + if (!rr.ttl) break; } - - if(cursor.next(key, val)) { + + if (cursor.next(key, val)) { // means database is wrong, nothing we can do // cout<<"hit end of zone when we shouldn't 2"<()); - + // cout<<"returning: before="<()) <()) == QType::NSEC3) { + if (co.getQType(key.get()) == QType::NSEC3) { serFromString(val.get(), rr); - if(!rr.ttl) { + if (!rr.ttl) { break; } } @@ -1401,68 +1387,68 @@ bool LMDBBackend::getBeforeAndAfterNames(uint32_t id, const DNSName& zonenameU, auto txn = getRecordsROTransaction(id); compoundOrdername co; DNSName qname2 = qname.makeRelative(zonename); - string matchkey=co(id,qname2); + string matchkey = co(id, qname2); auto cursor = txn->txn->getCursor(txn->db->dbi); MDBOutVal key, val; // cout<<"Lower_bound for "<()) == id) { + if (co.getDomainID(key.get()) == id) { before = co.getQName(key.get()) + zonename; after = zonename; } // else - // cout << "We were at end of database, but this zone is not there?!"<()) <<", in zone id "<())<< endl; - if(co.getQType(key.get()).getCode() && co.getDomainID(key.get()) ==id && co.getQName(key.get()) == qname2) { // don't match ENTs + if (co.getQType(key.get()).getCode() && co.getDomainID(key.get()) == id && co.getQName(key.get()) == qname2) { // don't match ENTs // cout << "Had an exact match!"<()) == id && key.get().rfind(matchkey, 0)==0) + for (;;) { + rc = cursor.next(key, val); + if (rc) + break; + + if (co.getDomainID(key.get()) == id && key.get().rfind(matchkey, 0) == 0) continue; DNSResourceRecord rr; serFromString(val.get(), rr); - if(co.getQType(key.get()).getCode() && (rr.auth || co.getQType(key.get()).getCode() == QType::NS)) + if (co.getQType(key.get()).getCode() && (rr.auth || co.getQType(key.get()).getCode() == QType::NS)) break; } - if(rc || co.getDomainID(key.get()) != id) { + if (rc || co.getDomainID(key.get()) != id) { // cout << "We hit the end of the zone or database. 'after' is apex" << endl; - after=zonename; + after = zonename; return false; } after = co.getQName(key.get()) + zonename; return true; } - - if(co.getDomainID(key.get()) != id) { + if (co.getDomainID(key.get()) != id) { // cout << "Ended up in next zone, 'after' is zonename" <()) != id) { + + if (co.getDomainID(key.get()) != id) { // cout<<"Reversed into zone, but found wrong zone id " << co.getDomainID(key.get()) << " != "<(), rr); - if(co.getQType(key.get()).getCode() && (rr.auth || co.getQType(key.get()).getCode() == QType::NS)) + if (co.getQType(key.get()).getCode() && (rr.auth || co.getQType(key.get()).getCode() == QType::NS)) break; } @@ -1474,10 +1460,10 @@ bool LMDBBackend::getBeforeAndAfterNames(uint32_t id, const DNSName& zonenameU, // cout <<"We ended up after "<())<(), rr); - if(co.getQType(key.get()).getCode() && (rr.auth || co.getQType(key.get()).getCode() == QType::NS)) { + if (co.getQType(key.get()).getCode() && (rr.auth || co.getQType(key.get()).getCode() == QType::NS)) { after = co.getQName(key.get()) + zonename; // cout <<"Found auth ("<()).getName()<<", ttl = "<()) << endl; @@ -1485,21 +1471,21 @@ bool LMDBBackend::getBeforeAndAfterNames(uint32_t id, const DNSName& zonenameU, } // cout <<" oops, " << co.getQName(key.get()) << " was not auth "<()) != id ) { + if (rc || co.getDomainID(key.get()) != id) { // cout << " oops, hit end of database or zone. This means after is apex" <()) != id) { + if (rc || co.getDomainID(key.get()) != id) { // XX I don't think this case can happen // cout << "We hit the beginning of the zone or database.. now what" << endl; return false; @@ -1508,13 +1494,12 @@ bool LMDBBackend::getBeforeAndAfterNames(uint32_t id, const DNSName& zonenameU, DNSResourceRecord rr; serFromString(val.get(), rr); // cout<<"And before to "< txn; bool needCommit = false; - if(d_rwtxn && d_transactiondomainid==domain_id) { + if (d_rwtxn && d_transactiondomainid == domain_id) { txn = d_rwtxn; // cout<<"Reusing open transaction"<getROTransaction().get(domain_id, di)) { + if (!d_tdomains->getROTransaction().get(domain_id, di)) { // cout<<"Could not find domain_id "<txn->getCursor(txn->db->dbi); MDBOutVal key, val; - if(cursor.lower_bound(matchkey, key, val)) { + if (cursor.lower_bound(matchkey, key, val)) { // cout << "Could not find anything"<().rfind(matchkey,0) == 0; ) { + for (; key.get().rfind(matchkey, 0) == 0;) { vector rrs; - if(co.getQType(key.get()) != QType::NSEC3) { + if (co.getQType(key.get()) != QType::NSEC3) { serFromString(val.get(), rrs); bool changed = false; vector newRRs; - for(auto rr: rrs) { + for (auto rr : rrs) { rr.qtype = co.getQType(key.get()); - if(!needNSEC3 && qtype != QType::ANY) { + if (!needNSEC3 && qtype != QType::ANY) { needNSEC3 = (rr.disabled && QType(qtype) != rr.qtype); } - if((qtype == QType::ANY || QType(qtype) == rr.qtype) && (rr.disabled != hasOrderName || rr.auth != auth)) { + if ((qtype == QType::ANY || QType(qtype) == rr.qtype) && (rr.disabled != hasOrderName || rr.auth != auth)) { rr.auth = auth; rr.disabled = hasOrderName; changed = true; @@ -1580,58 +1565,60 @@ bool LMDBBackend::updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName } } - if(cursor.next(key, val)) + if (cursor.next(key, val)) break; } bool del = false; DNSResourceRecord rr; - matchkey = co(domain_id,rel,QType::NSEC3); - if(!txn->txn->get(txn->db->dbi, matchkey, val)) { + matchkey = co(domain_id, rel, QType::NSEC3); + if (!txn->txn->get(txn->db->dbi, matchkey, val)) { serFromString(val.get(), rr); - if(needNSEC3) { - if(hasOrderName && rr.content != ordername.toDNSStringLC()) { - del = true; + if (needNSEC3) { + if (hasOrderName && rr.content != ordername.toDNSStringLC()) { + del = true; } - } else { + } + else { del = true; } - if(del) { + if (del) { txn->txn->del(txn->db->dbi, co(domain_id, DNSName(rr.content.c_str(), rr.content.size(), 0, false), QType::NSEC3)); txn->txn->del(txn->db->dbi, matchkey); } - } else { + } + else { del = true; } - if(hasOrderName && del) { - matchkey = co(domain_id,rel,QType::NSEC3); + if (hasOrderName && del) { + matchkey = co(domain_id, rel, QType::NSEC3); - rr.ttl=0; - rr.auth=0; - rr.content=rel.toDNSStringLC(); + rr.ttl = 0; + rr.auth = 0; + rr.content = rel.toDNSStringLC(); string str = serToString(rr); - txn->txn->put(txn->db->dbi, co(domain_id,ordername,QType::NSEC3), str); + txn->txn->put(txn->db->dbi, co(domain_id, ordername, QType::NSEC3), str); rr.ttl = 1; rr.content = ordername.toDNSStringLC(); str = serToString(rr); - txn->txn->put(txn->db->dbi, matchkey, str); // 2 + txn->txn->put(txn->db->dbi, matchkey, str); // 2 } - if(needCommit) + if (needCommit) txn->txn->commit(); return false; } -bool LMDBBackend::updateEmptyNonTerminals(uint32_t domain_id, set& insert, set& erase, bool remove) +bool LMDBBackend::updateEmptyNonTerminals(uint32_t domain_id, set& insert, set& erase, bool remove) { // cout << __PRETTY_FUNCTION__<< ": "<< domain_id << ", insert.size() "< txn; - if(d_rwtxn && d_transactiondomainid == domain_id) { + if (d_rwtxn && d_transactiondomainid == domain_id) { txn = d_rwtxn; // cout<<"Reusing open transaction"<& inse needCommit = true; } - // if remove is set, all ENTs should be removed & nothing else should be done - if(remove) { + if (remove) { deleteDomainRecords(*txn, domain_id, 0); } else { DomainInfo di; auto rotxn = d_tdomains->getROTransaction(); - if(!rotxn.get(domain_id, di)) { + if (!rotxn.get(domain_id, di)) { // cout <<"No such domain with id "<& inse DNSResourceRecord rr2; serFromString(ser, rr2); - + // cout <<" +"<txn->del(txn->db->dbi, co(domain_id, n, 0)); } } - if(needCommit) + if (needCommit) txn->txn->commit(); return false; } @@ -1686,33 +1672,32 @@ bool LMDBBackend::getTSIGKey(const DNSName& name, DNSName* algorithm, string* co auto txn = d_ttsig->getROTransaction(); TSIGKey tk; - if(!txn.get<0>(name, tk)) + if (!txn.get<0>(name, tk)) return false; - if(algorithm) + if (algorithm) *algorithm = tk.algorithm; - if(content) + if (content) *content = tk.key; return true; - } // this deletes an old key if it has the same algorithm bool LMDBBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) { auto txn = d_ttsig->getRWTransaction(); - for(auto range = txn.equal_range<0>(name); range.first != range.second; ++range.first) { - if(range.first->algorithm == algorithm) + for (auto range = txn.equal_range<0>(name); range.first != range.second; ++range.first) { + if (range.first->algorithm == algorithm) range.first.del(); } TSIGKey tk; tk.name = name; tk.algorithm = algorithm; - tk.key=content; - + tk.key = content; + txn.put(tk); txn.commit(); - + return true; } bool LMDBBackend::deleteTSIGKey(const DNSName& name) @@ -1720,47 +1705,42 @@ bool LMDBBackend::deleteTSIGKey(const DNSName& name) auto txn = d_ttsig->getRWTransaction(); TSIGKey tk; - for(auto range = txn.equal_range<0>(name); range.first != range.second; ++range.first) { + for (auto range = txn.equal_range<0>(name); range.first != range.second; ++range.first) { range.first.del(); } txn.commit(); return true; } -bool LMDBBackend::getTSIGKeys(std::vector< struct TSIGKey > &keys) +bool LMDBBackend::getTSIGKeys(std::vector& keys) { auto txn = d_ttsig->getROTransaction(); keys.clear(); - for(auto iter = txn.begin(); iter != txn.end(); ++iter) { + for (auto iter = txn.begin(); iter != txn.end(); ++iter) { keys.push_back(*iter); } return false; } - - - class LMDBFactory : public BackendFactory { public: - LMDBFactory() : BackendFactory("lmdb") {} - void declareArguments(const string &suffix="") override + LMDBFactory() : + BackendFactory("lmdb") {} + void declareArguments(const string& suffix = "") override { - declare(suffix,"filename","Filename for lmdb","./pdns.lmdb"); - declare(suffix,"sync-mode","Synchronisation mode: nosync, nometasync, mapasync, sync","mapasync"); + declare(suffix, "filename", "Filename for lmdb", "./pdns.lmdb"); + declare(suffix, "sync-mode", "Synchronisation mode: nosync, nometasync, mapasync, sync", "mapasync"); // there just is no room for more on 32 bit - declare(suffix,"shards","Records database will be split into this number of shards", (sizeof(long) == 4) ? "2" : "64"); - declare(suffix,"schema-version","Maximum allowed schema version to run on this DB. If a lower version is found, auto update is performed", std::to_string(SCHEMAVERSION)); + declare(suffix, "shards", "Records database will be split into this number of shards", (sizeof(long) == 4) ? "2" : "64"); + declare(suffix, "schema-version", "Maximum allowed schema version to run on this DB. If a lower version is found, auto update is performed", std::to_string(SCHEMAVERSION)); } - DNSBackend *make(const string &suffix="") override + DNSBackend* make(const string& suffix = "") override { return new LMDBBackend(suffix); } }; - - - /* THIRD PART */ class LMDBLoader @@ -1771,10 +1751,10 @@ public: BackendMakers().report(new LMDBFactory); g_log << Logger::Info << "[lmdbbackend] This is the lmdb backend version " VERSION #ifndef REPRODUCIBLE - << " (" __DATE__ " " __TIME__ ")" + << " (" __DATE__ " " __TIME__ ")" #endif - << " reporting" << endl; - } + << " reporting" << endl; + } }; static LMDBLoader randomLoader; diff --git a/modules/lmdbbackend/lmdbbackend.hh b/modules/lmdbbackend/lmdbbackend.hh index c06779075f..02e30497f9 100644 --- a/modules/lmdbbackend/lmdbbackend.hh +++ b/modules/lmdbbackend/lmdbbackend.hh @@ -24,7 +24,7 @@ #include "pdns/dnsbackend.hh" #include "ext/lmdb-safe/lmdb-typed.hh" -template::value,T>::type* = nullptr> +template ::value, T>::type* = nullptr> std::string keyConv(const T& t) { /* www.ds9a.nl -> nl0ds9a0www0 @@ -32,62 +32,61 @@ std::string keyConv(const T& t) nl -> nl0 */ - if(t.isRoot()) + if (t.isRoot()) return std::string(1, (char)0); std::string in = t.labelReverse().toDNSStringLC(); // www.ds9a.nl is now 2nl4ds9a3www0 std::string ret; ret.reserve(in.size()); - - for(auto iter = in.begin(); iter != in.end(); ++iter) { + + for (auto iter = in.begin(); iter != in.end(); ++iter) { uint8_t len = *iter; - if(iter != in.begin()) + if (iter != in.begin()) ret.append(1, (char)0); - if(!len) + if (!len) break; - ret.append(&*(iter+1), len); - iter+=len; + ret.append(&*(iter + 1), len); + iter += len; } return ret; } - class LMDBBackend : public DNSBackend { public: - explicit LMDBBackend(const string &suffix=""); + explicit LMDBBackend(const string& suffix = ""); - bool list(const DNSName &target, int id, bool include_disabled) override; + bool list(const DNSName& target, int id, bool include_disabled) override; - bool getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial=true) override; - bool createDomain(const DNSName &domain, const DomainInfo::DomainKind kind, const vector &masters, const string &account) override; + bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial = true) override; + bool createDomain(const DNSName& domain, const DomainInfo::DomainKind kind, const vector& masters, const string& account) override; - bool startTransaction(const DNSName &domain, int domain_id=-1) override; + bool startTransaction(const DNSName& domain, int domain_id = -1) override; bool commitTransaction() override; bool abortTransaction() override; - bool feedRecord(const DNSResourceRecord &r, const DNSName &ordername, bool ordernameIsNSEC3=false) override; - bool feedEnts(int domain_id, map& nonterm) override; - bool feedEnts3(int domain_id, const DNSName &domain, map &nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) override; + bool feedRecord(const DNSResourceRecord& r, const DNSName& ordername, bool ordernameIsNSEC3 = false) override; + bool feedEnts(int domain_id, map& nonterm) override; + bool feedEnts3(int domain_id, const DNSName& domain, map& nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) override; bool replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector& rrset) override; - void getAllDomains(vector *domains, bool include_disabled=false) override; - void lookup(const QType &type, const DNSName &qdomain, int zoneId, DNSPacket *p=nullptr) override; - bool get(DNSResourceRecord &rr) override; + void getAllDomains(vector* domains, bool include_disabled = false) override; + void lookup(const QType& type, const DNSName& qdomain, int zoneId, DNSPacket* p = nullptr) override; + bool get(DNSResourceRecord& rr) override; bool get(DNSZoneRecord& dzr) override; void getUnfreshSlaveInfos(vector* domains) override; - - bool setMasters(const DNSName &domain, const vector &masters) override; - bool setKind(const DNSName &domain, const DomainInfo::DomainKind kind) override; - bool getAllDomainMetadata(const DNSName& name, std::map >& meta) override; + + bool setMasters(const DNSName& domain, const vector& masters) override; + bool setKind(const DNSName& domain, const DomainInfo::DomainKind kind) override; + bool getAllDomainMetadata(const DNSName& name, std::map>& meta) override; bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) override { // std::cout<<"Request for metadata items for zone "< > metas; - if(getAllDomainMetadata(name, metas)) { - for(const auto& m : metas) { - if(m.first == kind) { + std::map> metas; + if (getAllDomainMetadata(name, metas)) { + for (const auto& m : metas) { + if (m.first == kind) { meta = m.second; return true; } @@ -100,8 +99,8 @@ public: bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) override; void setFresh(uint32_t domain_id) override; void setNotified(uint32_t id, uint32_t serial) override; - bool setAccount(const DNSName &domain, const std::string& account) override; - bool deleteDomain(const DNSName &domain) override; + bool setAccount(const DNSName& domain, const std::string& account) override; + bool deleteDomain(const DNSName& domain) override; bool getDomainKeys(const DNSName& name, std::vector& keys) override; bool removeDomainKey(const DNSName& name, unsigned int id) override; @@ -115,16 +114,15 @@ public: bool getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) override; bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) override; bool deleteTSIGKey(const DNSName& name) override; - bool getTSIGKeys(std::vector< struct TSIGKey > &keys) override; + bool getTSIGKeys(std::vector& keys) override; - // DNSSEC bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) override; virtual bool getBeforeAndAfterNames(uint32_t id, const DNSName& zonename, const DNSName& qname, DNSName& before, DNSName& after) override; - bool updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName& qname, const DNSName& ordername, bool auth, const uint16_t qtype=QType::ANY) override; + bool updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName& qname, const DNSName& ordername, bool auth, const uint16_t qtype = QType::ANY) override; bool updateEmptyNonTerminals(uint32_t domain_id, set& insert, set& erase, bool remove) override; @@ -132,8 +130,8 @@ public: { return true; } -private: +private: struct compoundOrdername { std::string operator()(uint32_t id, const DNSName& t, uint16_t qtype) @@ -178,19 +176,19 @@ private: DNSName ret; auto iter = key.cbegin() + 4; auto end = key.cend() - 2; - while(iter < end) { + while (iter < end) { auto startpos = iter; - while(iter != end && *iter) + while (iter != end && *iter) ++iter; - if(iter == startpos) + if (iter == startpos) break; - string part(&*startpos, iter-startpos); + string part(&*startpos, iter - startpos); ret.prependRawLabel(part); // cout << "Prepending part: "< - > tdomains_t; + index_on> + tdomains_t; - typedef TypedDBI - > tmeta_t; - + index_on> + tmeta_t; + typedef TypedDBI - > tkdb_t; + index_on> + tkdb_t; typedef TypedDBI - > ttsig_t; - + index_on> + ttsig_t; + int d_asyncFlag; struct RecordsDB @@ -248,20 +244,23 @@ private: struct RecordsROTransaction { - RecordsROTransaction(MDBROTransaction&& intxn) : txn(std::move(intxn)) + RecordsROTransaction(MDBROTransaction&& intxn) : + txn(std::move(intxn)) {} shared_ptr db; MDBROTransaction txn; }; struct RecordsRWTransaction { - RecordsRWTransaction(MDBRWTransaction&& intxn) : txn(std::move(intxn)) + RecordsRWTransaction(MDBRWTransaction&& intxn) : + txn(std::move(intxn)) {} shared_ptr db; MDBRWTransaction txn; }; - vector d_trecords;; + vector d_trecords; + ; std::shared_ptr d_getcursor; @@ -269,19 +268,19 @@ private: shared_ptr d_tmeta; shared_ptr d_tkdb; shared_ptr d_ttsig; - + shared_ptr d_rotxn; // for lookup and list shared_ptr d_rwtxn; // for feedrecord within begin/aborttransaction std::shared_ptr getRecordsRWTransaction(uint32_t id); std::shared_ptr getRecordsROTransaction(uint32_t id, std::shared_ptr rwtxn = nullptr); int genChangeDomain(const DNSName& domain, std::function func); int genChangeDomain(uint32_t id, std::function func); - void deleteDomainRecords(RecordsRWTransaction& txn, uint32_t domain_id, uint16_t qtype=QType::ANY); + void deleteDomainRecords(RecordsRWTransaction& txn, uint32_t domain_id, uint16_t qtype = QType::ANY); bool upgradeToSchemav3(); - - bool get_list(DNSZoneRecord &rr); - bool get_lookup(DNSZoneRecord &rr); + + bool get_list(DNSZoneRecord& rr); + bool get_lookup(DNSZoneRecord& rr); std::string d_matchkey; DNSName d_lookupdomain; @@ -289,7 +288,7 @@ private: size_t d_currentrrsetpos; MDBOutVal d_currentKey; MDBOutVal d_currentVal; - + DNSName d_transactiondomain; uint32_t d_transactiondomainid; bool d_dolog; diff --git a/modules/lua2backend/lua2api2.cc b/modules/lua2backend/lua2api2.cc index df53d46b37..d9a2304aba 100644 --- a/modules/lua2backend/lua2api2.cc +++ b/modules/lua2backend/lua2api2.cc @@ -24,7 +24,8 @@ #endif #include "lua2backend.hh" -Lua2BackendAPIv2::~Lua2BackendAPIv2() { +Lua2BackendAPIv2::~Lua2BackendAPIv2() +{ if (f_deinit) f_deinit(); } diff --git a/modules/lua2backend/lua2api2.hh b/modules/lua2backend/lua2api2.hh index d61ee11805..a1bab41b68 100644 --- a/modules/lua2backend/lua2api2.hh +++ b/modules/lua2backend/lua2api2.hh @@ -24,45 +24,48 @@ #include "boost/algorithm/string/join.hpp" #include "pdns/arguments.hh" -class Lua2BackendAPIv2 : public DNSBackend, AuthLua4 { +class Lua2BackendAPIv2 : public DNSBackend, AuthLua4 +{ private: typedef std::function init_call_t; typedef std::function deinit_call_t; - typedef std::vector > lookup_context_t; + typedef std::vector> lookup_context_t; - typedef std::vector > > > > lookup_result_t; - typedef std::function lookup_call_t; + typedef std::vector>>>> lookup_result_t; + typedef std::function lookup_call_t; typedef boost::variant list_result_t; typedef std::function list_call_t; - typedef vector > > > domaininfo_result_t; + typedef vector>>> domaininfo_result_t; typedef boost::variant get_domaininfo_result_t; - typedef vector > get_all_domains_result_t; + typedef vector> get_all_domains_result_t; typedef std::function get_domaininfo_call_t; typedef std::function get_all_domains_call_t; - typedef vector > domain_metadata_result_t; + typedef vector> domain_metadata_result_t; typedef boost::variant get_domain_metadata_result_t; - typedef boost::variant > > get_all_domain_metadata_result_t; + typedef boost::variant>> get_all_domain_metadata_result_t; typedef std::function get_domain_metadata_call_t; typedef std::function get_all_domain_metadata_call_t; - typedef vector > > keydata_result_t; - typedef boost::variant > > get_domain_keys_result_t; + typedef vector>> keydata_result_t; + typedef boost::variant>> get_domain_keys_result_t; typedef std::function get_domain_keys_call_t; - typedef std::vector > > before_and_after_names_result_t; + typedef std::vector>> before_and_after_names_result_t; typedef boost::variant get_before_and_after_names_absolute_result_t; typedef std::function get_before_and_after_names_absolute_call_t; typedef std::function set_notified_call_t; typedef std::function direct_backend_cmd_call_t; + public: - Lua2BackendAPIv2(const string& suffix) { - setArgPrefix("lua2"+suffix); + Lua2BackendAPIv2(const string& suffix) + { + setArgPrefix("lua2" + suffix); d_debug_log = mustDo("query-logging"); prepareContext(); loadFile(getArg("filename")); @@ -70,14 +73,27 @@ public: ~Lua2BackendAPIv2(); - #define logCall(func, var) { if (d_debug_log) { g_log<readVariable>("dns_lookup").get_value_or(0); f_list = d_lw->readVariable>("dns_list").get_value_or(0); f_get_all_domains = d_lw->readVariable>("dns_get_all_domains").get_value_or(0); @@ -106,35 +122,39 @@ public: throw PDNSException("dns_dnssec is true but dns_get_before_and_after_names_absolute is missing"); /* domain keys is not strictly speaking necessary for dnssec backend */ if (f_get_domain_keys == nullptr) - g_log<(item.second)); - else if (item.second.which() == 3) - rec.qtype = boost::get(item.second); - else if (item.second.which() == 4) - rec.qtype = boost::get(item.second); - else - throw PDNSException("Unsupported value for type"); - } else if (item.first == "name") { + for (const auto& item : row.second) { + if (item.first == "type") { + if (item.second.which() == 1) + rec.qtype = QType(boost::get(item.second)); + else if (item.second.which() == 3) + rec.qtype = boost::get(item.second); + else if (item.second.which() == 4) + rec.qtype = boost::get(item.second); + else + throw PDNSException("Unsupported value for type"); + } + else if (item.first == "name") { if (item.second.which() == 3) rec.qname = DNSName(boost::get(item.second)); else if (item.second.which() == 2) rec.qname = boost::get(item.second); else throw PDNSException("Unsupported value for name"); - } else if (item.first == "domain_id") + } + else if (item.first == "domain_id") rec.domain_id = boost::get(item.second); else if (item.first == "auth") rec.auth = boost::get(item.second); @@ -147,26 +167,26 @@ public: else if (item.first == "scopeMask") rec.scopeMask = boost::get(item.second); else - g_log<getRealRemote().toString()}); } - logCall("lookup", "qtype="<readVariable>(cmd).get_value_or(0); if (f == nullptr) { return cmd + "not found"; } - logCall(cmd, "parameter="<(item.second); - else if (item.first == "last_check") - di.last_check = static_cast(boost::get(item.second)); - else if (item.first == "masters") - for(const auto& master: boost::get>(item.second)) - di.masters.push_back(ComboAddress(master, 53)); - else if (item.first == "id") - di.id = static_cast(boost::get(item.second)); - else if (item.first == "notified_serial") - di.notified_serial = static_cast(boost::get(item.second)); - else if (item.first == "serial") - di.serial = static_cast(boost::get(item.second)); - else if (item.first == "kind") - di.kind = DomainInfo::stringToKind(boost::get(item.second)); - else - g_log<(item.second); + else if (item.first == "last_check") + di.last_check = static_cast(boost::get(item.second)); + else if (item.first == "masters") + for (const auto& master : boost::get>(item.second)) + di.masters.push_back(ComboAddress(master, 53)); + else if (item.first == "id") + di.id = static_cast(boost::get(item.second)); + else if (item.first == "notified_serial") + di.notified_serial = static_cast(boost::get(item.second)); + else if (item.first == "serial") + di.serial = static_cast(boost::get(item.second)); + else if (item.first == "kind") + di.kind = DomainInfo::stringToKind(boost::get(item.second)); + else + g_log << Logger::Warning << "Unsupported key '" << item.first << "' in domaininfo result" << endl; + } + di.backend = this; + logResult("zone=" << di.zone << ",serial=" << di.serial << ",kind=" << di.getKindString()); } - bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial=true) override { + bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial = true) override + { if (f_get_domaininfo == nullptr) { // use getAuth instead SOAData sd; @@ -260,7 +286,7 @@ public: return true; } - logCall("get_domaininfo","domain="<push_back(di); - } + void getAllDomains(vector* domains, bool include_disabled = false) override + { + if (f_get_all_domains == nullptr) + return; + + logCall("get_all_domains", ""); + for (const auto& row : f_get_all_domains()) { + DomainInfo di; + di.zone = row.first; + logResult(di.zone); + parseDomainInfo(row.second, di); + domains->push_back(di); + } } - bool getAllDomainMetadata(const DNSName& name, std::map >& meta) override { + bool getAllDomainMetadata(const DNSName& name, std::map>& meta) override + { if (f_get_all_domain_metadata == nullptr) return false; - logCall("get_all_domain_metadata","name="<>>(result)) { + meta[row.first].clear(); + for (const auto& item : row.second) + meta[row.first].push_back(item.second); + logResult("kind=" << row.first << ",value=" << boost::algorithm::join(meta[row.first], ", ")); } return true; } - bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) override { + bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) override + { if (f_get_domain_metadata == nullptr) return false; - logCall("get_domain_metadata","name="<& keys) override { + bool getDomainKeys(const DNSName& name, std::vector& keys) override + { if (f_get_domain_keys == nullptr) return false; - logCall("get_domain_keys","name="<(item.second); else if (item.first == "id") @@ -347,20 +377,21 @@ public: else if (item.first == "published") key.published = boost::get(item.second); else - g_log<(item.second)); + value = DNSName(boost::get(item.second)); else - value = DNSName(boost::get(item.second)); + value = DNSName(boost::get(item.second)); if (item.first == "unhashed") unhashed = value; else if (item.first == "before") @@ -384,12 +415,12 @@ public: else if (item.first == "after") after = value; else { - g_log< #include -CoProcess::CoProcess(const string &command,int timeout, int infd, int outfd): d_infd(infd), d_outfd(outfd), d_timeout(timeout) +CoProcess::CoProcess(const string& command, int timeout, int infd, int outfd) : + d_infd(infd), d_outfd(outfd), d_timeout(timeout) { split(d_params, command, boost::is_any_of(" ")); - d_argv.resize(d_params.size()+1); - d_argv[d_params.size()]=nullptr; + d_argv.resize(d_params.size() + 1); + d_argv[d_params.size()] = nullptr; for (size_t n = 0; n < d_params.size(); n++) { - d_argv[n]=d_params[n].c_str(); + d_argv[n] = d_params[n].c_str(); } d_pid = 0; } @@ -57,15 +58,15 @@ void CoProcess::launch() { signal(SIGPIPE, SIG_IGN); - if(access(d_argv[0],X_OK)) // check before fork so we can throw - throw PDNSException("Command '"+string(d_argv[0])+"' cannot be executed: "+stringerror()); + if (access(d_argv[0], X_OK)) // check before fork so we can throw + throw PDNSException("Command '" + string(d_argv[0]) + "' cannot be executed: " + stringerror()); - if(pipe(d_fd1)<0 || pipe(d_fd2)<0) - throw PDNSException("Unable to open pipe for coprocess: "+string(strerror(errno))); + if (pipe(d_fd1) < 0 || pipe(d_fd2) < 0) + throw PDNSException("Unable to open pipe for coprocess: " + string(strerror(errno))); - if((d_pid=fork())<0) - throw PDNSException("Unable to fork for coprocess: "+stringerror()); - else if(d_pid>0) { // parent speaking + if ((d_pid = fork()) < 0) + throw PDNSException("Unable to fork for coprocess: " + stringerror()); + else if (d_pid > 0) { // parent speaking // no need to keep this around d_argv.clear(); close(d_fd1[0]); @@ -77,23 +78,23 @@ void CoProcess::launch() setNonBlocking(d_fd2[0]); } } - else if(!d_pid) { // child + else if (!d_pid) { // child signal(SIGCHLD, SIG_DFL); // silence a warning from perl close(d_fd1[1]); close(d_fd2[0]); - if(d_fd1[0]!= d_infd) { + if (d_fd1[0] != d_infd) { dup2(d_fd1[0], d_infd); close(d_fd1[0]); } - if(d_fd2[1]!= d_outfd) { + if (d_fd2[1] != d_outfd) { dup2(d_fd2[1], d_outfd); close(d_fd2[1]); } // stdin & stdout are now connected, fire up our coprocess! - if(execv(d_argv[0], const_cast(d_argv.data()))<0) // now what + if (execv(d_argv[0], const_cast(d_argv.data())) < 0) // now what exit(123); /* not a lot we can do here. We shouldn't return because that will leave a forked process around. @@ -104,13 +105,13 @@ void CoProcess::launch() CoProcess::~CoProcess() { int status; - if(d_pid){ - if(!waitpid(d_pid, &status, WNOHANG)) { + if (d_pid) { + if (!waitpid(d_pid, &status, WNOHANG)) { kill(d_pid, 9); waitpid(d_pid, &status, 0); } } - + close(d_fd1[1]); close(d_fd2[0]); } @@ -118,47 +119,47 @@ CoProcess::~CoProcess() void CoProcess::checkStatus() { int status; - int ret=waitpid(d_pid, &status, WNOHANG); - if(ret<0) - throw PDNSException("Unable to ascertain status of coprocess "+itoa(d_pid)+" from "+itoa(getpid())+": "+string(strerror(errno))); - else if(ret) { - if(WIFEXITED(status)) { - int exitStatus=WEXITSTATUS(status); - throw PDNSException("Coprocess exited with code "+itoa(exitStatus)); + int ret = waitpid(d_pid, &status, WNOHANG); + if (ret < 0) + throw PDNSException("Unable to ascertain status of coprocess " + itoa(d_pid) + " from " + itoa(getpid()) + ": " + string(strerror(errno))); + else if (ret) { + if (WIFEXITED(status)) { + int exitStatus = WEXITSTATUS(status); + throw PDNSException("Coprocess exited with code " + itoa(exitStatus)); } - if(WIFSIGNALED(status)) { - int sig=WTERMSIG(status); - string reason="CoProcess died on receiving signal "+itoa(sig); + if (WIFSIGNALED(status)) { + int sig = WTERMSIG(status); + string reason = "CoProcess died on receiving signal " + itoa(sig); #ifdef WCOREDUMP - if(WCOREDUMP(status)) - reason+=". Dumped core"; + if (WCOREDUMP(status)) + reason += ". Dumped core"; #endif - + throw PDNSException(reason); } } } -void CoProcess::send(const string &snd) +void CoProcess::send(const string& snd) { checkStatus(); string line(snd); - line.append(1,'\n'); - - unsigned int sent=0; + line.append(1, '\n'); + + unsigned int sent = 0; int bytes; // writen routine - socket may not accept al data in one go - while(sent(got)); } } @@ -209,30 +211,29 @@ void CoProcess::receive(string &received) boost::trim_right(received); } -void CoProcess::sendReceive(const string &snd, string &rcv) +void CoProcess::sendReceive(const string& snd, string& rcv) { checkStatus(); send(snd); receive(rcv); - } -UnixRemote::UnixRemote(const string& path, int timeout) +UnixRemote::UnixRemote(const string& path, int timeout) { d_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if(d_fd < 0) - throw PDNSException("Unable to create UNIX domain socket: "+string(strerror(errno))); + if (d_fd < 0) + throw PDNSException("Unable to create UNIX domain socket: " + string(strerror(errno))); struct sockaddr_un remote; if (makeUNsockaddr(path, &remote)) - throw PDNSException("Unable to create UNIX domain socket: Path '"+path+"' is not a valid UNIX socket path."); + throw PDNSException("Unable to create UNIX domain socket: Path '" + path + "' is not a valid UNIX socket path."); // fcntl(fd, F_SETFL, O_NONBLOCK, &sock); - if(connect(d_fd, (struct sockaddr*)&remote, sizeof(remote)) < 0) - unixDie("Unable to connect to remote '"+path+"' using UNIX domain socket"); + if (connect(d_fd, (struct sockaddr*)&remote, sizeof(remote)) < 0) + unixDie("Unable to connect to remote '" + path + "' using UNIX domain socket"); - d_fp = std::unique_ptr(fdopen(d_fd, "r"), fclose); + d_fp = std::unique_ptr(fdopen(d_fd, "r"), fclose); } void UnixRemote::send(const string& line) @@ -249,7 +250,7 @@ void UnixRemote::receive(string& line) boost::trim_right(line); } -void UnixRemote::sendReceive(const string &snd, string &rcv) +void UnixRemote::sendReceive(const string& snd, string& rcv) { // checkStatus(); send(snd); @@ -259,13 +260,12 @@ void UnixRemote::sendReceive(const string &snd, string &rcv) bool isUnixSocket(const string& fname) { struct stat st; - if(stat(fname.c_str(), &st) < 0) + if (stat(fname.c_str(), &st) < 0) return false; // not a unix socket in any case ;-) return (st.st_mode & S_IFSOCK) == S_IFSOCK; } - #ifdef TESTDRIVER main() { @@ -273,11 +273,10 @@ main() CoProcess cp("./irc.pl"); string reply; cp.sendReceive("www.trilab.com", reply); - cout<<"Answered: '"< d_params; - std::vector d_argv; + std::vector d_argv; std::string d_remaining; int d_fd1[2], d_fd2[2]; int d_pid; @@ -60,12 +60,13 @@ private: class UnixRemote : public CoRemote { public: - UnixRemote(const string &path, int timeout=0); - void sendReceive(const string &send, string &receive) override; - void receive(string &rcv) override; - void send(const string &send) override; + UnixRemote(const string& path, int timeout = 0); + void sendReceive(const string& send, string& receive) override; + void receive(string& rcv) override; + void send(const string& send) override; + private: int d_fd; - std::unique_ptr d_fp{nullptr, fclose}; + std::unique_ptr d_fp{nullptr, fclose}; }; bool isUnixSocket(const string& fname); diff --git a/modules/pipebackend/pipebackend.cc b/modules/pipebackend/pipebackend.cc index c24d8ce113..c16852103f 100644 --- a/modules/pipebackend/pipebackend.cc +++ b/modules/pipebackend/pipebackend.cc @@ -42,15 +42,15 @@ #include #include "pipebackend.hh" -static const char *kBackendId = "[PIPEBackend]"; +static const char* kBackendId = "[PIPEBackend]"; -CoWrapper::CoWrapper(const string &command, int timeout, int abiVersion) +CoWrapper::CoWrapper(const string& command, int timeout, int abiVersion) { - d_command=command; - d_timeout=timeout; - d_abiVersion = abiVersion; - launch(); // let exceptions fall through - if initial launch fails, we want to die - // I think + d_command = command; + d_timeout = timeout; + d_abiVersion = abiVersion; + launch(); // let exceptions fall through - if initial launch fails, we want to die + // I think } CoWrapper::~CoWrapper() @@ -59,85 +59,85 @@ CoWrapper::~CoWrapper() void CoWrapper::launch() { - if(d_cp) - return; - - if(d_command.empty()) - throw ArgException("pipe-command is not specified"); - - if(isUnixSocket(d_command)) { - d_cp = std::unique_ptr(new UnixRemote(d_command, d_timeout)); - } - else { - auto coprocess = std::unique_ptr(new CoProcess(d_command, d_timeout)); - coprocess->launch(); - d_cp = std::move(coprocess); - } - - d_cp->send("HELO\t"+std::to_string(d_abiVersion)); - string banner; - d_cp->receive(banner); - g_log<(new UnixRemote(d_command, d_timeout)); + } + else { + auto coprocess = std::unique_ptr(new CoProcess(d_command, d_timeout)); + coprocess->launch(); + d_cp = std::move(coprocess); + } + + d_cp->send("HELO\t" + std::to_string(d_abiVersion)); + string banner; + d_cp->receive(banner); + g_log << Logger::Error << "Backend launched with banner: " << banner << endl; } -void CoWrapper::send(const string &line) +void CoWrapper::send(const string& line) { - launch(); - try { - d_cp->send(line); - return; - } - catch(PDNSException &ae) { - d_cp.reset(); - throw; - } + launch(); + try { + d_cp->send(line); + return; + } + catch (PDNSException& ae) { + d_cp.reset(); + throw; + } } -void CoWrapper::receive(string &line) +void CoWrapper::receive(string& line) { - launch(); - try { - d_cp->receive(line); - return; - } - catch(PDNSException &ae) { - g_log<receive(line); + return; + } + catch (PDNSException& ae) { + g_log << Logger::Warning << kBackendId << " Unable to receive data from coprocess. " << ae.reason << endl; + d_cp.reset(); + throw; + } } -PipeBackend::PipeBackend(const string &suffix) +PipeBackend::PipeBackend(const string& suffix) { - d_disavow=false; - signal(SIGCHLD, SIG_IGN); - setArgPrefix("pipe"+suffix); - try { - launch(); - } - catch(const ArgException &A) { - g_log<(new Regex(getArg("regex"))); } - d_regexstr=getArg("regex"); + d_regexstr = getArg("regex"); d_abiVersion = getArgAsNum("abi-version"); - d_coproc=unique_ptr (new CoWrapper(getArg("command"), getArgAsNum("timeout"), getArgAsNum("abi-version"))); + d_coproc = unique_ptr(new CoWrapper(getArg("command"), getArgAsNum("timeout"), getArgAsNum("abi-version"))); } - catch(const ArgException &A) { + catch (const ArgException& A) { cleanup(); throw; } @@ -154,91 +154,94 @@ void PipeBackend::cleanup() d_abiVersion = 0; } -void PipeBackend::lookup(const QType& qtype,const DNSName& qname, int zoneId, DNSPacket *pkt_p) +void PipeBackend::lookup(const QType& qtype, const DNSName& qname, int zoneId, DNSPacket* pkt_p) { try { launch(); - d_disavow=false; - if(d_regex && !d_regex->match(qname.toStringRootDot())) { - if(::arg().mustDo("query-logging")) - g_log<match(qname.toStringRootDot())) { + if (::arg().mustDo("query-logging")) + g_log << Logger::Error << "Query for '" << qname << "' failed regex '" << d_regexstr << "'" << endl; + d_disavow = true; // don't pass to backend + } + else { ostringstream query; - string localIP="0.0.0.0"; - string remoteIP="0.0.0.0"; + string localIP = "0.0.0.0"; + string remoteIP = "0.0.0.0"; Netmask realRemote("0.0.0.0/0"); if (pkt_p) { - localIP=pkt_p->getLocal().toString(); + localIP = pkt_p->getLocal().toString(); realRemote = pkt_p->getRealRemote(); remoteIP = pkt_p->getRemote().toString(); } // abi-version = 1 // type qname qclass qtype id remote-ip-address - query<<"Q\t"<= 2) - query<<"\t"<= 3) - query <<"\t"<= 3) + query << "\t" << realRemote.toString(); - if(::arg().mustDo("query-logging")) - g_log<send(query.str()); } } - catch(PDNSException &pe) { - g_log<= 4) - query<<"AXFR\t"<send(query.str()); } - catch(PDNSException &ae) { - g_log<send(oss.str()); } - catch(PDNSException &ae) { - g_log<receive(line); - if (line == "END") break; + if (line == "END") + break; oss << line << std::endl; }; @@ -246,15 +249,15 @@ string PipeBackend::directBackendCmd(const string &query) { } //! For the dynamic loader -DNSBackend *PipeBackend::maker() +DNSBackend* PipeBackend::maker() { - try { - return new PipeBackend(); - } - catch(...) { - g_log<= 3) + if (d_abiVersion >= 3) extraFields = 2; - try{ + try { launch(); - for(;;) { + for (;;) { d_coproc->receive(line); - vectorparts; - stringtok(parts,line,"\t"); - if(parts.empty()) { - g_log< parts; + stringtok(parts, line, "\t"); + if (parts.empty()) { + g_log << Logger::Error << kBackendId << " Coprocess returned empty line in query for " << d_qname << endl; throw PDNSException("Format error communicating with coprocess"); } - else if(parts[0]=="FAIL") { + else if (parts[0] == "FAIL") { throw DBException("coprocess returned a FAIL"); } - else if(parts[0]=="END") { + else if (parts[0] == "END") { return false; } - else if(parts[0]=="LOG") { - g_log<= 3) { - r.scopeMask = std::stoi(parts[1]); - r.auth = (parts[2] == "1"); - } else { - r.scopeMask = 0; - r.auth = true; - } - r.qname=DNSName(parts[1+extraFields]); - r.qtype=parts[3+extraFields]; - r.ttl=pdns_stou(parts[4+extraFields]); - r.domain_id=std::stoi(parts[5+extraFields]); - - if(r.qtype.getCode() != QType::MX && r.qtype.getCode() != QType::SRV) { + if (d_abiVersion >= 3) { + r.scopeMask = std::stoi(parts[1]); + r.auth = (parts[2] == "1"); + } + else { + r.scopeMask = 0; + r.auth = true; + } + r.qname = DNSName(parts[1 + extraFields]); + r.qtype = parts[3 + extraFields]; + r.ttl = pdns_stou(parts[4 + extraFields]); + r.domain_id = std::stoi(parts[5 + extraFields]); + + if (r.qtype.getCode() != QType::MX && r.qtype.getCode() != QType::SRV) { r.content.clear(); - for(unsigned int n= 6 + extraFields; n < parts.size(); ++n) { - if(n!=6+extraFields) - r.content.append(1,' '); + for (unsigned int n = 6 + extraFields; n < parts.size(); ++n) { + if (n != 6 + extraFields) + r.content.append(1, ' '); r.content.append(parts[n]); } } else { - if(parts.size()< 8 + extraFields) { - g_log< d_cp; string d_command; @@ -48,14 +48,14 @@ private: class PipeBackend : public DNSBackend { public: - PipeBackend(const string &suffix=""); + PipeBackend(const string& suffix = ""); ~PipeBackend(); - void lookup(const QType&, const DNSName& qdomain, int zoneId, DNSPacket *p=nullptr) override; - bool list(const DNSName& target, int domain_id, bool include_disabled=false) override; - bool get(DNSResourceRecord &r) override; - string directBackendCmd(const string &query) override; - static DNSBackend *maker(); - + void lookup(const QType&, const DNSName& qdomain, int zoneId, DNSPacket* p = nullptr) override; + bool list(const DNSName& target, int domain_id, bool include_disabled = false) override; + bool get(DNSResourceRecord& r) override; + string directBackendCmd(const string& query) override; + static DNSBackend* maker(); + private: void launch(); void cleanup(); diff --git a/modules/randombackend/randombackend.cc b/modules/randombackend/randombackend.cc index 71028a0841..01839e94fd 100644 --- a/modules/randombackend/randombackend.cc +++ b/modules/randombackend/randombackend.cc @@ -36,57 +36,64 @@ class RandomBackend : public DNSBackend { public: - RandomBackend(const string &suffix="") + RandomBackend(const string& suffix = "") { - setArgPrefix("random"+suffix); - d_ourname=DNSName(getArg("hostname")); + setArgPrefix("random" + suffix); + d_ourname = DNSName(getArg("hostname")); d_ourdomain = d_ourname; d_ourdomain.chopOff(); } - bool list(const DNSName &target, int id, bool include_disabled) override { + bool list(const DNSName& target, int id, bool include_disabled) override + { return false; // we don't support AXFR } - void lookup(const QType &type, const DNSName &qdomain, int zoneId, DNSPacket *p) override + void lookup(const QType& type, const DNSName& qdomain, int zoneId, DNSPacket* p) override { - if(qdomain == d_ourdomain){ - if(type.getCode() == QType::SOA || type.getCode() == QType::ANY) { - d_answer="ns1." + d_ourdomain.toString() + " hostmaster." + d_ourdomain.toString() + " 1234567890 86400 7200 604800 300"; - } else { - d_answer.clear();; + if (qdomain == d_ourdomain) { + if (type.getCode() == QType::SOA || type.getCode() == QType::ANY) { + d_answer = "ns1." + d_ourdomain.toString() + " hostmaster." + d_ourdomain.toString() + " 1234567890 86400 7200 604800 300"; + } + else { + d_answer.clear(); + ; } - } else if (qdomain == d_ourname) { - if(type.getCode() == QType::A || type.getCode() == QType::ANY) { + } + else if (qdomain == d_ourname) { + if (type.getCode() == QType::A || type.getCode() == QType::ANY) { ostringstream os; - os< options): d_socket(nullptr) { +HTTPConnector::HTTPConnector(std::map options) : + d_socket(nullptr) +{ - if (options.find("url") == options.end()) { - throw PDNSException("Cannot find 'url' option in the remote backend HTTP connector's parameters"); + if (options.find("url") == options.end()) { + throw PDNSException("Cannot find 'url' option in the remote backend HTTP connector's parameters"); + } + + this->d_url = options.find("url")->second; + + try { + YaHTTP::URL url(d_url); + d_host = url.host; + d_port = url.port; + } + catch (const std::exception& e) { + throw PDNSException("Error parsing the 'url' option provided to the remote backend HTTP connector: " + std::string(e.what())); + } + + if (options.find("url-suffix") != options.end()) { + this->d_url_suffix = options.find("url-suffix")->second; + } + else { + this->d_url_suffix = ""; + } + this->timeout = 2; + this->d_post = false; + this->d_post_json = false; + + if (options.find("timeout") != options.end()) { + this->timeout = std::stoi(options.find("timeout")->second) / 1000; + } + if (options.find("post") != options.end()) { + std::string val = options.find("post")->second; + if (val == "yes" || val == "true" || val == "on" || val == "1") { + this->d_post = true; + } + } + if (options.find("post_json") != options.end()) { + std::string val = options.find("post_json")->second; + if (val == "yes" || val == "true" || val == "on" || val == "1") { + this->d_post_json = true; } + } +} + +HTTPConnector::~HTTPConnector() {} + +void HTTPConnector::addUrlComponent(const Json& parameters, const string& element, std::stringstream& ss) +{ + std::string sparam; + if (parameters[element] != Json()) + ss << "/" << YaHTTP::Utility::encodeURL(asString(parameters[element]), false); +} - this->d_url = options.find("url")->second; +std::string HTTPConnector::buildMemberListArgs(std::string prefix, const Json& args) +{ + std::stringstream stream; - try { - YaHTTP::URL url(d_url); - d_host = url.host; - d_port = url.port; + for (const auto& pair : args.object_items()) { + if (pair.second.is_bool()) { + stream << (pair.second.bool_value() ? "1" : "0"); } - catch(const std::exception& e) { - throw PDNSException("Error parsing the 'url' option provided to the remote backend HTTP connector: " + std::string(e.what())); + else if (pair.second.is_null()) { + stream << prefix << "[" << YaHTTP::Utility::encodeURL(pair.first, false) << "]="; } - - if (options.find("url-suffix") != options.end()) { - this->d_url_suffix = options.find("url-suffix")->second; - } else { - this->d_url_suffix = ""; + else { + stream << prefix << "[" << YaHTTP::Utility::encodeURL(pair.first, false) << "]=" << YaHTTP::Utility::encodeURL(this->asString(pair.second), false); } - this->timeout = 2; - this->d_post = false; - this->d_post_json = false; + stream << "&"; + } - if (options.find("timeout") != options.end()) { - this->timeout = std::stoi(options.find("timeout")->second)/1000; + return stream.str().substr(0, stream.str().size() - 1); // snip the trailing & +} + +// builds our request (near-restful) +void HTTPConnector::restful_requestbuilder(const std::string& method, const Json& parameters, YaHTTP::Request& req) +{ + std::stringstream ss; + std::string sparam; + std::string verb; + + // special names are qname, name, zonename, kind, others go to headers + + ss << d_url; + + ss << "/" << method; + + // add the url components, if found, in following order. + // id must be first due to the fact that the qname/name can be empty + + addUrlComponent(parameters, "id", ss); + addUrlComponent(parameters, "domain_id", ss); + addUrlComponent(parameters, "zonename", ss); + addUrlComponent(parameters, "qname", ss); + addUrlComponent(parameters, "name", ss); + addUrlComponent(parameters, "kind", ss); + addUrlComponent(parameters, "qtype", ss); + + // set the correct type of request based on method + if (method == "activateDomainKey" || method == "deactivateDomainKey" || method == "publishDomainKey" || method == "unpublishDomainKey") { + // create an empty post + req.preparePost(); + verb = "POST"; + } + else if (method == "setTSIGKey") { + req.POST()["algorithm"] = parameters["algorithm"].string_value(); + req.POST()["content"] = parameters["content"].string_value(); + req.preparePost(); + verb = "PATCH"; + } + else if (method == "deleteTSIGKey") { + verb = "DELETE"; + } + else if (method == "addDomainKey") { + const Json& param = parameters["key"]; + req.POST()["flags"] = asString(param["flags"]); + req.POST()["active"] = (param["active"].bool_value() ? "1" : "0"); + req.POST()["published"] = (param["published"].bool_value() ? "1" : "0"); + req.POST()["content"] = param["content"].string_value(); + req.preparePost(); + verb = "PUT"; + } + 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 (size_t index = 0; index < parameters["nsset"].array_items().size(); index++) { + ss2 << buildMemberListArgs("nsset[" + std::to_string(index) + "]", parameters["nsset"][index]) << "&"; } - if (options.find("post") != options.end()) { - std::string val = options.find("post")->second; - if (val == "yes" || val == "true" || val == "on" || val == "1") { - this->d_post = true; - } + req.body = ss2.str().substr(0, ss2.str().size() - 1); + req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; + req.headers["content-length"] = std::to_string(req.body.size()); + verb = "POST"; + } + else if (method == "createSlaveDomain") { + addUrlComponent(parameters, "ip", ss); + addUrlComponent(parameters, "domain", ss); + if (parameters["account"].is_null() == false && parameters["account"].is_string()) { + req.POST()["account"] = parameters["account"].string_value(); + } + req.preparePost(); + verb = "PUT"; + } + else if (method == "replaceRRSet") { + std::stringstream ss2; + for (size_t index = 0; index < parameters["rrset"].array_items().size(); index++) { + ss2 << buildMemberListArgs("rrset[" + std::to_string(index) + "]", parameters["rrset"][index]); + } + req.body = ss2.str(); + req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; + req.headers["content-length"] = std::to_string(req.body.size()); + verb = "PATCH"; + } + else if (method == "feedRecord") { + addUrlComponent(parameters, "trxid", ss); + req.body = buildMemberListArgs("rr", parameters["rr"]); + req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; + req.headers["content-length"] = std::to_string(req.body.size()); + verb = "PATCH"; + } + else if (method == "feedEnts") { + std::stringstream ss2; + addUrlComponent(parameters, "trxid", ss); + for (const auto& param : parameters["nonterm"].array_items()) { + ss2 << "nonterm[]=" << YaHTTP::Utility::encodeURL(param.string_value(), false) << "&"; + } + for (const auto& param : parameters["auth"].array_items()) { + ss2 << "auth[]=" << (param["auth"].bool_value() ? "1" : "0") << "&"; + } + req.body = ss2.str().substr(0, ss2.str().size() - 1); + req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; + req.headers["content-length"] = std::to_string(req.body.size()); + verb = "PATCH"; + } + else if (method == "feedEnts3") { + std::stringstream ss2; + addUrlComponent(parameters, "domain", ss); + addUrlComponent(parameters, "trxid", ss); + ss2 << "times=" << parameters["times"].int_value() << "&salt=" << YaHTTP::Utility::encodeURL(parameters["salt"].string_value(), false) << "&narrow=" << (parameters["narrow"].bool_value() ? 1 : 0) << "&"; + for (const auto& param : parameters["nonterm"].array_items()) { + ss2 << "nonterm[]=" << YaHTTP::Utility::encodeURL(param.string_value(), false) << "&"; } - if (options.find("post_json") != options.end()) { - std::string val = options.find("post_json")->second; - if (val == "yes" || val == "true" || val == "on" || val == "1") { - this->d_post_json = true; + for (const auto& param : parameters["auth"].array_items()) { + ss2 << "auth[]=" << (param["auth"].bool_value() ? "1" : "0") << "&"; + } + req.body = ss2.str().substr(0, ss2.str().size() - 1); + req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; + req.headers["content-length"] = std::to_string(req.body.size()); + verb = "PATCH"; + } + else if (method == "startTransaction") { + addUrlComponent(parameters, "domain", ss); + addUrlComponent(parameters, "trxid", ss); + req.preparePost(); + verb = "POST"; + } + else if (method == "commitTransaction" || method == "abortTransaction") { + addUrlComponent(parameters, "trxid", ss); + req.preparePost(); + verb = "POST"; + } + else if (method == "setDomainMetadata") { + // copy all metadata values into post + std::stringstream ss2; + // this one has values too + if (parameters["value"].is_array()) { + for (const auto& val : parameters["value"].array_items()) { + ss2 << "value[]=" << YaHTTP::Utility::encodeURL(val.string_value(), false) << "&"; } } -} + req.body = ss2.str().substr(0, ss2.str().size() - 1); + req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; + req.headers["content-length"] = std::to_string(req.body.size()); + verb = "PATCH"; + } + else if (method == "removeDomainKey") { + // this one is delete + verb = "DELETE"; + } + else if (method == "setNotified") { + req.POST()["serial"] = std::to_string(parameters["serial"].number_value()); + req.preparePost(); + verb = "PATCH"; + } + else if (method == "setFresh") { + req.preparePost(); + verb = "PATCH"; + } + else if (method == "directBackendCmd") { + req.POST()["query"] = parameters["query"].string_value(); + req.preparePost(); + verb = "POST"; + } + else if (method == "searchRecords" || method == "searchComments") { + req.GET()["pattern"] = parameters["pattern"].string_value(); + req.GET()["maxResults"] = std::to_string(parameters["maxResults"].int_value()); + verb = "GET"; + } + else if (method == "getAllDomains") { + req.GET()["includeDisabled"] = (parameters["include_disabled"].bool_value() ? "true" : "false"); + verb = "GET"; + } + else { + // perform normal get + verb = "GET"; + } + + // put everything else into headers + for (const auto& pair : parameters.object_items()) { + std::string member = pair.first; + // whitelist header parameters + if ((member == "trxid" || member == "local" || member == "remote" || member == "real-remote" || member == "zone-id")) { + std::string hdr = "x-remotebackend-" + member; + req.headers[hdr] = asString(pair.second); + } + }; -HTTPConnector::~HTTPConnector() { } + // finally add suffix and store url + ss << d_url_suffix; -void HTTPConnector::addUrlComponent(const Json ¶meters, const string& element, std::stringstream& ss) { - std::string sparam; - if (parameters[element] != Json()) - ss << "/" << YaHTTP::Utility::encodeURL(asString(parameters[element]), false); + req.setup(verb, ss.str()); + req.headers["accept"] = "application/json"; } -std::string HTTPConnector::buildMemberListArgs(std::string prefix, const Json& args) { - std::stringstream stream; - - for(const auto& pair: args.object_items()) { - if (pair.second.is_bool()) { - stream << (pair.second.bool_value()?"1":"0"); - } else if (pair.second.is_null()) { - stream << prefix << "[" << YaHTTP::Utility::encodeURL(pair.first, false) << "]="; - } else { - stream << prefix << "[" << YaHTTP::Utility::encodeURL(pair.first, false) << "]=" << YaHTTP::Utility::encodeURL(this->asString(pair.second), false); - } - stream << "&"; - } - - return stream.str().substr(0, stream.str().size()-1); // snip the trailing & +void HTTPConnector::post_requestbuilder(const Json& input, YaHTTP::Request& req) +{ + if (this->d_post_json) { + std::string out = input.dump(); + req.setup("POST", d_url); + // simple case, POST JSON into url. nothing fancy. + req.headers["Content-Type"] = "text/javascript; charset=utf-8"; + req.headers["Content-Length"] = std::to_string(out.size()); + req.headers["accept"] = "application/json"; + req.body = out; + } + else { + std::stringstream url, content; + // call url/method.suffix + url << d_url << "/" << input["method"].string_value() << d_url_suffix; + req.setup("POST", url.str()); + // then build content + req.POST()["parameters"] = input["parameters"].dump(); + req.preparePost(); + req.headers["accept"] = "application/json"; + } } -// builds our request (near-restful) -void HTTPConnector::restful_requestbuilder(const std::string &method, const Json& parameters, YaHTTP::Request& req) +int HTTPConnector::send_message(const Json& input) { - std::stringstream ss; - std::string sparam; - std::string verb; - - // special names are qname, name, zonename, kind, others go to headers - - ss << d_url; - - ss << "/" << method; - - // add the url components, if found, in following order. - // id must be first due to the fact that the qname/name can be empty - - addUrlComponent(parameters, "id", ss); - addUrlComponent(parameters, "domain_id", ss); - addUrlComponent(parameters, "zonename", ss); - addUrlComponent(parameters, "qname", ss); - addUrlComponent(parameters, "name", ss); - addUrlComponent(parameters, "kind", ss); - addUrlComponent(parameters, "qtype", ss); - - // set the correct type of request based on method - if (method == "activateDomainKey" || method == "deactivateDomainKey" || method == "publishDomainKey" || method == "unpublishDomainKey") { - // create an empty post - req.preparePost(); - verb = "POST"; - } else if (method == "setTSIGKey") { - req.POST()["algorithm"] = parameters["algorithm"].string_value(); - req.POST()["content"] = parameters["content"].string_value(); - req.preparePost(); - verb = "PATCH"; - } else if (method == "deleteTSIGKey") { - verb = "DELETE"; - } else if (method == "addDomainKey") { - const Json& param = parameters["key"]; - req.POST()["flags"] = asString(param["flags"]); - req.POST()["active"] = (param["active"].bool_value() ? "1" : "0"); - req.POST()["published"] = (param["published"].bool_value() ? "1" : "0"); - req.POST()["content"] = param["content"].string_value(); - req.preparePost(); - verb = "PUT"; - } 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(size_t index = 0; index < parameters["nsset"].array_items().size(); index++) { - ss2 << buildMemberListArgs("nsset[" + std::to_string(index) + "]", parameters["nsset"][index]) << "&"; - } - req.body = ss2.str().substr(0, ss2.str().size()-1); - req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; - req.headers["content-length"] = std::to_string(req.body.size()); - verb = "POST"; - } else if (method == "createSlaveDomain") { - addUrlComponent(parameters, "ip", ss); - addUrlComponent(parameters, "domain", ss); - if (parameters["account"].is_null() == false && parameters["account"].is_string()) { - req.POST()["account"] = parameters["account"].string_value(); - } - req.preparePost(); - verb = "PUT"; - } else if (method == "replaceRRSet") { - std::stringstream ss2; - for(size_t index = 0; index < parameters["rrset"].array_items().size(); index++) { - ss2 << buildMemberListArgs("rrset[" + std::to_string(index) + "]", parameters["rrset"][index]); - } - req.body = ss2.str(); - req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; - req.headers["content-length"] = std::to_string(req.body.size()); - verb = "PATCH"; - } else if (method == "feedRecord") { - addUrlComponent(parameters, "trxid", ss); - req.body = buildMemberListArgs("rr", parameters["rr"]); - req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; - req.headers["content-length"] = std::to_string(req.body.size()); - verb = "PATCH"; - } else if (method == "feedEnts") { - std::stringstream ss2; - addUrlComponent(parameters, "trxid", ss); - for(const auto& param: parameters["nonterm"].array_items()) { - ss2 << "nonterm[]=" << YaHTTP::Utility::encodeURL(param.string_value(), false) << "&"; - } - for(const auto& param: parameters["auth"].array_items()) { - ss2 << "auth[]=" << (param["auth"].bool_value()?"1":"0") << "&"; - } - req.body = ss2.str().substr(0, ss2.str().size()-1); - req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; - req.headers["content-length"] = std::to_string(req.body.size()); - verb = "PATCH"; - } else if (method == "feedEnts3") { - std::stringstream ss2; - addUrlComponent(parameters, "domain", ss); - addUrlComponent(parameters, "trxid", ss); - ss2 << "times=" << parameters["times"].int_value() << "&salt=" << YaHTTP::Utility::encodeURL(parameters["salt"].string_value(), false) << "&narrow=" << (parameters["narrow"].bool_value() ? 1 : 0) << "&"; - for(const auto& param: parameters["nonterm"].array_items()) { - ss2 << "nonterm[]=" << YaHTTP::Utility::encodeURL(param.string_value(), false) << "&"; - } - for(const auto& param: parameters["auth"].array_items()) { - ss2 << "auth[]=" << (param["auth"].bool_value()?"1":"0") << "&"; - } - req.body = ss2.str().substr(0, ss2.str().size()-1); - req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; - req.headers["content-length"] = std::to_string(req.body.size()); - verb = "PATCH"; - } else if (method == "startTransaction") { - addUrlComponent(parameters, "domain", ss); - addUrlComponent(parameters, "trxid", ss); - req.preparePost(); - verb = "POST"; - } else if (method == "commitTransaction" || method == "abortTransaction") { - addUrlComponent(parameters, "trxid", ss); - req.preparePost(); - verb = "POST"; - } else if (method == "setDomainMetadata") { - // copy all metadata values into post - std::stringstream ss2; - // this one has values too - if (parameters["value"].is_array()) { - for(const auto& val: parameters["value"].array_items()) { - ss2 << "value[]=" << YaHTTP::Utility::encodeURL(val.string_value(), false) << "&"; - } - } - req.body = ss2.str().substr(0, ss2.str().size()-1); - req.headers["content-type"] = "application/x-www-form-urlencoded; charset=utf-8"; - req.headers["content-length"] = std::to_string(req.body.size()); - verb = "PATCH"; - } else if (method == "removeDomainKey") { - // this one is delete - verb = "DELETE"; - } else if (method == "setNotified") { - req.POST()["serial"] = std::to_string(parameters["serial"].number_value()); - req.preparePost(); - verb = "PATCH"; - } else if (method == "setFresh") { - req.preparePost(); - verb = "PATCH"; - } else if (method == "directBackendCmd") { - req.POST()["query"] = parameters["query"].string_value(); - req.preparePost(); - verb = "POST"; - } else if (method == "searchRecords" || method == "searchComments") { - req.GET()["pattern"] = parameters["pattern"].string_value(); - req.GET()["maxResults"] = std::to_string(parameters["maxResults"].int_value()); - verb = "GET"; - } else if (method == "getAllDomains") { - req.GET()["includeDisabled"] = (parameters["include_disabled"].bool_value()?"true":"false"); - verb = "GET"; - } else { - // perform normal get - verb = "GET"; - } + int rv, ec, fd; - // put everything else into headers - for(const auto& pair: parameters.object_items()) { - std::string member = pair.first; - // whitelist header parameters - if ((member == "trxid" || - member == "local" || - member == "remote" || - member == "real-remote" || - member == "zone-id")) { - std::string hdr = "x-remotebackend-" + member; - req.headers[hdr] = asString(pair.second); - } - }; + std::vector members; + std::string method; + std::ostringstream out; - // finally add suffix and store url - ss << d_url_suffix; + // perform request + YaHTTP::Request req; - req.setup(verb, ss.str()); - req.headers["accept"] = "application/json"; -} + if (d_post) + post_requestbuilder(input, req); + else + restful_requestbuilder(input["method"].string_value(), input["parameters"], req); -void HTTPConnector::post_requestbuilder(const Json& input, YaHTTP::Request& req) { - if (this->d_post_json) { - std::string out = input.dump(); - req.setup("POST", d_url); - // simple case, POST JSON into url. nothing fancy. - req.headers["Content-Type"] = "text/javascript; charset=utf-8"; - req.headers["Content-Length"] = std::to_string(out.size()); - req.headers["accept"] = "application/json"; - req.body = out; - } else { - std::stringstream url,content; - // call url/method.suffix - url << d_url << "/" << input["method"].string_value() << d_url_suffix; - req.setup("POST", url.str()); - // then build content - req.POST()["parameters"] = input["parameters"].dump(); - req.preparePost(); - req.headers["accept"] = "application/json"; - } -} + rv = -1; + req.headers["connection"] = "Keep-Alive"; // see if we can streamline requests (not needed, strictly speaking) -int HTTPConnector::send_message(const Json& input) { - int rv,ec,fd; - - std::vector members; - std::string method; - std::ostringstream out; - - // perform request - YaHTTP::Request req; - - if (d_post) - post_requestbuilder(input, req); - else - restful_requestbuilder(input["method"].string_value(), input["parameters"], req); - - rv = -1; - req.headers["connection"] = "Keep-Alive"; // see if we can streamline requests (not needed, strictly speaking) - - out << req; - - // try sending with current socket, if it fails retry with new socket - if (this->d_socket != nullptr) { - fd = this->d_socket->getHandle(); - // there should be no data waiting - if (waitForRWData(fd, true, 0, 1000) < 1) { - try { - d_socket->writenWithTimeout(out.str().c_str(), out.str().size(), timeout); - rv = 1; - } catch (NetworkError& ne) { - g_log<d_socket.reset(); - - // connect using tcp - struct addrinfo *gAddr, *gAddrPtr, hints; - std::string sPort = std::to_string(d_port); - memset(&hints,0,sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_flags = AI_ADDRCONFIG; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - if ((ec = getaddrinfo(d_host.c_str(), sPort.c_str(), &hints, &gAddr)) == 0) { - // try to connect to each address. - gAddrPtr = gAddr; - - while(gAddrPtr) { - try { - d_socket = std::unique_ptr(new Socket(gAddrPtr->ai_family, gAddrPtr->ai_socktype, gAddrPtr->ai_protocol)); - d_addr.setSockaddr(gAddrPtr->ai_addr, gAddrPtr->ai_addrlen); - d_socket->connect(d_addr); - d_socket->setNonBlocking(); - d_socket->writenWithTimeout(out.str().c_str(), out.str().size(), timeout); - rv = 1; - } catch (NetworkError& ne) { - g_log< -1) break; - d_socket.reset(); - gAddrPtr = gAddrPtr->ai_next; + // try sending with current socket, if it fails retry with new socket + if (this->d_socket != nullptr) { + fd = this->d_socket->getHandle(); + // there should be no data waiting + if (waitForRWData(fd, true, 0, 1000) < 1) { + try { + d_socket->writenWithTimeout(out.str().c_str(), out.str().size(), timeout); + rv = 1; + } + catch (NetworkError& ne) { + g_log << Logger::Error << "While writing to HTTP endpoint " << d_addr.toStringWithPort() << ": " << ne.what() << std::endl; + } + catch (...) { + g_log << Logger::Error << "While writing to HTTP endpoint " << d_addr.toStringWithPort() << ": exception caught" << std::endl; } - freeaddrinfo(gAddr); - } else { - g_log<readWithTimeout(buffer, sizeof(buffer), timeout); - if (rd==0) - throw NetworkError("EOF while reading"); - if (rd<0) - throw NetworkError(std::string(strerror(rd))); - arl.feed(std::string(buffer, rd)); + this->d_socket.reset(); + + // connect using tcp + struct addrinfo *gAddr, *gAddrPtr, hints; + std::string sPort = std::to_string(d_port); + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_ADDRCONFIG; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + if ((ec = getaddrinfo(d_host.c_str(), sPort.c_str(), &hints, &gAddr)) == 0) { + // try to connect to each address. + gAddrPtr = gAddr; + + while (gAddrPtr) { + try { + d_socket = std::unique_ptr(new Socket(gAddrPtr->ai_family, gAddrPtr->ai_socktype, gAddrPtr->ai_protocol)); + d_addr.setSockaddr(gAddrPtr->ai_addr, gAddrPtr->ai_addrlen); + d_socket->connect(d_addr); + d_socket->setNonBlocking(); + d_socket->writenWithTimeout(out.str().c_str(), out.str().size(), timeout); + rv = 1; } - // timeout occurred. - if (arl.ready() == false) - throw NetworkError("timeout"); - } catch (NetworkError &ne) { - d_socket.reset(); - throw PDNSException("While reading from HTTP endpoint " + d_addr.toStringWithPort() + ": " + ne.what()); - } catch (...) { + catch (NetworkError& ne) { + g_log << Logger::Error << "While writing to HTTP endpoint " << d_addr.toStringWithPort() << ": " << ne.what() << std::endl; + } + catch (...) { + g_log << Logger::Error << "While writing to HTTP endpoint " << d_addr.toStringWithPort() << ": exception caught" << std::endl; + } + + if (rv > -1) + break; d_socket.reset(); - throw PDNSException("While reading from HTTP endpoint " + d_addr.toStringWithPort() + ": unknown error"); + gAddrPtr = gAddrPtr->ai_next; } + freeaddrinfo(gAddr); + } + else { + g_log << Logger::Error << "Unable to resolve " << d_host << ": " << gai_strerror(ec) << std::endl; + } - arl.finalize(); + return rv; +} - if ((resp.status < 200 || resp.status >= 400) && resp.status != 404) { - // bad. - throw PDNSException("Received unacceptable HTTP status code " + std::to_string(resp.status) + " from HTTP endpoint " + d_addr.toStringWithPort()); +int HTTPConnector::recv_message(Json& output) +{ + YaHTTP::AsyncResponseLoader arl; + YaHTTP::Response resp; + + if (d_socket == nullptr) + return -1; // cannot receive :( + char buffer[4096]; + int rd = -1; + time_t t0; + + arl.initialize(&resp); + + try { + t0 = time((time_t*)NULL); + while (arl.ready() == false && (labs(time((time_t*)NULL) - t0) <= timeout)) { + rd = d_socket->readWithTimeout(buffer, sizeof(buffer), timeout); + if (rd == 0) + throw NetworkError("EOF while reading"); + if (rd < 0) + throw NetworkError(std::string(strerror(rd))); + arl.feed(std::string(buffer, rd)); } - - int rv = -1; - std::string err; - output = Json::parse(resp.body, err); - if (output != nullptr) return resp.body.size(); - g_log<= 400) && resp.status != 404) { + // bad. + throw PDNSException("Received unacceptable HTTP status code " + std::to_string(resp.status) + " from HTTP endpoint " + d_addr.toStringWithPort()); + } + + int rv = -1; + std::string err; + output = Json::parse(resp.body, err); + if (output != nullptr) + return resp.body.size(); + g_log << Logger::Error << "Cannot parse JSON reply: " << err << endl; + + return rv; } diff --git a/modules/remotebackend/pipeconnector.cc b/modules/remotebackend/pipeconnector.cc index e9d116b60d..5d563acc0a 100644 --- a/modules/remotebackend/pipeconnector.cc +++ b/modules/remotebackend/pipeconnector.cc @@ -24,29 +24,33 @@ #endif #include "remotebackend.hh" -PipeConnector::PipeConnector(std::map optionsMap): d_pid(-1) { +PipeConnector::PipeConnector(std::map optionsMap) : + d_pid(-1) +{ if (optionsMap.count("command") == 0) { - g_log<command = optionsMap.find("command")->second; this->options = optionsMap; - d_timeout=2000; + d_timeout = 2000; if (optionsMap.find("timeout") != optionsMap.end()) { - d_timeout = std::stoi(optionsMap.find("timeout")->second); + d_timeout = std::stoi(optionsMap.find("timeout")->second); } d_fd1[0] = d_fd1[1] = -1; d_fd2[0] = d_fd2[1] = -1; } -PipeConnector::~PipeConnector(){ +PipeConnector::~PipeConnector() +{ int status; // just in case... - if (d_pid == -1) return; + if (d_pid == -1) + return; - if(!waitpid(d_pid, &status, WNOHANG)) { + if (!waitpid(d_pid, &status, WNOHANG)) { kill(d_pid, 9); waitpid(d_pid, &status, 0); } @@ -56,57 +60,59 @@ PipeConnector::~PipeConnector(){ } } -void PipeConnector::launch() { +void PipeConnector::launch() +{ // no relaunch - if (d_pid > 0 && checkStatus()) return; + if (d_pid > 0 && checkStatus()) + return; - std::vector v; + std::vector v; split(v, command, boost::is_any_of(" ")); - std::vectorargv(v.size()+1); - argv[v.size()]=0; + std::vector argv(v.size() + 1); + argv[v.size()] = 0; for (size_t n = 0; n < v.size(); n++) - argv[n]=v[n].c_str(); + argv[n] = v[n].c_str(); signal(SIGPIPE, SIG_IGN); - if(access(argv[0],X_OK)) // check before fork so we can throw - throw PDNSException("Command '"+string(argv[0])+"' cannot be executed: "+stringerror()); + if (access(argv[0], X_OK)) // check before fork so we can throw + throw PDNSException("Command '" + string(argv[0]) + "' cannot be executed: " + stringerror()); - if(pipe(d_fd1)<0 || pipe(d_fd2)<0) - throw PDNSException("Unable to open pipe for coprocess: "+string(strerror(errno))); + if (pipe(d_fd1) < 0 || pipe(d_fd2) < 0) + throw PDNSException("Unable to open pipe for coprocess: " + string(strerror(errno))); - if((d_pid=fork())<0) - throw PDNSException("Unable to fork for coprocess: "+stringerror()); - else if(d_pid>0) { // parent speaking + if ((d_pid = fork()) < 0) + throw PDNSException("Unable to fork for coprocess: " + stringerror()); + else if (d_pid > 0) { // parent speaking close(d_fd1[0]); setCloseOnExec(d_fd1[1]); close(d_fd2[1]); setCloseOnExec(d_fd2[0]); - if(!(d_fp=std::unique_ptr(fdopen(d_fd2[0],"r"), fclose))) - throw PDNSException("Unable to associate a file pointer with pipe: "+stringerror()); + if (!(d_fp = std::unique_ptr(fdopen(d_fd2[0], "r"), fclose))) + throw PDNSException("Unable to associate a file pointer with pipe: " + stringerror()); if (d_timeout) - setbuf(d_fp.get(),0); // no buffering please, confuses poll + setbuf(d_fp.get(), 0); // no buffering please, confuses poll } - else if(!d_pid) { // child + else if (!d_pid) { // child signal(SIGCHLD, SIG_DFL); // silence a warning from perl close(d_fd1[1]); close(d_fd2[0]); - if(d_fd1[0]!= 0) { + if (d_fd1[0] != 0) { dup2(d_fd1[0], 0); close(d_fd1[0]); } - if(d_fd2[1]!= 1) { + if (d_fd2[1] != 1) { dup2(d_fd2[1], 1); close(d_fd2[1]); } // stdin & stdout are now connected, fire up our coprocess! - if(execv(argv[0], const_cast(argv.data()))<0) // now what + if (execv(argv[0], const_cast(argv.data())) < 0) // now what exit(123); /* not a lot we can do here. We shouldn't return because that will leave a forked process around. @@ -115,83 +121,84 @@ void PipeConnector::launch() { Json::array parameters; Json msg = Json(Json::object{ - { "method", "initialize" }, - { "parameters", Json(options) }, + {"method", "initialize"}, + {"parameters", Json(options)}, }); this->send(msg); msg = nullptr; - if (this->recv(msg)==false) { - g_log<recv(msg) == false) { + g_log << Logger::Error << "Failed to initialize coprocess" << std::endl; } } int PipeConnector::send_message(const Json& input) { - auto line = input.dump(); - launch(); + auto line = input.dump(); + launch(); - line.append(1,'\n'); + line.append(1, '\n'); - unsigned int sent=0; - int bytes; + unsigned int sent = 0; + int bytes; - // writen routine - socket may not accept al data in one go - while(sent0; +bool Connector::send(Json& value) +{ + return send_message(value) > 0; } /** @@ -41,25 +42,28 @@ bool Connector::send(Json& value) { * that the receiving happened ok, and extract * result. Logging is performed here, too. */ -bool Connector::recv(Json& value) { +bool Connector::recv(Json& value) +{ if (recv_message(value) > 0) { bool retval = true; if (value["result"] == Json()) { throw PDNSException("No 'result' field in response from remote process"); - } else if (value["result"].is_bool() && boolFromJson(value, "result", false) == false) { + } + else if (value["result"].is_bool() && boolFromJson(value, "result", false) == false) { retval = false; } - for(const auto& message: value["log"].array_items()) { - g_log<d_connstr = getArg("connection-string"); - this->d_dnssec = mustDo("dnssec"); - this->d_index = -1; - this->d_trxid = 0; + this->d_connstr = getArg("connection-string"); + this->d_dnssec = mustDo("dnssec"); + this->d_index = -1; + this->d_trxid = 0; - build(); + build(); } -RemoteBackend::~RemoteBackend() { } +RemoteBackend::~RemoteBackend() {} -bool RemoteBackend::send(Json& value) { +bool RemoteBackend::send(Json& value) +{ try { if (!connector->send(value)) { // XXX does this work work even though we throw? @@ -90,816 +95,736 @@ bool RemoteBackend::send(Json& value) { build(); throw DBException("Could not send a message to remote process"); } - } catch (const PDNSException &ex) { + } + catch (const PDNSException& ex) { throw DBException("Exception caught when sending: " + ex.reason); } return true; } -bool RemoteBackend::recv(Json& value) { +bool RemoteBackend::recv(Json& value) +{ try { return connector->recv(value); - } catch (const PDNSException &ex) { + } + catch (const PDNSException& ex) { this->connector.reset(); build(); throw DBException("Exception caught when receiving: " + ex.reason); - } catch (const std::exception &e) { + } + catch (const std::exception& e) { this->connector.reset(); build(); throw DBException("Exception caught when receiving: " + std::string(e.what())); } } - /** * Builds connector based on options * Currently supports unix,pipe and http */ -int RemoteBackend::build() { - std::vector parts; - std::string type; - std::string opts; - std::map options; - - // connstr is of format "type:options" - size_t pos; - pos = d_connstr.find_first_of(":"); - if (pos == std::string::npos) - throw PDNSException("Invalid connection string: malformed"); - - type = d_connstr.substr(0, pos); - opts = d_connstr.substr(pos+1); - - // tokenize the string on comma - stringtok(parts, opts, ","); - - // find out some options and parse them while we're at it - for(const auto& opt: parts) { - std::string key,val; - // make sure there is something else than air in the option... - if (opt.find_first_not_of(" ") == std::string::npos) continue; - - // split it on '='. if not found, we treat it as "yes" - pos = opt.find_first_of("="); - - if (pos == std::string::npos) { - key = opt; - val = "yes"; - } else { - key = opt.substr(0,pos); - val = opt.substr(pos+1); - } - options[key] = val; - } - - // connectors know what they are doing - if (type == "unix") { - this->connector = std::unique_ptr(new UnixsocketConnector(options)); - } else if (type == "http") { - this->connector = std::unique_ptr(new HTTPConnector(options)); - } else if (type == "zeromq") { +int RemoteBackend::build() +{ + std::vector parts; + std::string type; + std::string opts; + std::map options; + + // connstr is of format "type:options" + size_t pos; + pos = d_connstr.find_first_of(":"); + if (pos == std::string::npos) + throw PDNSException("Invalid connection string: malformed"); + + type = d_connstr.substr(0, pos); + opts = d_connstr.substr(pos + 1); + + // tokenize the string on comma + stringtok(parts, opts, ","); + + // find out some options and parse them while we're at it + for (const auto& opt : parts) { + std::string key, val; + // make sure there is something else than air in the option... + if (opt.find_first_not_of(" ") == std::string::npos) + continue; + + // split it on '='. if not found, we treat it as "yes" + pos = opt.find_first_of("="); + + if (pos == std::string::npos) { + key = opt; + val = "yes"; + } + else { + key = opt.substr(0, pos); + val = opt.substr(pos + 1); + } + options[key] = val; + } + + // connectors know what they are doing + if (type == "unix") { + this->connector = std::unique_ptr(new UnixsocketConnector(options)); + } + else if (type == "http") { + this->connector = std::unique_ptr(new HTTPConnector(options)); + } + else if (type == "zeromq") { #ifdef REMOTEBACKEND_ZEROMQ - this->connector = std::unique_ptr(new ZeroMQConnector(options)); + this->connector = std::unique_ptr(new ZeroMQConnector(options)); #else - throw PDNSException("Invalid connection string: zeromq connector support not enabled. Recompile with --enable-remotebackend-zeromq"); + throw PDNSException("Invalid connection string: zeromq connector support not enabled. Recompile with --enable-remotebackend-zeromq"); #endif - } else if (type == "pipe") { - this->connector = std::unique_ptr(new PipeConnector(options)); - } else { - throw PDNSException("Invalid connection string: unknown connector"); - } + } + else if (type == "pipe") { + this->connector = std::unique_ptr(new PipeConnector(options)); + } + else { + throw PDNSException("Invalid connection string: unknown connector"); + } - return -1; + return -1; } /** * The functions here are just remote json stubs that send and receive the method call * data is mainly left alone, some defaults are assumed. */ -void RemoteBackend::lookup(const QType &qtype, const DNSName& qdomain, int zoneId, DNSPacket *pkt_p) { - if (d_index != -1) - throw PDNSException("Attempt to lookup while one running"); - - string localIP="0.0.0.0"; - string remoteIP="0.0.0.0"; - string realRemote="0.0.0.0/0"; - - if (pkt_p) { - localIP=pkt_p->getLocal().toString(); - realRemote = pkt_p->getRealRemote().toString(); - remoteIP = pkt_p->getRemote().toString(); - } - - Json query = Json::object{ - { "method", "lookup" }, - { "parameters", Json::object{ - { "qtype", qtype.getName() }, - { "qname", qdomain.toString() }, - { "remote", remoteIP }, - { "local", localIP }, - { "real-remote", realRemote }, - { "zone-id", zoneId } - }} - }; - - if (this->send(query) == false || this->recv(d_result) == false) { - return; - } - - // OK. we have result parameters in result. do not process empty result. - if (d_result["result"].is_array() == false || d_result["result"].array_items().size() < 1) - return; - - d_index = 0; -} +void RemoteBackend::lookup(const QType& qtype, const DNSName& qdomain, int zoneId, DNSPacket* pkt_p) +{ + if (d_index != -1) + throw PDNSException("Attempt to lookup while one running"); -bool RemoteBackend::list(const DNSName& target, int domain_id, bool include_disabled) { - if (d_index != -1) - throw PDNSException("Attempt to lookup while one running"); - - Json query = Json::object{ - { "method", "list" }, - { "parameters", Json::object{ - { "zonename", target.toString() }, - { "domain_id", domain_id }, - { "include_disabled", include_disabled } - }} - }; - - if (this->send(query) == false || this->recv(d_result) == false) - return false; - if (d_result["result"].is_array() == false || d_result["result"].array_items().size() < 1) - return false; - - d_index = 0; - return true; -} + string localIP = "0.0.0.0"; + string remoteIP = "0.0.0.0"; + string realRemote = "0.0.0.0/0"; -bool RemoteBackend::get(DNSResourceRecord &rr) { - if (d_index == -1) return false; - - rr.qtype = stringFromJson(d_result["result"][d_index], "qtype"); - rr.qname = DNSName(stringFromJson(d_result["result"][d_index], "qname")); - rr.qclass = QClass::IN; - rr.content = stringFromJson(d_result["result"][d_index], "content"); - rr.ttl = d_result["result"][d_index]["ttl"].int_value(); - rr.domain_id = intFromJson(d_result["result"][d_index], "domain_id", -1); - if (d_dnssec) - rr.auth = intFromJson(d_result["result"][d_index], "auth", 1); - else - rr.auth = 1; - rr.scopeMask = d_result["result"][d_index]["scopeMask"].int_value(); - d_index++; - - // id index is out of bounds, we know the results end here. - if (d_index == static_cast(d_result["result"].array_items().size())) { - d_result = Json(); - d_index = -1; - } - return true; + if (pkt_p) { + localIP = pkt_p->getLocal().toString(); + realRemote = pkt_p->getRealRemote().toString(); + remoteIP = pkt_p->getRemote().toString(); + } + + Json query = Json::object{ + {"method", "lookup"}, + {"parameters", Json::object{{"qtype", qtype.getName()}, {"qname", qdomain.toString()}, {"remote", remoteIP}, {"local", localIP}, {"real-remote", realRemote}, {"zone-id", zoneId}}}}; + + if (this->send(query) == false || this->recv(d_result) == false) { + return; + } + + // OK. we have result parameters in result. do not process empty result. + if (d_result["result"].is_array() == false || d_result["result"].array_items().size() < 1) + return; + + d_index = 0; } -bool RemoteBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) { - // no point doing dnssec if it's not supported - if (d_dnssec == false) return false; - - Json query = Json::object{ - { "method", "getBeforeAndAfterNamesAbsolute" }, - { "parameters", Json::object { - { "id", Json(static_cast(id)) }, - { "qname", qname.toString() } - }} - }; - Json answer; - - if (this->send(query) == false || this->recv(answer) == false) - return false; - - unhashed = DNSName(stringFromJson(answer["result"], "unhashed")); - before.clear(); - after.clear(); - if (answer["result"]["before"] != Json()) - before = DNSName(stringFromJson(answer["result"], "before")); - if (answer["result"]["after"] != Json()) - after = DNSName(stringFromJson(answer["result"], "after")); - - return true; +bool RemoteBackend::list(const DNSName& target, int domain_id, bool include_disabled) +{ + if (d_index != -1) + throw PDNSException("Attempt to lookup while one running"); + + Json query = Json::object{ + {"method", "list"}, + {"parameters", Json::object{{"zonename", target.toString()}, {"domain_id", domain_id}, {"include_disabled", include_disabled}}}}; + + if (this->send(query) == false || this->recv(d_result) == false) + return false; + if (d_result["result"].is_array() == false || d_result["result"].array_items().size() < 1) + return false; + + d_index = 0; + return true; } -bool RemoteBackend::getAllDomainMetadata(const DNSName& name, std::map >& meta) { - Json query = Json::object{ - { "method", "getAllDomainMetadata" }, - { "parameters", Json::object { - { "name", name.toString() } - }} - }; - - if (this->send(query) == false) - return false; - - meta.clear(); - - Json answer; - // not mandatory to implement - if (this->recv(answer) == false) - return true; - - for(const auto& pair: answer["result"].object_items()) { - if (pair.second.is_array()) { - for(const auto& val: pair.second.array_items()) - meta[pair.first].push_back(asString(val)); - } else { - meta[pair.first].push_back(asString(pair.second)); - } - } - - return true; +bool RemoteBackend::get(DNSResourceRecord& rr) +{ + if (d_index == -1) + return false; + + rr.qtype = stringFromJson(d_result["result"][d_index], "qtype"); + rr.qname = DNSName(stringFromJson(d_result["result"][d_index], "qname")); + rr.qclass = QClass::IN; + rr.content = stringFromJson(d_result["result"][d_index], "content"); + rr.ttl = d_result["result"][d_index]["ttl"].int_value(); + rr.domain_id = intFromJson(d_result["result"][d_index], "domain_id", -1); + if (d_dnssec) + rr.auth = intFromJson(d_result["result"][d_index], "auth", 1); + else + rr.auth = 1; + rr.scopeMask = d_result["result"][d_index]["scopeMask"].int_value(); + d_index++; + + // id index is out of bounds, we know the results end here. + if (d_index == static_cast(d_result["result"].array_items().size())) { + d_result = Json(); + d_index = -1; + } + return true; } -bool RemoteBackend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) { - Json query = Json::object{ - { "method", "getDomainMetadata" }, - { "parameters", Json::object { - { "name", name.toString() }, - { "kind", kind } - }} - }; - - if (this->send(query) == false) - return false; - - meta.clear(); - - Json answer; - // not mandatory to implement - if (this->recv(answer) == false) - return true; - - if (answer["result"].is_array()) { - for(const auto& row: answer["result"].array_items()) - meta.push_back(row.string_value()); - } else if (answer["result"].is_string()) { - meta.push_back(answer["result"].string_value()); - } - - return true; +bool RemoteBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) +{ + // no point doing dnssec if it's not supported + if (d_dnssec == false) + return false; + + Json query = Json::object{ + {"method", "getBeforeAndAfterNamesAbsolute"}, + {"parameters", Json::object{{"id", Json(static_cast(id))}, {"qname", qname.toString()}}}}; + Json answer; + + if (this->send(query) == false || this->recv(answer) == false) + return false; + + unhashed = DNSName(stringFromJson(answer["result"], "unhashed")); + before.clear(); + after.clear(); + if (answer["result"]["before"] != Json()) + before = DNSName(stringFromJson(answer["result"], "before")); + if (answer["result"]["after"] != Json()) + after = DNSName(stringFromJson(answer["result"], "after")); + + return true; } -bool RemoteBackend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) { - Json query = Json::object{ - { "method", "setDomainMetadata" }, - { "parameters", Json::object { - { "name", name.toString() }, - { "kind", kind }, - { "value", meta } - }} - }; - - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; - - return boolFromJson(answer, "result", false); +bool RemoteBackend::getAllDomainMetadata(const DNSName& name, std::map>& meta) +{ + Json query = Json::object{ + {"method", "getAllDomainMetadata"}, + {"parameters", Json::object{{"name", name.toString()}}}}; + + if (this->send(query) == false) + return false; + + meta.clear(); + + Json answer; + // not mandatory to implement + if (this->recv(answer) == false) + return true; + + for (const auto& pair : answer["result"].object_items()) { + if (pair.second.is_array()) { + for (const auto& val : pair.second.array_items()) + meta[pair.first].push_back(asString(val)); + } + else { + meta[pair.first].push_back(asString(pair.second)); + } + } + + return true; } +bool RemoteBackend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) +{ + Json query = Json::object{ + {"method", "getDomainMetadata"}, + {"parameters", Json::object{{"name", name.toString()}, {"kind", kind}}}}; -bool RemoteBackend::getDomainKeys(const DNSName& name, std::vector& keys) { - // no point doing dnssec if it's not supported - if (d_dnssec == false) return false; + if (this->send(query) == false) + return false; - Json query = Json::object{ - { "method", "getDomainKeys" }, - { "parameters", Json::object{ - { "name", name.toString() } - }} - }; + meta.clear(); - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; + Json answer; + // not mandatory to implement + if (this->recv(answer) == false) + return true; - keys.clear(); + if (answer["result"].is_array()) { + for (const auto& row : answer["result"].array_items()) + meta.push_back(row.string_value()); + } + else if (answer["result"].is_string()) { + meta.push_back(answer["result"].string_value()); + } - for(const auto& jsonKey: answer["result"].array_items()) { - DNSBackend::KeyData key; - key.id = intFromJson(jsonKey, "id"); - key.flags = intFromJson(jsonKey, "flags"); - key.active = asBool(jsonKey["active"]); - key.published = boolFromJson(jsonKey, "published", true); - key.content = stringFromJson(jsonKey, "content"); - keys.push_back(key); - } + return true; +} + +bool RemoteBackend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector& meta) +{ + Json query = Json::object{ + {"method", "setDomainMetadata"}, + {"parameters", Json::object{{"name", name.toString()}, {"kind", kind}, {"value", meta}}}}; - return true; + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + + return boolFromJson(answer, "result", false); } -bool RemoteBackend::removeDomainKey(const DNSName& name, unsigned int id) { - // no point doing dnssec if it's not supported - if (d_dnssec == false) return false; +bool RemoteBackend::getDomainKeys(const DNSName& name, std::vector& keys) +{ + // no point doing dnssec if it's not supported + if (d_dnssec == false) + return false; - Json query = Json::object{ - { "method", "removeDomainKey" }, - { "parameters", Json::object { - { "name", name.toString() }, - { "id", static_cast(id) } - }} - }; + Json query = Json::object{ + {"method", "getDomainKeys"}, + {"parameters", Json::object{{"name", name.toString()}}}}; - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; - return true; + keys.clear(); + + for (const auto& jsonKey : answer["result"].array_items()) { + DNSBackend::KeyData key; + key.id = intFromJson(jsonKey, "id"); + key.flags = intFromJson(jsonKey, "flags"); + key.active = asBool(jsonKey["active"]); + key.published = boolFromJson(jsonKey, "published", true); + key.content = stringFromJson(jsonKey, "content"); + keys.push_back(key); + } + + return true; } -bool RemoteBackend::addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) { - // no point doing dnssec if it's not supported - if (d_dnssec == false) return false; - - Json query = Json::object{ - { "method", "addDomainKey" }, - { "parameters", Json::object { - { "name", name.toString() }, - { "key", Json::object { - { "flags", static_cast(key.flags) }, - { "active", key.active }, - { "published", key.published }, - { "content", key.content } - }} - }} - }; - - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; - - id = answer["result"].int_value(); - return id >= 0; +bool RemoteBackend::removeDomainKey(const DNSName& name, unsigned int id) +{ + // no point doing dnssec if it's not supported + if (d_dnssec == false) + return false; + + Json query = Json::object{ + {"method", "removeDomainKey"}, + {"parameters", Json::object{{"name", name.toString()}, {"id", static_cast(id)}}}}; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + + return true; } -bool RemoteBackend::activateDomainKey(const DNSName& name, unsigned int id) { - // no point doing dnssec if it's not supported - if (d_dnssec == false) return false; +bool RemoteBackend::addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) +{ + // no point doing dnssec if it's not supported + if (d_dnssec == false) + return false; - Json query = Json::object{ - { "method", "activateDomainKey" }, - { "parameters", Json::object { - { "name", name.toString() }, - { "id", static_cast(id) } - }} - }; + Json query = Json::object{ + {"method", "addDomainKey"}, + {"parameters", Json::object{{"name", name.toString()}, {"key", Json::object{{"flags", static_cast(key.flags)}, {"active", key.active}, {"published", key.published}, {"content", key.content}}}}}}; - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; - return true; + id = answer["result"].int_value(); + return id >= 0; } -bool RemoteBackend::deactivateDomainKey(const DNSName& name, unsigned int id) { - // no point doing dnssec if it's not supported - if (d_dnssec == false) return false; +bool RemoteBackend::activateDomainKey(const DNSName& name, unsigned int id) +{ + // no point doing dnssec if it's not supported + if (d_dnssec == false) + return false; - Json query = Json::object{ - { "method", "deactivateDomainKey" }, - { "parameters", Json::object { - { "name", name.toString() }, - { "id", static_cast(id) } - }} - }; + Json query = Json::object{ + {"method", "activateDomainKey"}, + {"parameters", Json::object{{"name", name.toString()}, {"id", static_cast(id)}}}}; - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; - return true; + return true; } -bool RemoteBackend::publishDomainKey(const DNSName& name, unsigned int id) { - // no point doing dnssec if it's not supported - if (d_dnssec == false) return false; +bool RemoteBackend::deactivateDomainKey(const DNSName& name, unsigned int id) +{ + // no point doing dnssec if it's not supported + if (d_dnssec == false) + return false; - Json query = Json::object{ - { "method", "publishDomainKey" }, - { "parameters", Json::object { - { "name", name.toString() }, - { "id", static_cast(id) } - }} - }; + Json query = Json::object{ + {"method", "deactivateDomainKey"}, + {"parameters", Json::object{{"name", name.toString()}, {"id", static_cast(id)}}}}; - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; - return true; + return true; } -bool RemoteBackend::unpublishDomainKey(const DNSName& name, unsigned int id) { - // no point doing dnssec if it's not supported - if (d_dnssec == false) return false; +bool RemoteBackend::publishDomainKey(const DNSName& name, unsigned int id) +{ + // no point doing dnssec if it's not supported + if (d_dnssec == false) + return false; - Json query = Json::object{ - { "method", "unpublishDomainKey" }, - { "parameters", Json::object { - { "name", name.toString() }, - { "id", static_cast(id) } - }} - }; + Json query = Json::object{ + {"method", "publishDomainKey"}, + {"parameters", Json::object{{"name", name.toString()}, {"id", static_cast(id)}}}}; - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; - return true; + return true; } +bool RemoteBackend::unpublishDomainKey(const DNSName& name, unsigned int id) +{ + // no point doing dnssec if it's not supported + if (d_dnssec == false) + return false; + + Json query = Json::object{ + {"method", "unpublishDomainKey"}, + {"parameters", Json::object{{"name", name.toString()}, {"id", static_cast(id)}}}}; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + + return true; +} -bool RemoteBackend::doesDNSSEC() { - return d_dnssec; +bool RemoteBackend::doesDNSSEC() +{ + return d_dnssec; } -bool RemoteBackend::getTSIGKey(const DNSName& name, DNSName* algorithm, std::string* content) { - // no point doing dnssec if it's not supported - if (d_dnssec == false) return false; +bool RemoteBackend::getTSIGKey(const DNSName& name, DNSName* algorithm, std::string* content) +{ + // no point doing dnssec if it's not supported + if (d_dnssec == false) + return false; - Json query = Json::object{ - { "method", "getTSIGKey" }, - { "parameters", Json::object { - { "name", name.toString() } - }} - }; + Json query = Json::object{ + {"method", "getTSIGKey"}, + {"parameters", Json::object{{"name", name.toString()}}}}; - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; - (*algorithm) = DNSName(stringFromJson(answer["result"], "algorithm")); - (*content) = stringFromJson(answer["result"], "content"); + (*algorithm) = DNSName(stringFromJson(answer["result"], "algorithm")); + (*content) = stringFromJson(answer["result"], "content"); - return true; + return true; } -bool RemoteBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const std::string& content) { - // no point doing dnssec if it's not supported - if (d_dnssec == false) return false; +bool RemoteBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const std::string& content) +{ + // no point doing dnssec if it's not supported + if (d_dnssec == false) + return false; - Json query = Json::object{ - { "method", "setTSIGKey" }, - { "parameters", Json::object { - { "name", name.toString() }, - { "algorithm", algorithm.toString() }, - { "content", content } - }} - }; + Json query = Json::object{ + {"method", "setTSIGKey"}, + {"parameters", Json::object{{"name", name.toString()}, {"algorithm", algorithm.toString()}, {"content", content}}}}; - Json answer; - if (connector->send(query) == false || connector->recv(answer) == false) - return false; + Json answer; + if (connector->send(query) == false || connector->recv(answer) == false) + return false; - return true; + return true; } -bool RemoteBackend::deleteTSIGKey(const DNSName& name) { - // no point doing dnssec if it's not supported - if (d_dnssec == false) return false; - Json query = Json::object{ - { "method", "deleteTSIGKey" }, - { "parameters", Json::object { - { "name", name.toString() } - }} - }; - - Json answer; - if (connector->send(query) == false || connector->recv(answer) == false) - return false; - - return true; +bool RemoteBackend::deleteTSIGKey(const DNSName& name) +{ + // no point doing dnssec if it's not supported + if (d_dnssec == false) + return false; + Json query = Json::object{ + {"method", "deleteTSIGKey"}, + {"parameters", Json::object{{"name", name.toString()}}}}; + + Json answer; + if (connector->send(query) == false || connector->recv(answer) == false) + return false; + + return true; } -bool RemoteBackend::getTSIGKeys(std::vector& keys) { - // no point doing dnssec if it's not supported - if (d_dnssec == false) return false; - Json query = Json::object{ - { "method", "getTSIGKeys" }, - { "parameters", Json::object { - }} - }; - - Json answer; - if (connector->send(query) == false || connector->recv(answer) == false) - return false; - - for(const auto& jsonKey: answer["result"].array_items()) { - struct TSIGKey key; - key.name = DNSName(stringFromJson(jsonKey, "name")); - key.algorithm = DNSName(stringFromJson(jsonKey, "algorithm")); - key.key = stringFromJson(jsonKey, "content"); - keys.push_back(key); - } - - return true; +bool RemoteBackend::getTSIGKeys(std::vector& keys) +{ + // no point doing dnssec if it's not supported + if (d_dnssec == false) + return false; + Json query = Json::object{ + {"method", "getTSIGKeys"}, + {"parameters", Json::object{}}}; + + Json answer; + if (connector->send(query) == false || connector->recv(answer) == false) + return false; + + for (const auto& jsonKey : answer["result"].array_items()) { + struct TSIGKey key; + key.name = DNSName(stringFromJson(jsonKey, "name")); + key.algorithm = DNSName(stringFromJson(jsonKey, "algorithm")); + key.key = stringFromJson(jsonKey, "content"); + keys.push_back(key); + } + + return true; } -void RemoteBackend::parseDomainInfo(const Json &obj, DomainInfo &di) +void RemoteBackend::parseDomainInfo(const Json& obj, DomainInfo& di) { - di.id = intFromJson(obj, "id", -1); - di.zone = DNSName(stringFromJson(obj, "zone")); - for(const auto& master: obj["masters"].array_items()) - di.masters.push_back(ComboAddress(master.string_value(), 53)); - - di.notified_serial = static_cast(doubleFromJson(obj, "notified_serial", 0)); - di.serial = static_cast(obj["serial"].number_value()); - di.last_check = static_cast(obj["last_check"].number_value()); - - string kind = ""; - if (obj["kind"].is_string()) { - kind = stringFromJson(obj, "kind"); - } - if (kind == "master") { - di.kind = DomainInfo::Master; - } else if (kind == "slave") { - di.kind = DomainInfo::Slave; - } else { - di.kind = DomainInfo::Native; - } - di.backend = this; + di.id = intFromJson(obj, "id", -1); + di.zone = DNSName(stringFromJson(obj, "zone")); + for (const auto& master : obj["masters"].array_items()) + di.masters.push_back(ComboAddress(master.string_value(), 53)); + + di.notified_serial = static_cast(doubleFromJson(obj, "notified_serial", 0)); + di.serial = static_cast(obj["serial"].number_value()); + di.last_check = static_cast(obj["last_check"].number_value()); + + string kind = ""; + if (obj["kind"].is_string()) { + kind = stringFromJson(obj, "kind"); + } + if (kind == "master") { + di.kind = DomainInfo::Master; + } + else if (kind == "slave") { + di.kind = DomainInfo::Slave; + } + else { + di.kind = DomainInfo::Native; + } + di.backend = this; } -bool RemoteBackend::getDomainInfo(const DNSName& domain, DomainInfo &di, bool getSerial) { - if (domain.empty()) return false; - Json query = Json::object{ - { "method", "getDomainInfo" }, - { "parameters", Json::object { - { "name", domain.toString() } - }} - }; - - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; - - this->parseDomainInfo(answer["result"], di); - return true; +bool RemoteBackend::getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial) +{ + if (domain.empty()) + return false; + Json query = Json::object{ + {"method", "getDomainInfo"}, + {"parameters", Json::object{{"name", domain.toString()}}}}; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + + this->parseDomainInfo(answer["result"], di); + return true; } -void RemoteBackend::setNotified(uint32_t id, uint32_t serial) { - Json query = Json::object{ - { "method", "setNotified" }, - { "parameters", Json::object { - { "id", static_cast(id) }, - { "serial", static_cast(serial) } - }} - }; - - Json answer; - if (this->send(query) == false || this->recv(answer) == false) { - g_log<(id)}, {"serial", static_cast(serial)}}}}; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) { + g_log << Logger::Error << kBackendId << " Failed to execute RPC for RemoteBackend::setNotified(" << id << "," << serial << ")" << endl; + } } -bool RemoteBackend::superMasterBackend(const string &ip, const DNSName& domain, const vector&nsset, string* nameserver, string *account, DNSBackend **ddb) +bool RemoteBackend::superMasterBackend(const string& ip, const DNSName& domain, const vector& nsset, string* nameserver, string* account, DNSBackend** ddb) { - Json::array rrset; - - for(const auto& ns: nsset) { - rrset.push_back(Json::object{ - { "qtype", ns.qtype.getName() }, - { "qname", ns.qname.toString() }, - { "qclass", QClass::IN }, - { "content", ns.content }, - { "ttl", static_cast(ns.ttl) }, - { "auth", ns.auth } - }); - } - - Json query = Json::object{ - { "method", "superMasterBackend" }, - { "parameters", Json::object { - { "ip", ip }, - { "domain", domain.toString() }, - { "nsset", rrset } - }} - }; - - *ddb = 0; - - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; - - // we are the backend - *ddb = this; - - // we allow simple true as well... - if (answer["result"].is_object()) { - *account = stringFromJson(answer["result"], "account"); - *nameserver = stringFromJson(answer["result"], "nameserver"); - } - - return true; + Json::array rrset; + + for (const auto& ns : nsset) { + rrset.push_back(Json::object{ + {"qtype", ns.qtype.getName()}, + {"qname", ns.qname.toString()}, + {"qclass", QClass::IN}, + {"content", ns.content}, + {"ttl", static_cast(ns.ttl)}, + {"auth", ns.auth}}); + } + + Json query = Json::object{ + {"method", "superMasterBackend"}, + {"parameters", Json::object{{"ip", ip}, {"domain", domain.toString()}, {"nsset", rrset}}}}; + + *ddb = 0; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + + // we are the backend + *ddb = this; + + // we allow simple true as well... + if (answer["result"].is_object()) { + *account = stringFromJson(answer["result"], "account"); + *nameserver = stringFromJson(answer["result"], "nameserver"); + } + + return true; } -bool RemoteBackend::createSlaveDomain(const string &ip, const DNSName& domain, const string& nameserver, const string &account) { - Json query = Json::object{ - { "method", "createSlaveDomain" }, - { "parameters", Json::object { - { "ip", ip }, - { "domain", domain.toString() }, - { "nameserver", nameserver }, - { "account", account }, - }} - }; - - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; - return true; +bool RemoteBackend::createSlaveDomain(const string& ip, const DNSName& domain, const string& nameserver, const string& account) +{ + Json query = Json::object{ + {"method", "createSlaveDomain"}, + {"parameters", Json::object{ + {"ip", ip}, + {"domain", domain.toString()}, + {"nameserver", nameserver}, + {"account", account}, + }}}; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + return true; } -bool RemoteBackend::replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qtype, const vector& rrset) { - Json::array json_rrset; - for(const auto& rr: rrset) { - json_rrset.push_back(Json::object{ - { "qtype", rr.qtype.getName() }, - { "qname", rr.qname.toString() }, - { "qclass", QClass::IN }, - { "content", rr.content }, - { "ttl", static_cast(rr.ttl) }, - { "auth", rr.auth } - }); - } - - Json query = Json::object{ - { "method", "replaceRRSet" }, - { "parameters", Json::object { - { "domain_id", static_cast(domain_id) }, - { "qname", qname.toString() }, - { "qtype", qtype.getName() }, - { "trxid", static_cast(d_trxid) }, - { "rrset", json_rrset } - }} - }; - - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; - - return true; +bool RemoteBackend::replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qtype, const vector& rrset) +{ + Json::array json_rrset; + for (const auto& rr : rrset) { + json_rrset.push_back(Json::object{ + {"qtype", rr.qtype.getName()}, + {"qname", rr.qname.toString()}, + {"qclass", QClass::IN}, + {"content", rr.content}, + {"ttl", static_cast(rr.ttl)}, + {"auth", rr.auth}}); + } + + Json query = Json::object{ + {"method", "replaceRRSet"}, + {"parameters", Json::object{{"domain_id", static_cast(domain_id)}, {"qname", qname.toString()}, {"qtype", qtype.getName()}, {"trxid", static_cast(d_trxid)}, {"rrset", json_rrset}}}}; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + + return true; } -bool RemoteBackend::feedRecord(const DNSResourceRecord &rr, const DNSName &ordername, bool ordernameIsNSEC3) { - Json query = Json::object{ - { "method", "feedRecord" }, - { "parameters", Json::object{ - { "rr", Json::object{ - { "qtype", rr.qtype.getName() }, - { "qname", rr.qname.toString() }, - { "qclass", QClass::IN }, - { "content", rr.content }, - { "ttl", static_cast(rr.ttl) }, - { "auth", rr.auth }, - { "ordername", (ordername.empty()?Json():ordername.toString()) } - }}, - { "trxid", static_cast(d_trxid) }, - }} - }; - - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; - return true; // XXX FIXME this API should not return 'true' I think -ahu +bool RemoteBackend::feedRecord(const DNSResourceRecord& rr, const DNSName& ordername, bool ordernameIsNSEC3) +{ + Json query = Json::object{ + {"method", "feedRecord"}, + {"parameters", Json::object{ + {"rr", Json::object{{"qtype", rr.qtype.getName()}, {"qname", rr.qname.toString()}, {"qclass", QClass::IN}, {"content", rr.content}, {"ttl", static_cast(rr.ttl)}, {"auth", rr.auth}, {"ordername", (ordername.empty() ? Json() : ordername.toString())}}}, + {"trxid", static_cast(d_trxid)}, + }}}; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + return true; // XXX FIXME this API should not return 'true' I think -ahu } -bool RemoteBackend::feedEnts(int domain_id, map& nonterm) { - Json::array nts; - - for(const auto& t: nonterm) - nts.push_back(Json::object{ - { "nonterm", t.first.toString() }, - { "auth", t.second } - }); - - Json query = Json::object{ - { "method", "feedEnts" }, - { "parameters", Json::object{ - { "domain_id", domain_id }, - { "trxid", static_cast(d_trxid) }, - { "nonterm", nts } - }}, - }; - - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; - return true; +bool RemoteBackend::feedEnts(int domain_id, map& nonterm) +{ + Json::array nts; + + for (const auto& t : nonterm) + nts.push_back(Json::object{ + {"nonterm", t.first.toString()}, + {"auth", t.second}}); + + Json query = Json::object{ + {"method", "feedEnts"}, + {"parameters", Json::object{{"domain_id", domain_id}, {"trxid", static_cast(d_trxid)}, {"nonterm", nts}}}, + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + return true; } -bool RemoteBackend::feedEnts3(int domain_id, const DNSName& domain, map& nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) { - Json::array nts; - - for(const auto& t: nonterm) - nts.push_back(Json::object{ - { "nonterm", t.first.toString() }, - { "auth", t.second } - }); - - Json query = Json::object{ - { "method", "feedEnts3" }, - { "parameters", Json::object{ - { "domain_id", domain_id }, - { "domain", domain.toString() }, - { "times", ns3prc.d_iterations }, - { "salt", ns3prc.d_salt }, - { "narrow", narrow }, - { "trxid", static_cast(d_trxid) }, - { "nonterm", nts } - }}, - }; - - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; - return true; +bool RemoteBackend::feedEnts3(int domain_id, const DNSName& domain, map& nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) +{ + Json::array nts; + + for (const auto& t : nonterm) + nts.push_back(Json::object{ + {"nonterm", t.first.toString()}, + {"auth", t.second}}); + + Json query = Json::object{ + {"method", "feedEnts3"}, + {"parameters", Json::object{{"domain_id", domain_id}, {"domain", domain.toString()}, {"times", ns3prc.d_iterations}, {"salt", ns3prc.d_salt}, {"narrow", narrow}, {"trxid", static_cast(d_trxid)}, {"nonterm", nts}}}, + }; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + return true; } -bool RemoteBackend::startTransaction(const DNSName& domain, int domain_id) { - this->d_trxid = time((time_t*)NULL); - - Json query = Json::object{ - { "method", "startTransaction" }, - { "parameters", Json::object{ - { "domain", domain.toString() }, - { "domain_id", domain_id }, - { "trxid", static_cast(d_trxid) } - }} - }; - - Json answer; - if (this->send(query) == false || this->recv(answer) == false) { - d_trxid = -1; - return false; - } - return true; +bool RemoteBackend::startTransaction(const DNSName& domain, int domain_id) +{ + this->d_trxid = time((time_t*)NULL); + + Json query = Json::object{ + {"method", "startTransaction"}, + {"parameters", Json::object{{"domain", domain.toString()}, {"domain_id", domain_id}, {"trxid", static_cast(d_trxid)}}}}; + Json answer; + if (this->send(query) == false || this->recv(answer) == false) { + d_trxid = -1; + return false; + } + return true; } -bool RemoteBackend::commitTransaction() { - if (d_trxid == -1) return false; - - Json query = Json::object{ - { "method", "commitTransaction" }, - { "parameters", Json::object{ - { "trxid", static_cast(d_trxid) } - }} - }; - - d_trxid = -1; - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; - return true; +bool RemoteBackend::commitTransaction() +{ + if (d_trxid == -1) + return false; + + Json query = Json::object{ + {"method", "commitTransaction"}, + {"parameters", Json::object{{"trxid", static_cast(d_trxid)}}}}; + + d_trxid = -1; + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + return true; } -bool RemoteBackend::abortTransaction() { - if (d_trxid == -1) return false; - - Json query = Json::object{ - { "method", "abortTransaction" }, - { "parameters", Json::object{ - { "trxid", static_cast(d_trxid) } - }} - }; - - d_trxid = -1; - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return false; - return true; +bool RemoteBackend::abortTransaction() +{ + if (d_trxid == -1) + return false; + + Json query = Json::object{ + {"method", "abortTransaction"}, + {"parameters", Json::object{{"trxid", static_cast(d_trxid)}}}}; + + d_trxid = -1; + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return false; + return true; } -string RemoteBackend::directBackendCmd(const string& querystr) { - Json query = Json::object{ - { "method", "directBackendCmd" }, - { "parameters", Json::object{ - { "query", querystr } - }} - }; +string RemoteBackend::directBackendCmd(const string& querystr) +{ + Json query = Json::object{ + {"method", "directBackendCmd"}, + {"parameters", Json::object{{"query", querystr}}}}; - Json answer; - if (this->send(query) == false || this->recv(answer) == false) - return "backend command failed"; + Json answer; + if (this->send(query) == false || this->recv(answer) == false) + return "backend command failed"; - return asString(answer["result"]); + return asString(answer["result"]); } -bool RemoteBackend::searchRecords(const string &pattern, int maxResults, vector& result) +bool RemoteBackend::searchRecords(const string& pattern, int maxResults, vector& result) { Json query = Json::object{ - { "method", "searchRecords" }, - { "parameters", Json::object{ - { "pattern", pattern }, - { "maxResults", maxResults } - }} - }; + {"method", "searchRecords"}, + {"parameters", Json::object{{"pattern", pattern}, {"maxResults", maxResults}}}}; Json answer; if (this->send(query) == false || this->recv(answer) == false) @@ -908,7 +833,7 @@ bool RemoteBackend::searchRecords(const string &pattern, int maxResults, vector< if (answer["result"].is_array() == false) return false; - for(const auto& row: answer["result"].array_items()) { + for (const auto& row : answer["result"].array_items()) { DNSResourceRecord rr; rr.qtype = stringFromJson(row, "qtype"); rr.qname = DNSName(stringFromJson(row, "qname")); @@ -927,20 +852,17 @@ bool RemoteBackend::searchRecords(const string &pattern, int maxResults, vector< return true; } -bool RemoteBackend::searchComments(const string &pattern, int maxResults, vector& result) +bool RemoteBackend::searchComments(const string& pattern, int maxResults, vector& result) { // FIXME: Implement Comment API return false; } -void RemoteBackend::getAllDomains(vector *domains, bool include_disabled) +void RemoteBackend::getAllDomains(vector* domains, bool include_disabled) { Json query = Json::object{ - { "method", "getAllDomains" }, - { "parameters", Json::object{ - { "include_disabled", include_disabled } - }} - }; + {"method", "getAllDomains"}, + {"parameters", Json::object{{"include_disabled", include_disabled}}}}; Json answer; if (this->send(query) == false || this->recv(answer) == false) @@ -948,15 +870,15 @@ void RemoteBackend::getAllDomains(vector *domains, bool include_disa if (answer["result"].is_array() == false) return; - - for(const auto& row: answer["result"].array_items()) { + + for (const auto& row : answer["result"].array_items()) { DomainInfo di; this->parseDomainInfo(row, di); domains->push_back(di); } } -void RemoteBackend::alsoNotifies(const DNSName &domain, set *ips) +void RemoteBackend::alsoNotifies(const DNSName& domain, set* ips) { std::vector meta; getDomainMetadata(domain, "ALSO-NOTIFY", meta); @@ -966,8 +888,8 @@ void RemoteBackend::alsoNotifies(const DNSName &domain, set *ips) void RemoteBackend::getUpdatedMasters(vector* domains) { Json query = Json::object{ - { "method", "getUpdatedMasters" }, - { "parameters", Json::object{ } }, + {"method", "getUpdatedMasters"}, + {"parameters", Json::object{}}, }; Json answer; @@ -977,17 +899,18 @@ void RemoteBackend::getUpdatedMasters(vector* domains) if (answer["result"].is_array() == false) return; - for(const auto& row: answer["result"].array_items()) { + for (const auto& row : answer["result"].array_items()) { DomainInfo di; this->parseDomainInfo(row, di); domains->push_back(di); } } -void RemoteBackend::getUnfreshSlaveInfos(vector* domains) { +void RemoteBackend::getUnfreshSlaveInfos(vector* domains) +{ Json query = Json::object{ - { "method", "getUnfreshSlaveInfos" }, - { "parameters", Json::object{ } }, + {"method", "getUnfreshSlaveInfos"}, + {"parameters", Json::object{}}, }; Json answer; @@ -997,71 +920,68 @@ void RemoteBackend::getUnfreshSlaveInfos(vector* domains) { if (answer["result"].is_array() == false) return; - for(const auto& row: answer["result"].array_items()) { + for (const auto& row : answer["result"].array_items()) { DomainInfo di; this->parseDomainInfo(row, di); domains->push_back(di); } } -void RemoteBackend::setFresh(uint32_t domain_id) { - Json query = Json::object{ - { "method", "setFresh" }, - { "parameters", Json::object { - { "id", static_cast(domain_id) } - }} - }; - - Json answer; - if (this->send(query) == false || this->recv(answer) == false) { - g_log<(domain_id)}}}}; + + Json answer; + if (this->send(query) == false || this->recv(answer) == false) { + g_log << Logger::Error << kBackendId << " Failed to execute RPC for RemoteBackend::setFresh(" << domain_id << ")" << endl; + } } -DNSBackend *RemoteBackend::maker() +DNSBackend* RemoteBackend::maker() { - try { - return new RemoteBackend(); - } - catch(...) { - g_log< options); - virtual ~UnixsocketConnector(); - virtual int send_message(const Json &input); - virtual int recv_message(Json &output); - private: - ssize_t read(std::string &data); - ssize_t write(const std::string &data); - void reconnect(); - std::map options; - int fd; - std::string path; - bool connected; - int timeout; +class UnixsocketConnector : public Connector +{ +public: + UnixsocketConnector(std::map options); + virtual ~UnixsocketConnector(); + virtual int send_message(const Json& input); + virtual int recv_message(Json& output); + +private: + ssize_t read(std::string& data); + ssize_t write(const std::string& data); + void reconnect(); + std::map options; + int fd; + std::string path; + bool connected; + int timeout; }; -class HTTPConnector: public Connector { - public: - - HTTPConnector(std::map options); +class HTTPConnector : public Connector +{ +public: + HTTPConnector(std::map options); ~HTTPConnector(); - virtual int send_message(const Json &input); - virtual int recv_message(Json &output); - private: - std::string d_url; - std::string d_url_suffix; - std::string d_data; - int timeout; - bool d_post; - bool d_post_json; - void restful_requestbuilder(const std::string &method, const Json ¶meters, YaHTTP::Request& req); - void post_requestbuilder(const Json &input, YaHTTP::Request& req); - void addUrlComponent(const Json ¶meters, const string& element, std::stringstream& ss); - std::string buildMemberListArgs(std::string prefix, const Json& args); - std::unique_ptr d_socket; - ComboAddress d_addr; - std::string d_host; - uint16_t d_port; + virtual int send_message(const Json& input); + virtual int recv_message(Json& output); + +private: + std::string d_url; + std::string d_url_suffix; + std::string d_data; + int timeout; + bool d_post; + bool d_post_json; + void restful_requestbuilder(const std::string& method, const Json& parameters, YaHTTP::Request& req); + void post_requestbuilder(const Json& input, YaHTTP::Request& req); + void addUrlComponent(const Json& parameters, const string& element, std::stringstream& ss); + std::string buildMemberListArgs(std::string prefix, const Json& args); + std::unique_ptr d_socket; + ComboAddress d_addr; + std::string d_host; + uint16_t d_port; }; #ifdef REMOTEBACKEND_ZEROMQ -class ZeroMQConnector: public Connector { - public: - ZeroMQConnector(std::map options); - virtual ~ZeroMQConnector(); - virtual int send_message(const Json &input); - virtual int recv_message(Json &output); - private: - void connect(); - std::string d_endpoint; - int d_timeout; - int d_timespent; - std::map d_options; - std::unique_ptr d_ctx; - std::unique_ptr d_sock; +class ZeroMQConnector : public Connector +{ +public: + ZeroMQConnector(std::map options); + virtual ~ZeroMQConnector(); + virtual int send_message(const Json& input); + virtual int recv_message(Json& output); + +private: + void connect(); + std::string d_endpoint; + int d_timeout; + int d_timespent; + std::map d_options; + std::unique_ptr d_ctx; + std::unique_ptr d_sock; }; #endif -class PipeConnector: public Connector { - public: - - PipeConnector(std::map options); +class PipeConnector : public Connector +{ +public: + PipeConnector(std::map options); ~PipeConnector(); - virtual int send_message(const Json &input); - virtual int recv_message(Json &output); - - private: + virtual int send_message(const Json& input); + virtual int recv_message(Json& output); +private: void launch(); bool checkStatus(); std::string command; - std::map options; - + std::map options; + int d_fd1[2], d_fd2[2]; int d_pid; int d_timeout; - std::unique_ptr d_fp{nullptr, fclose}; + std::unique_ptr d_fp{nullptr, fclose}; }; class RemoteBackend : public DNSBackend { - public: - RemoteBackend(const std::string &suffix=""); +public: + RemoteBackend(const std::string& suffix = ""); ~RemoteBackend(); - void lookup(const QType &qtype, const DNSName& qdomain, int zoneId=-1, DNSPacket *pkt_p=nullptr) override; - bool get(DNSResourceRecord &rr) override; - bool list(const DNSName& target, int domain_id, bool include_disabled=false) override; + void lookup(const QType& qtype, const DNSName& qdomain, int zoneId = -1, DNSPacket* pkt_p = nullptr) override; + bool get(DNSResourceRecord& rr) override; + bool list(const DNSName& target, int domain_id, bool include_disabled = false) override; - bool getAllDomainMetadata(const DNSName& name, std::map >& meta) override; + bool getAllDomainMetadata(const DNSName& name, std::map>& meta) override; bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) override; bool getDomainKeys(const DNSName& name, std::vector& keys) override; bool getTSIGKey(const DNSName& name, DNSName* algorithm, std::string* content) override; bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) override; - bool setDomainMetadata(const DNSName& name, const string& kind, const std::vector >& meta) override; + bool setDomainMetadata(const DNSName& name, const string& kind, const std::vector>& meta) override; bool removeDomainKey(const DNSName& name, unsigned int id) override; bool addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) override; bool activateDomainKey(const DNSName& name, unsigned int id) override; bool deactivateDomainKey(const DNSName& name, unsigned int id) override; bool publishDomainKey(const DNSName& name, unsigned int id) override; bool unpublishDomainKey(const DNSName& name, unsigned int id) override; - bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial=true ) override; + bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial = true) override; void setNotified(uint32_t id, uint32_t serial) override; bool doesDNSSEC() override; - bool superMasterBackend(const string &ip, const DNSName& domain, const vector&nsset, string *nameserver, string *account, DNSBackend **ddb) override; - bool createSlaveDomain(const string &ip, const DNSName& domain, const string& nameserver, const string &account) override; + bool superMasterBackend(const string& ip, const DNSName& domain, const vector& nsset, string* nameserver, string* account, DNSBackend** ddb) override; + bool createSlaveDomain(const string& ip, const DNSName& domain, const string& nameserver, const string& account) override; bool replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector& rrset) override; - bool feedRecord(const DNSResourceRecord &r, const DNSName &ordername, bool ordernameIsNSEC3=false) override; - bool feedEnts(int domain_id, map& nonterm) override; - bool feedEnts3(int domain_id, const DNSName& domain, map& nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) override; + bool feedRecord(const DNSResourceRecord& r, const DNSName& ordername, bool ordernameIsNSEC3 = false) override; + bool feedEnts(int domain_id, map& nonterm) override; + bool feedEnts3(int domain_id, const DNSName& domain, map& nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) override; bool startTransaction(const DNSName& domain, int domain_id) override; bool commitTransaction() override; bool abortTransaction() override; bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) override; bool deleteTSIGKey(const DNSName& name) override; - bool getTSIGKeys(std::vector< struct TSIGKey > &keys) override; + bool getTSIGKeys(std::vector& keys) override; string directBackendCmd(const string& querystr) override; - bool searchRecords(const string &pattern, int maxResults, vector& result) override; - bool searchComments(const string &pattern, int maxResults, vector& result) override; - void getAllDomains(vector *domains, bool include_disabled=false) override; + bool searchRecords(const string& pattern, int maxResults, vector& result) override; + bool searchComments(const string& pattern, int maxResults, vector& result) override; + void getAllDomains(vector* domains, bool include_disabled = false) override; void getUpdatedMasters(vector* domains) override; - void alsoNotifies(const DNSName &domain, set *ips) override; + void alsoNotifies(const DNSName& domain, set* ips) override; void getUnfreshSlaveInfos(vector* domains) override; void setFresh(uint32_t domain_id) override; - static DNSBackend *maker(); - - private: - int build(); - std::unique_ptr connector; - bool d_dnssec; - Json d_result; - int d_index; - int64_t d_trxid; - std::string d_connstr; - - bool send(Json &value); - bool recv(Json &value); - void makeErrorAndThrow(Json &value); - - string asString(const Json& value) { - if (value.is_number()) return std::to_string(value.int_value()); - if (value.is_bool()) return (value.bool_value()?"1":"0"); - if (value.is_string()) return value.string_value(); - throw JsonException("Json value not convertible to String"); - }; - - bool asBool(const Json& value) { - if (value.is_bool()) return value.bool_value(); - try { - string val = asString(value); - if (val == "0") return false; - if (val == "1") return true; - } catch (const JsonException&) {}; - throw JsonException("Json value not convertible to boolean"); + static DNSBackend* maker(); + +private: + int build(); + std::unique_ptr connector; + bool d_dnssec; + Json d_result; + int d_index; + int64_t d_trxid; + std::string d_connstr; + + bool send(Json& value); + bool recv(Json& value); + void makeErrorAndThrow(Json& value); + + string asString(const Json& value) + { + if (value.is_number()) + return std::to_string(value.int_value()); + if (value.is_bool()) + return (value.bool_value() ? "1" : "0"); + if (value.is_string()) + return value.string_value(); + throw JsonException("Json value not convertible to String"); + }; + + bool asBool(const Json& value) + { + if (value.is_bool()) + return value.bool_value(); + try { + string val = asString(value); + if (val == "0") + return false; + if (val == "1") + return true; + } + catch (const JsonException&) { }; + throw JsonException("Json value not convertible to boolean"); + }; - void parseDomainInfo(const json11::Json &obj, DomainInfo &di); + void parseDomainInfo(const json11::Json& obj, DomainInfo& di); }; diff --git a/modules/remotebackend/test-remotebackend-http.cc b/modules/remotebackend/test-remotebackend-http.cc index e92d4bbe4c..796737dc38 100644 --- a/modules/remotebackend/test-remotebackend-http.cc +++ b/modules/remotebackend/test-remotebackend-http.cc @@ -38,7 +38,7 @@ StatBag S; AuthPacketCache PC; AuthQueryCache QC; -ArgvMap &arg() +ArgvMap& arg() { static ArgvMap arg; return arg; @@ -46,11 +46,11 @@ ArgvMap &arg() class RemoteLoader { - public: - RemoteLoader(); +public: + RemoteLoader(); }; -DNSBackend *be; +DNSBackend* be; #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MAIN @@ -61,23 +61,26 @@ DNSBackend *be; #include -struct RemotebackendSetup { - RemotebackendSetup() { - be = 0; - try { - // setup minimum arguments - ::arg().set("module-dir")="./.libs"; - new RemoteLoader(); - BackendMakers().launch("remote"); - // then get us a instance of it - ::arg().set("remote-connection-string")="http:url=http://localhost:62434/dns"; - ::arg().set("remote-dnssec")="yes"; - be = BackendMakers().all()[0]; - } catch (PDNSException &ex) { - BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason ); - }; +struct RemotebackendSetup +{ + RemotebackendSetup() + { + be = 0; + try { + // setup minimum arguments + ::arg().set("module-dir") = "./.libs"; + new RemoteLoader(); + BackendMakers().launch("remote"); + // then get us a instance of it + ::arg().set("remote-connection-string") = "http:url=http://localhost:62434/dns"; + ::arg().set("remote-dnssec") = "yes"; + be = BackendMakers().all()[0]; } - ~RemotebackendSetup() { } + catch (PDNSException& ex) { + BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason); + }; + } + ~RemotebackendSetup() {} }; -BOOST_GLOBAL_FIXTURE( RemotebackendSetup ); +BOOST_GLOBAL_FIXTURE(RemotebackendSetup); diff --git a/modules/remotebackend/test-remotebackend-json.cc b/modules/remotebackend/test-remotebackend-json.cc index fb56ee10a1..26f905c476 100644 --- a/modules/remotebackend/test-remotebackend-json.cc +++ b/modules/remotebackend/test-remotebackend-json.cc @@ -37,7 +37,7 @@ StatBag S; AuthPacketCache PC; AuthQueryCache QC; -ArgvMap &arg() +ArgvMap& arg() { static ArgvMap arg; return arg; @@ -45,11 +45,11 @@ ArgvMap &arg() class RemoteLoader { - public: - RemoteLoader(); +public: + RemoteLoader(); }; -DNSBackend *be; +DNSBackend* be; #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MAIN @@ -60,23 +60,26 @@ DNSBackend *be; #include -struct RemotebackendSetup { - RemotebackendSetup() { - be = 0; - try { - // setup minimum arguments - ::arg().set("module-dir")="./.libs"; - new RemoteLoader(); - BackendMakers().launch("remote"); - // then get us a instance of it - ::arg().set("remote-connection-string")="http:url=http://localhost:62434/dns/endpoint.json,post=1,post_json=1"; - ::arg().set("remote-dnssec")="yes"; - be = BackendMakers().all()[0]; - } catch (PDNSException &ex) { - BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason ); - }; +struct RemotebackendSetup +{ + RemotebackendSetup() + { + be = 0; + try { + // setup minimum arguments + ::arg().set("module-dir") = "./.libs"; + new RemoteLoader(); + BackendMakers().launch("remote"); + // then get us a instance of it + ::arg().set("remote-connection-string") = "http:url=http://localhost:62434/dns/endpoint.json,post=1,post_json=1"; + ::arg().set("remote-dnssec") = "yes"; + be = BackendMakers().all()[0]; } - ~RemotebackendSetup() { } + catch (PDNSException& ex) { + BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason); + }; + } + ~RemotebackendSetup() {} }; -BOOST_GLOBAL_FIXTURE( RemotebackendSetup ); +BOOST_GLOBAL_FIXTURE(RemotebackendSetup); diff --git a/modules/remotebackend/test-remotebackend-keys.hh b/modules/remotebackend/test-remotebackend-keys.hh index cc51fb0e68..807bdd8609 100644 --- a/modules/remotebackend/test-remotebackend-keys.hh +++ b/modules/remotebackend/test-remotebackend-keys.hh @@ -19,6 +19,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -DNSBackend::KeyData k1 = {std::string("Private-key-format: v1.2\nAlgorithm: 5 (RSASHA1)\nModulus: qpe9fxlN4dBT38cLPWtqljZhcJjbqRprj9XsYmf2/uFu4kA5sHYrlQY7H9lpzGJPRfOAfxShBpKs1AVaVInfJQ==\nPublicExponent: AQAB\nPrivateExponent: Ad3YogzXvVDLsWuAfioY571QlolbdTbzVlhLEMLD6dSRx+xcZgw6c27ak2HAH00iSKTvqK3AyeaK8Eqy/oJ5QQ==\nPrime1: wo8LZrdU2y0xLGCeLhwziQDDtTMi18NEIwlx8tUPnhs=\nPrime2: 4HcuFqgo7NOiXFvN+V2PT+QaIt2+oi6D2m8/qtTDS78=\nExponent1: GUdCoPbi9JM7l1t6Ud1iKMPLqchaF5SMTs0UXAuous8=\nExponent2: nzgKqimX9f1corTAEw0pddrwKyEtcu8ZuhzFhZCsAxM=\nCoefficient: YGNxbulf5GTNiIu0oNKmAF0khNtx9layjOPEI0R4/RY="), 1, 257, true, true }; +DNSBackend::KeyData k1 = {std::string("Private-key-format: v1.2\nAlgorithm: 5 (RSASHA1)\nModulus: qpe9fxlN4dBT38cLPWtqljZhcJjbqRprj9XsYmf2/uFu4kA5sHYrlQY7H9lpzGJPRfOAfxShBpKs1AVaVInfJQ==\nPublicExponent: AQAB\nPrivateExponent: Ad3YogzXvVDLsWuAfioY571QlolbdTbzVlhLEMLD6dSRx+xcZgw6c27ak2HAH00iSKTvqK3AyeaK8Eqy/oJ5QQ==\nPrime1: wo8LZrdU2y0xLGCeLhwziQDDtTMi18NEIwlx8tUPnhs=\nPrime2: 4HcuFqgo7NOiXFvN+V2PT+QaIt2+oi6D2m8/qtTDS78=\nExponent1: GUdCoPbi9JM7l1t6Ud1iKMPLqchaF5SMTs0UXAuous8=\nExponent2: nzgKqimX9f1corTAEw0pddrwKyEtcu8ZuhzFhZCsAxM=\nCoefficient: YGNxbulf5GTNiIu0oNKmAF0khNtx9layjOPEI0R4/RY="), 1, 257, true, true}; -DNSBackend::KeyData k2 = {std::string("Private-key-format: v1.2\nAlgorithm: 5 (RSASHA1)\nModulus: tY2TAMgL/whZdSbn2aci4wcMqohO24KQAaq5RlTRwQ33M8FYdW5fZ3DMdMsSLQUkjGnKJPKEdN3Qd4Z5b18f+w==\nPublicExponent: AQAB\nPrivateExponent: BB6xibPNPrBV0PUp3CQq0OdFpk9v9EZ2NiBFrA7osG5mGIZICqgOx/zlHiHKmX4OLmL28oU7jPKgogeuONXJQQ==\nPrime1: yjxe/iHQ4IBWpvCmuGqhxApWF+DY9LADIP7bM3Ejf3M=\nPrime2: 5dGWTyYEQRBVK74q1a64iXgaNuYm1pbClvvZ6ccCq1k=\nExponent1: TwM5RebmWeAqerzJFoIqw5IaQugJO8hM4KZR9A4/BTs=\nExponent2: bpV2HSmu3Fvuj7jWxbFoDIXlH0uJnrI2eg4/4hSnvSk=\nCoefficient: e2uDDWN2zXwYa2P6VQBWQ4mR1ZZjFEtO/+YqOJZun1Y="), 2, 256, true, true }; +DNSBackend::KeyData k2 = {std::string("Private-key-format: v1.2\nAlgorithm: 5 (RSASHA1)\nModulus: tY2TAMgL/whZdSbn2aci4wcMqohO24KQAaq5RlTRwQ33M8FYdW5fZ3DMdMsSLQUkjGnKJPKEdN3Qd4Z5b18f+w==\nPublicExponent: AQAB\nPrivateExponent: BB6xibPNPrBV0PUp3CQq0OdFpk9v9EZ2NiBFrA7osG5mGIZICqgOx/zlHiHKmX4OLmL28oU7jPKgogeuONXJQQ==\nPrime1: yjxe/iHQ4IBWpvCmuGqhxApWF+DY9LADIP7bM3Ejf3M=\nPrime2: 5dGWTyYEQRBVK74q1a64iXgaNuYm1pbClvvZ6ccCq1k=\nExponent1: TwM5RebmWeAqerzJFoIqw5IaQugJO8hM4KZR9A4/BTs=\nExponent2: bpV2HSmu3Fvuj7jWxbFoDIXlH0uJnrI2eg4/4hSnvSk=\nCoefficient: e2uDDWN2zXwYa2P6VQBWQ4mR1ZZjFEtO/+YqOJZun1Y="), 2, 256, true, true}; diff --git a/modules/remotebackend/test-remotebackend-pipe.cc b/modules/remotebackend/test-remotebackend-pipe.cc index 8d4ca4ea43..11883b104e 100644 --- a/modules/remotebackend/test-remotebackend-pipe.cc +++ b/modules/remotebackend/test-remotebackend-pipe.cc @@ -46,7 +46,7 @@ StatBag S; AuthPacketCache PC; AuthQueryCache QC; -ArgvMap &arg() +ArgvMap& arg() { static ArgvMap arg; return arg; @@ -54,34 +54,36 @@ ArgvMap &arg() class RemoteLoader { - public: - RemoteLoader(); +public: + RemoteLoader(); }; -DNSBackend *be; +DNSBackend* be; -struct RemotebackendSetup { - RemotebackendSetup() { - be = 0; - try { - // setup minimum arguments - ::arg().set("module-dir")="./.libs"; - new RemoteLoader(); - BackendMakers().launch("remote"); - // then get us a instance of it - ::arg().set("remote-connection-string")="pipe:command=unittest_pipe.rb"; - ::arg().set("remote-dnssec")="yes"; - be = BackendMakers().all()[0]; - // load few record types to help out - SOARecordContent::report(); - NSRecordContent::report(); - ARecordContent::report(); - } catch (PDNSException &ex) { - BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason ); - }; +struct RemotebackendSetup +{ + RemotebackendSetup() + { + be = 0; + try { + // setup minimum arguments + ::arg().set("module-dir") = "./.libs"; + new RemoteLoader(); + BackendMakers().launch("remote"); + // then get us a instance of it + ::arg().set("remote-connection-string") = "pipe:command=unittest_pipe.rb"; + ::arg().set("remote-dnssec") = "yes"; + be = BackendMakers().all()[0]; + // load few record types to help out + SOARecordContent::report(); + NSRecordContent::report(); + ARecordContent::report(); } - ~RemotebackendSetup() { } + catch (PDNSException& ex) { + BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason); + }; + } + ~RemotebackendSetup() {} }; -BOOST_GLOBAL_FIXTURE( RemotebackendSetup ); - +BOOST_GLOBAL_FIXTURE(RemotebackendSetup); diff --git a/modules/remotebackend/test-remotebackend-post.cc b/modules/remotebackend/test-remotebackend-post.cc index 785fb6461b..899b51dbb9 100644 --- a/modules/remotebackend/test-remotebackend-post.cc +++ b/modules/remotebackend/test-remotebackend-post.cc @@ -37,7 +37,7 @@ StatBag S; AuthPacketCache PC; AuthQueryCache QC; -ArgvMap &arg() +ArgvMap& arg() { static ArgvMap arg; return arg; @@ -45,11 +45,11 @@ ArgvMap &arg() class RemoteLoader { - public: - RemoteLoader(); +public: + RemoteLoader(); }; -DNSBackend *be; +DNSBackend* be; #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MAIN @@ -60,23 +60,26 @@ DNSBackend *be; #include -struct RemotebackendSetup { - RemotebackendSetup() { - be = 0; - try { - // setup minimum arguments - ::arg().set("module-dir")="./.libs"; - new RemoteLoader(); - BackendMakers().launch("remote"); - // then get us a instance of it - ::arg().set("remote-connection-string")="http:url=http://localhost:62434/dns,post=1"; - ::arg().set("remote-dnssec")="yes"; - be = BackendMakers().all()[0]; - } catch (PDNSException &ex) { - BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason ); - }; +struct RemotebackendSetup +{ + RemotebackendSetup() + { + be = 0; + try { + // setup minimum arguments + ::arg().set("module-dir") = "./.libs"; + new RemoteLoader(); + BackendMakers().launch("remote"); + // then get us a instance of it + ::arg().set("remote-connection-string") = "http:url=http://localhost:62434/dns,post=1"; + ::arg().set("remote-dnssec") = "yes"; + be = BackendMakers().all()[0]; } - ~RemotebackendSetup() { } + catch (PDNSException& ex) { + BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason); + }; + } + ~RemotebackendSetup() {} }; -BOOST_GLOBAL_FIXTURE( RemotebackendSetup ); +BOOST_GLOBAL_FIXTURE(RemotebackendSetup); diff --git a/modules/remotebackend/test-remotebackend-unix.cc b/modules/remotebackend/test-remotebackend-unix.cc index bf3f9da20d..c2be2f3972 100644 --- a/modules/remotebackend/test-remotebackend-unix.cc +++ b/modules/remotebackend/test-remotebackend-unix.cc @@ -46,7 +46,7 @@ StatBag S; AuthPacketCache PC; AuthQueryCache QC; -ArgvMap &arg() +ArgvMap& arg() { static ArgvMap arg; return arg; @@ -54,34 +54,36 @@ ArgvMap &arg() class RemoteLoader { - public: - RemoteLoader(); +public: + RemoteLoader(); }; -DNSBackend *be; +DNSBackend* be; -struct RemotebackendSetup { - RemotebackendSetup() { - be = 0; - try { - // setup minimum arguments - ::arg().set("module-dir")="./.libs"; - new RemoteLoader(); - BackendMakers().launch("remote"); - // then get us a instance of it - ::arg().set("remote-connection-string")="unix:path=/tmp/remotebackend.sock"; - ::arg().set("remote-dnssec")="yes"; - be = BackendMakers().all()[0]; - // load few record types to help out - SOARecordContent::report(); - NSRecordContent::report(); - ARecordContent::report(); - } catch (PDNSException &ex) { - BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason ); - }; +struct RemotebackendSetup +{ + RemotebackendSetup() + { + be = 0; + try { + // setup minimum arguments + ::arg().set("module-dir") = "./.libs"; + new RemoteLoader(); + BackendMakers().launch("remote"); + // then get us a instance of it + ::arg().set("remote-connection-string") = "unix:path=/tmp/remotebackend.sock"; + ::arg().set("remote-dnssec") = "yes"; + be = BackendMakers().all()[0]; + // load few record types to help out + SOARecordContent::report(); + NSRecordContent::report(); + ARecordContent::report(); } - ~RemotebackendSetup() { } + catch (PDNSException& ex) { + BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason); + }; + } + ~RemotebackendSetup() {} }; -BOOST_GLOBAL_FIXTURE( RemotebackendSetup ); - +BOOST_GLOBAL_FIXTURE(RemotebackendSetup); diff --git a/modules/remotebackend/test-remotebackend-zeromq.cc b/modules/remotebackend/test-remotebackend-zeromq.cc index 9a08fc8fd5..c5e5396edc 100644 --- a/modules/remotebackend/test-remotebackend-zeromq.cc +++ b/modules/remotebackend/test-remotebackend-zeromq.cc @@ -45,7 +45,7 @@ StatBag S; AuthPacketCache PC; AuthQueryCache QC; -ArgvMap &arg() +ArgvMap& arg() { static ArgvMap arg; return arg; @@ -53,45 +53,49 @@ ArgvMap &arg() class RemoteLoader { - public: - RemoteLoader(); +public: + RemoteLoader(); }; -DNSBackend *be; +DNSBackend* be; #ifdef REMOTEBACKEND_ZEROMQ #include -struct RemotebackendSetup { - RemotebackendSetup() { - be = 0; - try { - // setup minimum arguments - ::arg().set("module-dir")="./.libs"; - new RemoteLoader(); - BackendMakers().launch("remote"); - // then get us a instance of it - ::arg().set("remote-connection-string")="zeromq:endpoint=ipc:///tmp/remotebackend.0"; - ::arg().set("remote-dnssec")="yes"; - be = BackendMakers().all()[0]; - // load few record types to help out - SOARecordContent::report(); - NSRecordContent::report(); - ARecordContent::report(); - } catch (PDNSException &ex) { - BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason ); - }; +struct RemotebackendSetup +{ + RemotebackendSetup() + { + be = 0; + try { + // setup minimum arguments + ::arg().set("module-dir") = "./.libs"; + new RemoteLoader(); + BackendMakers().launch("remote"); + // then get us a instance of it + ::arg().set("remote-connection-string") = "zeromq:endpoint=ipc:///tmp/remotebackend.0"; + ::arg().set("remote-dnssec") = "yes"; + be = BackendMakers().all()[0]; + // load few record types to help out + SOARecordContent::report(); + NSRecordContent::report(); + ARecordContent::report(); } - ~RemotebackendSetup() { } + catch (PDNSException& ex) { + BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason); + }; + } + ~RemotebackendSetup() {} }; -BOOST_GLOBAL_FIXTURE( RemotebackendSetup ); +BOOST_GLOBAL_FIXTURE(RemotebackendSetup); #else #include -int main(void) { +int main(void) +{ std::cout << "No HTTP support in remotebackend - skipping test" << std::endl; return 0; } diff --git a/modules/remotebackend/test-remotebackend.cc b/modules/remotebackend/test-remotebackend.cc index ef783f4ea8..084ce1ada3 100644 --- a/modules/remotebackend/test-remotebackend.cc +++ b/modules/remotebackend/test-remotebackend.cc @@ -41,315 +41,346 @@ #include "test-remotebackend-keys.hh" -extern DNSBackend *be; +extern DNSBackend* be; BOOST_AUTO_TEST_SUITE(test_remotebackend_so) -BOOST_AUTO_TEST_CASE(test_method_lookup) { - BOOST_TEST_MESSAGE("Testing lookup method"); - DNSResourceRecord rr; - be->lookup(QType(QType::SOA), DNSName("unit.test.")); - // then try to get() - BOOST_CHECK(be->get(rr)); // and this should be TRUE. - // then we check rr contains what we expect - BOOST_CHECK_EQUAL(rr.qname.toString(), "unit.test."); - BOOST_CHECK_MESSAGE(rr.qtype == QType::SOA, "returned qtype was not SOA"); - BOOST_CHECK_EQUAL(rr.content, "ns.unit.test. hostmaster.unit.test. 1 2 3 4 5"); - BOOST_CHECK_EQUAL(rr.ttl, 300); +BOOST_AUTO_TEST_CASE(test_method_lookup) +{ + BOOST_TEST_MESSAGE("Testing lookup method"); + DNSResourceRecord rr; + be->lookup(QType(QType::SOA), DNSName("unit.test.")); + // then try to get() + BOOST_CHECK(be->get(rr)); // and this should be TRUE. + // then we check rr contains what we expect + BOOST_CHECK_EQUAL(rr.qname.toString(), "unit.test."); + BOOST_CHECK_MESSAGE(rr.qtype == QType::SOA, "returned qtype was not SOA"); + BOOST_CHECK_EQUAL(rr.content, "ns.unit.test. hostmaster.unit.test. 1 2 3 4 5"); + BOOST_CHECK_EQUAL(rr.ttl, 300); } -BOOST_AUTO_TEST_CASE(test_method_lookup_empty) { - BOOST_TEST_MESSAGE("Testing lookup method with empty result"); - DNSResourceRecord rr; - be->lookup(QType(QType::SOA), DNSName("empty.unit.test.")); - // then try to get() - BOOST_CHECK(!be->get(rr)); // and this should be FALSE +BOOST_AUTO_TEST_CASE(test_method_lookup_empty) +{ + BOOST_TEST_MESSAGE("Testing lookup method with empty result"); + DNSResourceRecord rr; + be->lookup(QType(QType::SOA), DNSName("empty.unit.test.")); + // then try to get() + BOOST_CHECK(!be->get(rr)); // and this should be FALSE } -BOOST_AUTO_TEST_CASE(test_method_list) { - int record_count = 0; - DNSResourceRecord rr; +BOOST_AUTO_TEST_CASE(test_method_list) +{ + int record_count = 0; + DNSResourceRecord rr; - BOOST_TEST_MESSAGE("Testing list method"); - be->list(DNSName("unit.test."), -1); - while(be->get(rr)) record_count++; + BOOST_TEST_MESSAGE("Testing list method"); + be->list(DNSName("unit.test."), -1); + while (be->get(rr)) + record_count++; - BOOST_CHECK_EQUAL(record_count, 5); // number of records our test domain has + BOOST_CHECK_EQUAL(record_count, 5); // number of records our test domain has } -BOOST_AUTO_TEST_CASE(test_method_doesDNSSEC) { - BOOST_TEST_MESSAGE("Testing doesDNSSEC method"); - BOOST_CHECK(be->doesDNSSEC()); // should be true +BOOST_AUTO_TEST_CASE(test_method_doesDNSSEC) +{ + BOOST_TEST_MESSAGE("Testing doesDNSSEC method"); + BOOST_CHECK(be->doesDNSSEC()); // should be true } -BOOST_AUTO_TEST_CASE(test_method_setDomainMetadata) { - std::vector meta; - meta.push_back("VALUE"); - BOOST_TEST_MESSAGE("Testing setDomainMetadata method"); - BOOST_CHECK(be->setDomainMetadata(DNSName("unit.test."),"TEST", meta)); +BOOST_AUTO_TEST_CASE(test_method_setDomainMetadata) +{ + std::vector meta; + meta.push_back("VALUE"); + BOOST_TEST_MESSAGE("Testing setDomainMetadata method"); + BOOST_CHECK(be->setDomainMetadata(DNSName("unit.test."), "TEST", meta)); } -BOOST_AUTO_TEST_CASE(test_method_alsoNotifies) { - BOOST_CHECK(be->setDomainMetadata(DNSName("unit.test."),"ALSO-NOTIFY", {"192.0.2.1"})); - std::set alsoNotifies; - BOOST_TEST_MESSAGE("Testing alsoNotifies method"); - be->alsoNotifies(DNSName("unit.test."), &alsoNotifies); - BOOST_CHECK_EQUAL(alsoNotifies.size(), 1); - if (alsoNotifies.size() > 0) - BOOST_CHECK_EQUAL(alsoNotifies.count("192.0.2.1"), 1); - BOOST_CHECK(be->setDomainMetadata(DNSName("unit.test."),"ALSO-NOTIFY", std::vector())); +BOOST_AUTO_TEST_CASE(test_method_alsoNotifies) +{ + BOOST_CHECK(be->setDomainMetadata(DNSName("unit.test."), "ALSO-NOTIFY", {"192.0.2.1"})); + std::set alsoNotifies; + BOOST_TEST_MESSAGE("Testing alsoNotifies method"); + be->alsoNotifies(DNSName("unit.test."), &alsoNotifies); + BOOST_CHECK_EQUAL(alsoNotifies.size(), 1); + if (alsoNotifies.size() > 0) + BOOST_CHECK_EQUAL(alsoNotifies.count("192.0.2.1"), 1); + BOOST_CHECK(be->setDomainMetadata(DNSName("unit.test."), "ALSO-NOTIFY", std::vector())); } -BOOST_AUTO_TEST_CASE(test_method_getDomainMetadata) { - std::vector meta; - BOOST_TEST_MESSAGE("Testing getDomainMetadata method"); - be->getDomainMetadata(DNSName("unit.test."),"TEST", meta); - BOOST_CHECK_EQUAL(meta.size(), 1); - // in case we got more than one value, which would be unexpected - // but not fatal - if (meta.size() > 0) - BOOST_CHECK_EQUAL(meta[0], "VALUE"); +BOOST_AUTO_TEST_CASE(test_method_getDomainMetadata) +{ + std::vector meta; + BOOST_TEST_MESSAGE("Testing getDomainMetadata method"); + be->getDomainMetadata(DNSName("unit.test."), "TEST", meta); + BOOST_CHECK_EQUAL(meta.size(), 1); + // in case we got more than one value, which would be unexpected + // but not fatal + if (meta.size() > 0) + BOOST_CHECK_EQUAL(meta[0], "VALUE"); } -BOOST_AUTO_TEST_CASE(test_method_getAllDomainMetadata) { - std::map > meta; - BOOST_TEST_MESSAGE("Testing getAllDomainMetadata method"); - be->getAllDomainMetadata(DNSName("unit.test."), meta); - BOOST_CHECK_EQUAL(meta.size(), 1); - // in case we got more than one value, which would be unexpected - // but not fatal - if (meta.size() > 0) - BOOST_CHECK_EQUAL(meta["TEST"][0], "VALUE"); +BOOST_AUTO_TEST_CASE(test_method_getAllDomainMetadata) +{ + std::map> meta; + BOOST_TEST_MESSAGE("Testing getAllDomainMetadata method"); + be->getAllDomainMetadata(DNSName("unit.test."), meta); + BOOST_CHECK_EQUAL(meta.size(), 1); + // in case we got more than one value, which would be unexpected + // but not fatal + if (meta.size() > 0) + BOOST_CHECK_EQUAL(meta["TEST"][0], "VALUE"); } -BOOST_AUTO_TEST_CASE(test_method_addDomainKey) { - BOOST_TEST_MESSAGE("Testing addDomainKey method"); - int64_t id; - be->addDomainKey(DNSName("unit.test."),k1,id); - BOOST_CHECK_EQUAL(id, 1); - be->addDomainKey(DNSName("unit.test."),k2,id); - BOOST_CHECK_EQUAL(id, 2); +BOOST_AUTO_TEST_CASE(test_method_addDomainKey) +{ + BOOST_TEST_MESSAGE("Testing addDomainKey method"); + int64_t id; + be->addDomainKey(DNSName("unit.test."), k1, id); + BOOST_CHECK_EQUAL(id, 1); + be->addDomainKey(DNSName("unit.test."), k2, id); + BOOST_CHECK_EQUAL(id, 2); } -BOOST_AUTO_TEST_CASE(test_method_getDomainKeys) { - std::vector keys; - BOOST_TEST_MESSAGE("Testing getDomainKeys method"); - // we expect to get two keys - be->getDomainKeys(DNSName("unit.test."),keys); - BOOST_CHECK_EQUAL(keys.size(), 2); - // in case we got more than 2 keys, which would be unexpected - // but not fatal - if (keys.size() > 1) { - // check that we have two keys - for(DNSBackend::KeyData &kd : keys) { - BOOST_CHECK(kd.id > 0); - BOOST_CHECK(kd.flags == 256 || kd.flags == 257); - BOOST_CHECK(kd.active == true); - BOOST_CHECK(kd.published == true); - BOOST_CHECK(kd.content.size() > 500); - } - } +BOOST_AUTO_TEST_CASE(test_method_getDomainKeys) +{ + std::vector keys; + BOOST_TEST_MESSAGE("Testing getDomainKeys method"); + // we expect to get two keys + be->getDomainKeys(DNSName("unit.test."), keys); + BOOST_CHECK_EQUAL(keys.size(), 2); + // in case we got more than 2 keys, which would be unexpected + // but not fatal + if (keys.size() > 1) { + // check that we have two keys + for (DNSBackend::KeyData& kd : keys) { + BOOST_CHECK(kd.id > 0); + BOOST_CHECK(kd.flags == 256 || kd.flags == 257); + BOOST_CHECK(kd.active == true); + BOOST_CHECK(kd.published == true); + BOOST_CHECK(kd.content.size() > 500); + } + } } -BOOST_AUTO_TEST_CASE(test_method_deactivateDomainKey) { - BOOST_TEST_MESSAGE("Testing deactivateDomainKey method"); - BOOST_CHECK(be->deactivateDomainKey(DNSName("unit.test."),1)); +BOOST_AUTO_TEST_CASE(test_method_deactivateDomainKey) +{ + BOOST_TEST_MESSAGE("Testing deactivateDomainKey method"); + BOOST_CHECK(be->deactivateDomainKey(DNSName("unit.test."), 1)); } -BOOST_AUTO_TEST_CASE(test_method_activateDomainKey) { - BOOST_TEST_MESSAGE("Testing activateDomainKey method"); - BOOST_CHECK(be->activateDomainKey(DNSName("unit.test."),1)); +BOOST_AUTO_TEST_CASE(test_method_activateDomainKey) +{ + BOOST_TEST_MESSAGE("Testing activateDomainKey method"); + BOOST_CHECK(be->activateDomainKey(DNSName("unit.test."), 1)); } -BOOST_AUTO_TEST_CASE(test_method_removeDomainKey) { - BOOST_CHECK(be->removeDomainKey(DNSName("unit.test."),2)); - BOOST_CHECK(be->removeDomainKey(DNSName("unit.test."),1)); +BOOST_AUTO_TEST_CASE(test_method_removeDomainKey) +{ + BOOST_CHECK(be->removeDomainKey(DNSName("unit.test."), 2)); + BOOST_CHECK(be->removeDomainKey(DNSName("unit.test."), 1)); } -BOOST_AUTO_TEST_CASE(test_method_getBeforeAndAfterNamesAbsolute) { - DNSName unhashed, before, after; - BOOST_TEST_MESSAGE("Testing getBeforeAndAfterNamesAbsolute method"); - - be->getBeforeAndAfterNamesAbsolute(-1, DNSName("middle.unit.test."), unhashed, before, after); - BOOST_CHECK_EQUAL(unhashed.toString(), "middle."); - BOOST_CHECK_EQUAL(before.toString(), "begin."); - BOOST_CHECK_EQUAL(after.toString(), "stop."); +BOOST_AUTO_TEST_CASE(test_method_getBeforeAndAfterNamesAbsolute) +{ + DNSName unhashed, before, after; + BOOST_TEST_MESSAGE("Testing getBeforeAndAfterNamesAbsolute method"); + + be->getBeforeAndAfterNamesAbsolute(-1, DNSName("middle.unit.test."), unhashed, before, after); + BOOST_CHECK_EQUAL(unhashed.toString(), "middle."); + BOOST_CHECK_EQUAL(before.toString(), "begin."); + BOOST_CHECK_EQUAL(after.toString(), "stop."); } -BOOST_AUTO_TEST_CASE(test_method_setTSIGKey) { - std::string algorithm, content; - BOOST_TEST_MESSAGE("Testing setTSIGKey method"); - BOOST_CHECK_MESSAGE(be->setTSIGKey(DNSName("unit.test."),DNSName("hmac-md5."),"kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys="), "did not return true"); +BOOST_AUTO_TEST_CASE(test_method_setTSIGKey) +{ + std::string algorithm, content; + BOOST_TEST_MESSAGE("Testing setTSIGKey method"); + BOOST_CHECK_MESSAGE(be->setTSIGKey(DNSName("unit.test."), DNSName("hmac-md5."), "kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys="), "did not return true"); } -BOOST_AUTO_TEST_CASE(test_method_getTSIGKey) { - DNSName algorithm; - std::string content; - BOOST_TEST_MESSAGE("Testing getTSIGKey method"); - be->getTSIGKey(DNSName("unit.test."),&algorithm,&content); - BOOST_CHECK_EQUAL(algorithm.toString(), "hmac-md5."); - BOOST_CHECK_EQUAL(content, "kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys="); +BOOST_AUTO_TEST_CASE(test_method_getTSIGKey) +{ + DNSName algorithm; + std::string content; + BOOST_TEST_MESSAGE("Testing getTSIGKey method"); + be->getTSIGKey(DNSName("unit.test."), &algorithm, &content); + BOOST_CHECK_EQUAL(algorithm.toString(), "hmac-md5."); + BOOST_CHECK_EQUAL(content, "kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys="); } -BOOST_AUTO_TEST_CASE(test_method_deleteTSIGKey) { - std::string algorithm, content; - BOOST_TEST_MESSAGE("Testing deleteTSIGKey method"); - BOOST_CHECK_MESSAGE(be->deleteTSIGKey(DNSName("unit.test.")), "did not return true"); +BOOST_AUTO_TEST_CASE(test_method_deleteTSIGKey) +{ + std::string algorithm, content; + BOOST_TEST_MESSAGE("Testing deleteTSIGKey method"); + BOOST_CHECK_MESSAGE(be->deleteTSIGKey(DNSName("unit.test.")), "did not return true"); } -BOOST_AUTO_TEST_CASE(test_method_getTSIGKeys) { - std::vector keys; - BOOST_TEST_MESSAGE("Testing getTSIGKeys method"); - be->getTSIGKeys(keys); - BOOST_CHECK(keys.size() > 0); - if (keys.size() > 0) { - BOOST_CHECK_EQUAL(keys[0].name.toString(), "test."); - BOOST_CHECK_EQUAL(keys[0].algorithm.toString(), "NULL."); - BOOST_CHECK_EQUAL(keys[0].key, "NULL"); - } +BOOST_AUTO_TEST_CASE(test_method_getTSIGKeys) +{ + std::vector keys; + BOOST_TEST_MESSAGE("Testing getTSIGKeys method"); + be->getTSIGKeys(keys); + BOOST_CHECK(keys.size() > 0); + if (keys.size() > 0) { + BOOST_CHECK_EQUAL(keys[0].name.toString(), "test."); + BOOST_CHECK_EQUAL(keys[0].algorithm.toString(), "NULL."); + BOOST_CHECK_EQUAL(keys[0].key, "NULL"); + } } -BOOST_AUTO_TEST_CASE(test_method_setNotified) { - BOOST_TEST_MESSAGE("Testing setNotified method"); - be->setNotified(1, 2); - BOOST_CHECK(true); // we check this on next step +BOOST_AUTO_TEST_CASE(test_method_setNotified) +{ + BOOST_TEST_MESSAGE("Testing setNotified method"); + be->setNotified(1, 2); + BOOST_CHECK(true); // we check this on next step } -BOOST_AUTO_TEST_CASE(test_method_getDomainInfo) { - DomainInfo di; - BOOST_TEST_MESSAGE("Testing getDomainInfo method"); - be->getDomainInfo(DNSName("unit.test."), di); - BOOST_CHECK_EQUAL(di.zone.toString(), "unit.test."); - BOOST_CHECK_EQUAL(di.serial, 2); - BOOST_CHECK_EQUAL(di.notified_serial, 2); - BOOST_CHECK_EQUAL(di.kind, DomainInfo::Native); - BOOST_CHECK_EQUAL(di.backend, be); +BOOST_AUTO_TEST_CASE(test_method_getDomainInfo) +{ + DomainInfo di; + BOOST_TEST_MESSAGE("Testing getDomainInfo method"); + be->getDomainInfo(DNSName("unit.test."), di); + BOOST_CHECK_EQUAL(di.zone.toString(), "unit.test."); + BOOST_CHECK_EQUAL(di.serial, 2); + BOOST_CHECK_EQUAL(di.notified_serial, 2); + BOOST_CHECK_EQUAL(di.kind, DomainInfo::Native); + BOOST_CHECK_EQUAL(di.backend, be); } -BOOST_AUTO_TEST_CASE(test_method_getAllDomains) { - DomainInfo di; - BOOST_TEST_MESSAGE("Testing getAllDomains method"); - vector result; +BOOST_AUTO_TEST_CASE(test_method_getAllDomains) +{ + DomainInfo di; + BOOST_TEST_MESSAGE("Testing getAllDomains method"); + vector result; - be->getAllDomains(&result, true); + be->getAllDomains(&result, true); - di = result[0]; - BOOST_CHECK_EQUAL(di.zone.toString(), "unit.test."); - BOOST_CHECK_EQUAL(di.serial, 2); - BOOST_CHECK_EQUAL(di.notified_serial, 2); - BOOST_CHECK_EQUAL(di.kind, DomainInfo::Native); - BOOST_CHECK_EQUAL(di.backend, be); + di = result[0]; + BOOST_CHECK_EQUAL(di.zone.toString(), "unit.test."); + BOOST_CHECK_EQUAL(di.serial, 2); + BOOST_CHECK_EQUAL(di.notified_serial, 2); + BOOST_CHECK_EQUAL(di.kind, DomainInfo::Native); + BOOST_CHECK_EQUAL(di.backend, be); } -BOOST_AUTO_TEST_CASE(test_method_superMasterBackend) { - DNSResourceRecord rr; - std::vector nsset; - DNSBackend *dbd; - BOOST_TEST_MESSAGE("Testing superMasterBackend method"); - - rr.qname = DNSName("example.com."); - rr.qtype = QType::NS; - rr.qclass = QClass::IN; - rr.ttl = 300; - rr.content = "ns1.example.com."; - nsset.push_back(rr); - rr.qname = DNSName("example.com."); - rr.qtype = QType::NS; - rr.qclass = QClass::IN; - rr.ttl = 300; - rr.content = "ns2.example.com."; - nsset.push_back(rr); - - BOOST_CHECK(be->superMasterBackend("10.0.0.1", DNSName("example.com."), nsset, NULL, NULL, &dbd)); - - // let's see what we got - BOOST_CHECK_EQUAL(dbd, be); +BOOST_AUTO_TEST_CASE(test_method_superMasterBackend) +{ + DNSResourceRecord rr; + std::vector nsset; + DNSBackend* dbd; + BOOST_TEST_MESSAGE("Testing superMasterBackend method"); + + rr.qname = DNSName("example.com."); + rr.qtype = QType::NS; + rr.qclass = QClass::IN; + rr.ttl = 300; + rr.content = "ns1.example.com."; + nsset.push_back(rr); + rr.qname = DNSName("example.com."); + rr.qtype = QType::NS; + rr.qclass = QClass::IN; + rr.ttl = 300; + rr.content = "ns2.example.com."; + nsset.push_back(rr); + + BOOST_CHECK(be->superMasterBackend("10.0.0.1", DNSName("example.com."), nsset, NULL, NULL, &dbd)); + + // let's see what we got + BOOST_CHECK_EQUAL(dbd, be); } -BOOST_AUTO_TEST_CASE(test_method_createSlaveDomain) { - BOOST_TEST_MESSAGE("Testing createSlaveDomain method"); - BOOST_CHECK(be->createSlaveDomain("10.0.0.1", DNSName("pirate.unit.test."), "", "")); +BOOST_AUTO_TEST_CASE(test_method_createSlaveDomain) +{ + BOOST_TEST_MESSAGE("Testing createSlaveDomain method"); + BOOST_CHECK(be->createSlaveDomain("10.0.0.1", DNSName("pirate.unit.test."), "", "")); } -BOOST_AUTO_TEST_CASE(test_method_feedRecord) { - DNSResourceRecord rr; - BOOST_TEST_MESSAGE("Testing feedRecord method"); - be->startTransaction(DNSName("example.com."),2); - rr.qname = DNSName("example.com."); - rr.qtype = QType::SOA; - rr.qclass = QClass::IN; - rr.ttl = 300; - rr.content = "ns1.example.com. hostmaster.example.com. 2013013441 7200 3600 1209600 300"; - BOOST_CHECK(be->feedRecord(rr, DNSName())); - rr.qname = DNSName("replace.example.com."); - rr.qtype = QType::A; - rr.qclass = QClass::IN; - rr.ttl = 300; - rr.content = "127.0.0.1"; - BOOST_CHECK(be->feedRecord(rr, DNSName())); - be->commitTransaction(); +BOOST_AUTO_TEST_CASE(test_method_feedRecord) +{ + DNSResourceRecord rr; + BOOST_TEST_MESSAGE("Testing feedRecord method"); + be->startTransaction(DNSName("example.com."), 2); + rr.qname = DNSName("example.com."); + rr.qtype = QType::SOA; + rr.qclass = QClass::IN; + rr.ttl = 300; + rr.content = "ns1.example.com. hostmaster.example.com. 2013013441 7200 3600 1209600 300"; + BOOST_CHECK(be->feedRecord(rr, DNSName())); + rr.qname = DNSName("replace.example.com."); + rr.qtype = QType::A; + rr.qclass = QClass::IN; + rr.ttl = 300; + rr.content = "127.0.0.1"; + BOOST_CHECK(be->feedRecord(rr, DNSName())); + be->commitTransaction(); } -BOOST_AUTO_TEST_CASE(test_method_replaceRRSet) { - be->startTransaction(DNSName("example.com."),2); - DNSResourceRecord rr; - std::vector rrset; - BOOST_TEST_MESSAGE("Testing replaceRRSet method"); - rr.qname = DNSName("replace.example.com."); - rr.qtype = QType::A; - rr.qclass = QClass::IN; - rr.ttl = 300; - rr.content = "1.1.1.1"; - rrset.push_back(rr); - BOOST_CHECK(be->replaceRRSet(2, DNSName("replace.example.com."), QType(QType::A), rrset)); - be->commitTransaction(); +BOOST_AUTO_TEST_CASE(test_method_replaceRRSet) +{ + be->startTransaction(DNSName("example.com."), 2); + DNSResourceRecord rr; + std::vector rrset; + BOOST_TEST_MESSAGE("Testing replaceRRSet method"); + rr.qname = DNSName("replace.example.com."); + rr.qtype = QType::A; + rr.qclass = QClass::IN; + rr.ttl = 300; + rr.content = "1.1.1.1"; + rrset.push_back(rr); + BOOST_CHECK(be->replaceRRSet(2, DNSName("replace.example.com."), QType(QType::A), rrset)); + be->commitTransaction(); } -BOOST_AUTO_TEST_CASE(test_method_feedEnts) { - BOOST_TEST_MESSAGE("Testing feedEnts method"); - be->startTransaction(DNSName("example.com."),2); - map nonterm = boost::assign::map_list_of(DNSName("_udp"), true)(DNSName("_sip._udp"), true); - BOOST_CHECK(be->feedEnts(2, nonterm)); - be->commitTransaction(); +BOOST_AUTO_TEST_CASE(test_method_feedEnts) +{ + BOOST_TEST_MESSAGE("Testing feedEnts method"); + be->startTransaction(DNSName("example.com."), 2); + map nonterm = boost::assign::map_list_of(DNSName("_udp"), true)(DNSName("_sip._udp"), true); + BOOST_CHECK(be->feedEnts(2, nonterm)); + be->commitTransaction(); } -BOOST_AUTO_TEST_CASE(test_method_feedEnts3) { - BOOST_TEST_MESSAGE("Testing feedEnts3 method"); - be->startTransaction(DNSName("example.com"),2); - NSEC3PARAMRecordContent ns3prc; - ns3prc.d_iterations=1; - ns3prc.d_salt="\u00aa\u00bb\u00cc\u00dd"; - map nonterm = boost::assign::map_list_of(DNSName("_udp"), true)(DNSName("_sip._udp"), true); - BOOST_CHECK(be->feedEnts3(2, DNSName("example.com."), nonterm, ns3prc, 0)); - be->commitTransaction(); +BOOST_AUTO_TEST_CASE(test_method_feedEnts3) +{ + BOOST_TEST_MESSAGE("Testing feedEnts3 method"); + be->startTransaction(DNSName("example.com"), 2); + NSEC3PARAMRecordContent ns3prc; + ns3prc.d_iterations = 1; + ns3prc.d_salt = "\u00aa\u00bb\u00cc\u00dd"; + map nonterm = boost::assign::map_list_of(DNSName("_udp"), true)(DNSName("_sip._udp"), true); + BOOST_CHECK(be->feedEnts3(2, DNSName("example.com."), nonterm, ns3prc, 0)); + be->commitTransaction(); } -BOOST_AUTO_TEST_CASE(test_method_abortTransaction) { - BOOST_TEST_MESSAGE("Testing abortTransaction method"); - be->startTransaction(DNSName("example.com."),2); - BOOST_CHECK(be->abortTransaction()); +BOOST_AUTO_TEST_CASE(test_method_abortTransaction) +{ + BOOST_TEST_MESSAGE("Testing abortTransaction method"); + be->startTransaction(DNSName("example.com."), 2); + BOOST_CHECK(be->abortTransaction()); } -BOOST_AUTO_TEST_CASE(test_method_directBackendCmd) { - BOOST_TEST_MESSAGE("Testing directBackendCmd method"); - BOOST_CHECK_EQUAL(be->directBackendCmd("PING 1234"), "PING 1234"); +BOOST_AUTO_TEST_CASE(test_method_directBackendCmd) +{ + BOOST_TEST_MESSAGE("Testing directBackendCmd method"); + BOOST_CHECK_EQUAL(be->directBackendCmd("PING 1234"), "PING 1234"); } -BOOST_AUTO_TEST_CASE(test_method_getUpdatedMasters) { - DomainInfo di; - BOOST_TEST_MESSAGE("Testing getUpdatedMasters method"); - vector result; +BOOST_AUTO_TEST_CASE(test_method_getUpdatedMasters) +{ + DomainInfo di; + BOOST_TEST_MESSAGE("Testing getUpdatedMasters method"); + vector result; - be->getUpdatedMasters(&result); + be->getUpdatedMasters(&result); - BOOST_CHECK(result.size() > 0); + BOOST_CHECK(result.size() > 0); - di = result[0]; - BOOST_CHECK_EQUAL(di.zone.toString(), "master.test."); - BOOST_CHECK_EQUAL(di.serial, 2); - BOOST_CHECK_EQUAL(di.notified_serial, 2); - BOOST_CHECK_EQUAL(di.kind, DomainInfo::Master); - BOOST_CHECK_EQUAL(di.backend, be); + di = result[0]; + BOOST_CHECK_EQUAL(di.zone.toString(), "master.test."); + BOOST_CHECK_EQUAL(di.serial, 2); + BOOST_CHECK_EQUAL(di.notified_serial, 2); + BOOST_CHECK_EQUAL(di.kind, DomainInfo::Master); + BOOST_CHECK_EQUAL(di.backend, be); } BOOST_AUTO_TEST_SUITE_END(); diff --git a/modules/remotebackend/unixconnector.cc b/modules/remotebackend/unixconnector.cc index 766e8a3993..9fd071528b 100644 --- a/modules/remotebackend/unixconnector.cc +++ b/modules/remotebackend/unixconnector.cc @@ -26,15 +26,16 @@ #include #include #include "remotebackend.hh" -#ifndef UNIX_PATH_MAX +#ifndef UNIX_PATH_MAX #define UNIX_PATH_MAX 108 #endif -UnixsocketConnector::UnixsocketConnector(std::map optionsMap) { +UnixsocketConnector::UnixsocketConnector(std::map optionsMap) +{ if (optionsMap.count("path") == 0) { - g_log<timeout = 2000; if (optionsMap.find("timeout") != optionsMap.end()) { this->timeout = std::stoi(optionsMap.find("timeout")->second); @@ -45,10 +46,11 @@ UnixsocketConnector::UnixsocketConnector(std::map optio this->fd = -1; } -UnixsocketConnector::~UnixsocketConnector() { +UnixsocketConnector::~UnixsocketConnector() +{ if (this->connected) { try { - g_log<write(data); if (rv == -1) @@ -64,17 +67,18 @@ int UnixsocketConnector::send_message(const Json& input) { return rv; } -int UnixsocketConnector::recv_message(Json& output) { +int UnixsocketConnector::recv_message(Json& output) +{ int rv; - std::string s_output,err; + std::string s_output, err; - struct timeval t0,t; + struct timeval t0, t; gettimeofday(&t0, NULL); - memcpy(&t,&t0,sizeof(t0)); - s_output = ""; + memcpy(&t, &t0, sizeof(t0)); + s_output = ""; - while((t.tv_sec - t0.tv_sec)*1000 + (t.tv_usec - t0.tv_usec)/1000 < this->timeout) { + while ((t.tv_sec - t0.tv_sec) * 1000 + (t.tv_usec - t0.tv_usec) / 1000 < this->timeout) { int avail = waitForData(this->fd, 0, this->timeout * 500); // use half the timeout as poll timeout if (avail < 0) // poll error return -1; @@ -84,13 +88,14 @@ int UnixsocketConnector::recv_message(Json& output) { } rv = this->read(s_output); - if (rv == -1) + if (rv == -1) return -1; - if (rv>0) { + if (rv > 0) { // see if it can be parsed output = Json::parse(s_output, err); - if (output != nullptr) return s_output.size(); + if (output != nullptr) + return s_output.size(); } gettimeofday(&t, NULL); } @@ -100,18 +105,21 @@ int UnixsocketConnector::recv_message(Json& output) { return -1; } -ssize_t UnixsocketConnector::read(std::string &data) { +ssize_t UnixsocketConnector::read(std::string& data) +{ ssize_t nread; char buf[1500] = {0}; reconnect(); - if (!connected) return -1; + if (!connected) + return -1; nread = ::read(this->fd, buf, sizeof buf); // just try again later... - if (nread==-1 && errno == EAGAIN) return 0; + if (nread == -1 && errno == EAGAIN) + return 0; - if (nread==-1 || nread==0) { + if (nread == -1 || nread == 0) { connected = false; close(fd); return -1; @@ -121,66 +129,72 @@ ssize_t UnixsocketConnector::read(std::string &data) { return nread; } -ssize_t UnixsocketConnector::write(const std::string &data) { +ssize_t UnixsocketConnector::write(const std::string& data) +{ size_t pos = 0; reconnect(); - if (!connected) return -1; + if (!connected) + return -1; - while(pos < data.size()) { + while (pos < data.size()) { ssize_t written = ::write(fd, &data.at(pos), data.size() - pos); if (written < 1) { connected = false; close(fd); return -1; - } else { + } + else { pos = pos + static_cast(written); } } return pos; } -void UnixsocketConnector::reconnect() { +void UnixsocketConnector::reconnect() +{ struct sockaddr_un sock; int rv; - if (connected) return; // no point reconnecting if connected... + if (connected) + return; // no point reconnecting if connected... connected = true; - g_log<(&sock), sizeof sock); if (rv != 0 && errno != EISCONN && errno != 0) { - g_log<send(msg); msg = nullptr; if (this->recv(msg) == false) { - g_log<connected = false; + g_log << Logger::Warning << "Failed to initialize backend" << std::endl; + close(fd); + this->connected = false; } } diff --git a/modules/remotebackend/zmqconnector.cc b/modules/remotebackend/zmqconnector.cc index 1c5ae093f6..86544eda20 100644 --- a/modules/remotebackend/zmqconnector.cc +++ b/modules/remotebackend/zmqconnector.cc @@ -25,122 +25,132 @@ #include "remotebackend.hh" #ifdef REMOTEBACKEND_ZEROMQ -ZeroMQConnector::ZeroMQConnector(std::map options): d_ctx(std::unique_ptr(zmq_init(2), zmq_close)), d_sock(std::unique_ptr(zmq_socket(d_ctx.get(), ZMQ_REQ), zmq_close)) { - int opt=0; +ZeroMQConnector::ZeroMQConnector(std::map options) : + d_ctx(std::unique_ptr(zmq_init(2), zmq_close)), d_sock(std::unique_ptr(zmq_socket(d_ctx.get(), ZMQ_REQ), zmq_close)) +{ + int opt = 0; // lookup timeout, target and stuff if (options.count("endpoint") == 0) { - g_log<d_endpoint = options.find("endpoint")->second; this->d_options = options; - this->d_timeout=2000; + this->d_timeout = 2000; if (options.find("timeout") != options.end()) { - this->d_timeout = std::stoi(options.find("timeout")->second); + this->d_timeout = std::stoi(options.find("timeout")->second); } zmq_setsockopt(d_sock.get(), ZMQ_LINGER, &opt, sizeof(opt)); - if(zmq_connect(this->d_sock.get(), this->d_endpoint.c_str()) < 0) - { - g_log<d_sock.get(), this->d_endpoint.c_str()) < 0) { + g_log << Logger::Error << "zmq_connect() failed" << zmq_strerror(errno) << std::endl; + ; throw PDNSException("Cannot find 'endpoint' option in connection string"); } Json::array parameters; Json msg = Json(Json::object{ - { "method", "initialize" }, - { "parameters", Json(options) }, + {"method", "initialize"}, + {"parameters", Json(options)}, }); this->send(msg); msg = nullptr; - if (this->recv(msg)==false) { - g_log<recv(msg) == false) { + g_log << Logger::Error << "Failed to initialize zeromq" << std::endl; throw PDNSException("Failed to initialize zeromq"); - } + } }; ZeroMQConnector::~ZeroMQConnector() {} -int ZeroMQConnector::send_message(const Json& input) { - auto line = input.dump(); - zmq_msg_t message; - - zmq_msg_init_size(&message, line.size()+1); - line.copy(reinterpret_cast(zmq_msg_data(&message)), line.size()); - ((char *)zmq_msg_data(&message))[line.size()] = '\0'; - - try { - zmq_pollitem_t item; - item.socket = d_sock.get(); - item.events = ZMQ_POLLOUT; - // poll until it's sent or timeout is spent. try to leave - // leave few cycles for read. just in case. - for(d_timespent = 0; d_timespent < d_timeout-5; d_timespent++) { - if (zmq_poll(&item, 1, 1)>0) { - if(zmq_msg_send(&message, this->d_sock.get(), 0) == -1) { - // message was not sent - g_log<d_endpoint << ": " << zmq_strerror(errno)<d_endpoint << ": " << ex.what()<(zmq_msg_data(&message)), line.size()); + ((char*)zmq_msg_data(&message))[line.size()] = '\0'; + + try { + zmq_pollitem_t item; + item.socket = d_sock.get(); + item.events = ZMQ_POLLOUT; + // poll until it's sent or timeout is spent. try to leave + // leave few cycles for read. just in case. + for (d_timespent = 0; d_timespent < d_timeout - 5; d_timespent++) { + if (zmq_poll(&item, 1, 1) > 0) { + if (zmq_msg_send(&message, this->d_sock.get(), 0) == -1) { + // message was not sent + g_log << Logger::Error << "Cannot send to " << this->d_endpoint << ": " << zmq_strerror(errno) << std::endl; + } + else + return line.size(); + } + } + } + catch (std::exception& ex) { + g_log << Logger::Error << "Cannot send to " << this->d_endpoint << ": " << ex.what() << std::endl; + throw PDNSException(ex.what()); + } + + return 0; } -int ZeroMQConnector::recv_message(Json& output) { - int rv = 0; - // try to receive message - zmq_pollitem_t item; - zmq_msg_t message; - - item.socket = d_sock.get(); - item.events = ZMQ_POLLIN; - - try { - // do zmq::poll few times - // d_timespent should always be initialized by send_message, recv should never - // be called without send first. - for(; d_timespent < d_timeout; d_timespent++) { - if (zmq_poll(&item, 1, 1)>0) { - // we have an event - if ((item.revents & ZMQ_POLLIN) == ZMQ_POLLIN) { - string data; - size_t msg_size; - zmq_msg_init(&message); - // read something - if(zmq_msg_recv(&message, this->d_sock.get(), ZMQ_NOBLOCK)>0) { - string err; - msg_size = zmq_msg_size(&message); - data.assign(reinterpret_cast(zmq_msg_data(&message)), msg_size); - zmq_msg_close(&message); - output = Json::parse(data, err); - if (output != nullptr) - rv = msg_size; - else - g_log<d_endpoint << ": " << err << endl; - break; - } else if (errno == EAGAIN) { continue; // try again } - } else { - break; - } +int ZeroMQConnector::recv_message(Json& output) +{ + int rv = 0; + // try to receive message + zmq_pollitem_t item; + zmq_msg_t message; + + item.socket = d_sock.get(); + item.events = ZMQ_POLLIN; + + try { + // do zmq::poll few times + // d_timespent should always be initialized by send_message, recv should never + // be called without send first. + for (; d_timespent < d_timeout; d_timespent++) { + if (zmq_poll(&item, 1, 1) > 0) { + // we have an event + if ((item.revents & ZMQ_POLLIN) == ZMQ_POLLIN) { + string data; + size_t msg_size; + zmq_msg_init(&message); + // read something + if (zmq_msg_recv(&message, this->d_sock.get(), ZMQ_NOBLOCK) > 0) { + string err; + msg_size = zmq_msg_size(&message); + data.assign(reinterpret_cast(zmq_msg_data(&message)), msg_size); + zmq_msg_close(&message); + output = Json::parse(data, err); + if (output != nullptr) + rv = msg_size; + else + g_log << Logger::Error << "Cannot parse JSON reply from " << this->d_endpoint << ": " << err << endl; + break; + } + else if (errno == EAGAIN) { + continue; // try again } + } + else { + break; } } - } - } catch (std::exception &ex) { - g_log<d_endpoint << ": " << ex.what()<d_endpoint << ": " << ex.what() << std::endl; + throw PDNSException(ex.what()); + } - return rv; + return rv; } #endif diff --git a/modules/tinydnsbackend/tinydnsbackend.cc b/modules/tinydnsbackend/tinydnsbackend.cc index b4d015fc60..4853d8b523 100644 --- a/modules/tinydnsbackend/tinydnsbackend.cc +++ b/modules/tinydnsbackend/tinydnsbackend.cc @@ -27,7 +27,7 @@ #include "pdns/dnsrecords.hh" #include -static string backendname="[TinyDNSBackend] "; +static string backendname = "[TinyDNSBackend] "; uint32_t TinyDNSBackend::s_lastId; std::mutex TinyDNSBackend::s_domainInfoLock; TinyDNSBackend::TDI_suffix_t TinyDNSBackend::s_domainInfo; @@ -36,7 +36,7 @@ vector TinyDNSBackend::getLocations() { vector ret; - if (! d_dnspacket) { + if (!d_dnspacket) { return ret; } @@ -51,19 +51,19 @@ vector TinyDNSBackend::getLocations() char key[6]; key[0] = '\000'; key[1] = '\045'; - key[2] = (addr )&0xff; - key[3] = (addr >> 8)&0xff; - key[4] = (addr >> 16)&0xff; - key[5] = (addr >> 24)&0xff; + key[2] = (addr)&0xff; + key[3] = (addr >> 8) & 0xff; + key[4] = (addr >> 16) & 0xff; + key[5] = (addr >> 24) & 0xff; - for (int i=4;i>=0;i--) { - string searchkey(key, i+2); + for (int i = 4; i >= 0; i--) { + string searchkey(key, i + 2); try { auto reader = std::unique_ptr(new CDB(getArg("dbfile"))); ret = reader->findall(searchkey); } - catch(const std::exception& e) { - g_log< TinyDNSBackend::getLocations() return ret; } -TinyDNSBackend::TinyDNSBackend(const string &suffix) +TinyDNSBackend::TinyDNSBackend(const string& suffix) { - setArgPrefix("tinydns"+suffix); + setArgPrefix("tinydns" + suffix); d_suffix = suffix; d_locations = mustDo("locations"); d_ignorebogus = mustDo("ignore-bogus-records"); @@ -89,25 +89,26 @@ TinyDNSBackend::TinyDNSBackend(const string &suffix) d_isWildcardQuery = false; } -void TinyDNSBackend::getUpdatedMasters(vector* retDomains) { +void TinyDNSBackend::getUpdatedMasters(vector* retDomains) +{ std::lock_guard l(s_domainInfoLock); //TODO: We could actually lock less if we do it per suffix. - if (! s_domainInfo.count(d_suffix)) { + if (!s_domainInfo.count(d_suffix)) { TDI_t tmp; - s_domainInfo.insert( make_pair(d_suffix,tmp) ); + s_domainInfo.insert(make_pair(d_suffix, tmp)); } - TDI_t *domains = &s_domainInfo[d_suffix]; + TDI_t* domains = &s_domainInfo[d_suffix]; vector allDomains; getAllDomains(&allDomains); if (domains->size() == 0 && !mustDo("notify-on-startup")) { - for (vector::iterator di=allDomains.begin(); di!=allDomains.end(); ++di) { + for (vector::iterator di = allDomains.begin(); di != allDomains.end(); ++di) { di->notified_serial = 0; } } - for(vector::iterator di=allDomains.begin(); di!=allDomains.end(); ++di) { + for (vector::iterator di = allDomains.begin(); di != allDomains.end(); ++di) { TDIByZone_t& zone_index = domains->get(); TDIByZone_t::iterator itByZone = zone_index.find(di->zone); if (itByZone == zone_index.end()) { @@ -123,7 +124,8 @@ void TinyDNSBackend::getUpdatedMasters(vector* retDomains) { if (di->notified_serial > 0) { retDomains->push_back(*di); } - } else { + } + else { if (itByZone->notified_serial < di->serial) { di->id = itByZone->id; retDomains->push_back(*di); @@ -132,32 +134,35 @@ void TinyDNSBackend::getUpdatedMasters(vector* retDomains) { } } -void TinyDNSBackend::setNotified(uint32_t id, uint32_t serial) { +void TinyDNSBackend::setNotified(uint32_t id, uint32_t serial) +{ std::lock_guard l(s_domainInfoLock); if (!s_domainInfo.count(d_suffix)) { throw PDNSException("Can't get list of domains to set the serial."); } - TDI_t *domains = &s_domainInfo[d_suffix]; + TDI_t* domains = &s_domainInfo[d_suffix]; TDIById_t& domain_index = domains->get(); TDIById_t::iterator itById = domain_index.find(id); if (itById == domain_index.end()) { - g_log<zone<<" to "<zone << " to " << serial << endl); domain_index.modify(itById, TDI_SerialModifier(serial)); } s_domainInfo[d_suffix] = *domains; } -void TinyDNSBackend::getAllDomains(vector *domains, bool include_disabled) { - d_isAxfr=true; +void TinyDNSBackend::getAllDomains(vector* domains, bool include_disabled) +{ + d_isAxfr = true; d_dnspacket = NULL; try { - d_cdbReader=std::unique_ptr(new CDB(getArg("dbfile"))); + d_cdbReader = std::unique_ptr(new CDB(getArg("dbfile"))); } catch (const std::exception& e) { - g_log< *domains, bool include_dis DomainInfo di; di.id = -1; //TODO: Check if this is ok. - di.backend=this; + di.backend = this; di.zone = rr.qname; di.serial = sd.serial; di.notified_serial = sd.serial; @@ -183,42 +188,44 @@ void TinyDNSBackend::getAllDomains(vector *domains, bool include_dis } } -bool TinyDNSBackend::list(const DNSName &target, int domain_id, bool include_disabled) { - d_isAxfr=true; +bool TinyDNSBackend::list(const DNSName& target, int domain_id, bool include_disabled) +{ + d_isAxfr = true; string key = target.toDNSStringLC(); try { - d_cdbReader=std::unique_ptr(new CDB(getArg("dbfile"))); + d_cdbReader = std::unique_ptr(new CDB(getArg("dbfile"))); } catch (const std::exception& e) { - g_log<searchSuffix(key); } -void TinyDNSBackend::lookup(const QType &qtype, const DNSName &qdomain, int zoneId, DNSPacket *pkt_p) { +void TinyDNSBackend::lookup(const QType& qtype, const DNSName& qdomain, int zoneId, DNSPacket* pkt_p) +{ d_isAxfr = false; string queryDomain = toLowerCanonic(qdomain.toString()); - string key=simpleCompress(queryDomain); + string key = simpleCompress(queryDomain); - DLOG(g_log<(new CDB(getArg("dbfile"))); + d_cdbReader = std::unique_ptr(new CDB(getArg("dbfile"))); } catch (const std::exception& e) { - g_log< record; @@ -253,13 +259,12 @@ bool TinyDNSBackend::get(DNSResourceRecord &rr) } } - PacketReader pr(val, 0); rr.qtype = QType(pr.get16BitInt()); - if(d_isAxfr || d_qtype.getCode() == QType::ANY || rr.qtype == d_qtype) { + if (d_isAxfr || d_qtype.getCode() == QType::ANY || rr.qtype == d_qtype) { char locwild = pr.get8BitInt(); - if(locwild != '\075' && (locwild == '\076' || locwild == '\053')) { + if (locwild != '\075' && (locwild == '\076' || locwild == '\053')) { if (d_isAxfr && d_locations) { // We skip records with a location in AXFR, unless we disable locations. continue; } @@ -270,7 +275,7 @@ bool TinyDNSBackend::get(DNSResourceRecord &rr) if (d_locations) { bool foundLocation = false; vector locations = getLocations(); - while(locations.size() > 0) { + while (locations.size() > 0) { string locId = locations.back(); locations.pop_back(); @@ -285,13 +290,13 @@ bool TinyDNSBackend::get(DNSResourceRecord &rr) } } - if (d_isAxfr && (val[2] == '\052' || val[2] == '\053' )) { // Keys are not stored with wildcard character, with AXFR we need to add that. + if (d_isAxfr && (val[2] == '\052' || val[2] == '\053')) { // Keys are not stored with wildcard character, with AXFR we need to add that. key.insert(0, 1, '\052'); key.insert(0, 1, '\001'); } // rr.qname.clear(); - rr.qname=DNSName(key.c_str(), key.size(), 0, false); - rr.domain_id=-1; + rr.qname = DNSName(key.c_str(), key.size(), 0, false); + rr.domain_id = -1; // 11:13.21 <@ahu> IT IS ALWAYS AUTH --- well not really because we are just a backend :-) // We could actually do NSEC3-NARROW DNSSEC according to Habbie, if we do, we need to change something here. rr.auth = true; @@ -300,16 +305,19 @@ bool TinyDNSBackend::get(DNSResourceRecord &rr) uint64_t timestamp = pr.get32BitInt(); timestamp <<= 32; timestamp += pr.get32BitInt(); - if(timestamp) { + if (timestamp) { uint64_t now = d_taiepoch + time(NULL); if (rr.ttl == 0) { if (timestamp < now) { continue; } rr.ttl = timestamp - now; - if (rr.ttl <= 2) rr.ttl = 2; - if (rr.ttl >= 3600) rr.ttl = 3600; - } else if (now <= timestamp) { + if (rr.ttl <= 2) + rr.ttl = 2; + if (rr.ttl >= 3600) + rr.ttl = 3600; + } + else if (now <= timestamp) { continue; } } @@ -317,39 +325,42 @@ bool TinyDNSBackend::get(DNSResourceRecord &rr) DNSRecord dr; dr.d_class = 1; dr.d_type = rr.qtype.getCode(); - dr.d_clen = val.size()-pr.getPosition(); + dr.d_clen = val.size() - pr.getPosition(); auto drc = DNSRecordContent::mastermake(dr, pr); rr.content = drc->getZoneRepresentation(); - DLOG(cerr<<"CONTENT: "< *domains, bool include_disabled=false) override; + TinyDNSBackend(const string& suffix); + void lookup(const QType& qtype, const DNSName& qdomain, int zoneId, DNSPacket* pkt_p = nullptr) override; + bool list(const DNSName& target, int domain_id, bool include_disabled = false) override; + bool get(DNSResourceRecord& rr) override; + void getAllDomains(vector* domains, bool include_disabled = false) override; //Master mode operation void getUpdatedMasters(vector* domains) override; void setNotified(uint32_t id, uint32_t serial) override; + private: vector getLocations(); //TypeDefs - struct tag_zone{}; - struct tag_domainid{}; + struct tag_zone + { + }; + struct tag_domainid + { + }; typedef multi_index_container< TinyDomainInfo, indexed_by< - hashed_unique, member >, - hashed_unique, member > - > - > TDI_t; + hashed_unique, member>, + hashed_unique, member>>> + TDI_t; typedef map TDI_suffix_t; typedef TDI_t::index::type TDIByZone_t; typedef TDI_t::index::type TDIById_t; @@ -95,7 +101,7 @@ private: uint64_t d_taiepoch; QType d_qtype; std::unique_ptr d_cdbReader; - DNSPacket *d_dnspacket; // used for location and edns-client support. + DNSPacket* d_dnspacket; // used for location and edns-client support. bool d_isWildcardQuery; // Indicate if the query received was a wildcard query. bool d_isAxfr; // Indicate if we received a list() and not a lookup(). bool d_locations;