From: Miod Vallat Date: Mon, 13 Jul 2026 13:56:01 +0000 (+0200) Subject: Move Lua2BackendAPIv2 method bodies from .hh to .cc. NFC X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=aa90add903da034fb6653c641e8098692e0c1fbb;p=thirdparty%2Fpdns.git Move Lua2BackendAPIv2 method bodies from .hh to .cc. NFC Signed-off-by: Miod Vallat --- diff --git a/modules/lua2backend/lua2api2.cc b/modules/lua2backend/lua2api2.cc index d9a2304aba..5f2f5ecea7 100644 --- a/modules/lua2backend/lua2api2.cc +++ b/modules/lua2backend/lua2api2.cc @@ -24,8 +24,488 @@ #endif #include "lua2backend.hh" +Lua2BackendAPIv2::Lua2BackendAPIv2(Logr::log_t slog, const string& suffix) +{ + d_slog = slog; + d_include_path = ::arg()["lua-global-include-dir"]; + setArgPrefix("lua2" + suffix); + d_debug_log = mustDo("query-logging"); + prepareContext(); + loadFile(getArg("filename")); +} + Lua2BackendAPIv2::~Lua2BackendAPIv2() { if (f_deinit) f_deinit(); } + +void Lua2BackendAPIv2::postPrepareContext() +{ + AuthLua4::postPrepareContext(); +} + +void Lua2BackendAPIv2::postLoad() +{ + f_lookup = d_lw->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); + f_get_domaininfo = d_lw->readVariable>("dns_get_domaininfo").get_value_or(0); + f_get_domain_metadata = d_lw->readVariable>("dns_get_domain_metadata").get_value_or(0); + f_get_all_domain_metadata = d_lw->readVariable>("dns_get_all_domain_metadata").get_value_or(0); + f_get_domain_keys = d_lw->readVariable>("dns_get_domain_keys").get_value_or(0); + f_get_before_and_after_names_absolute = d_lw->readVariable>("dns_get_before_and_after_names_absolute").get_value_or(0); + f_set_notified = d_lw->readVariable>("dns_set_notified").get_value_or(0); + + auto init = d_lw->readVariable>("dns_init").get_value_or(0); + if (init) { + init(); + } + + f_deinit = d_lw->readVariable>("dns_deinit").get_value_or(0); + + if (f_lookup == nullptr) { + throw PDNSException("dns_lookup missing"); + } + + /* see if dnssec support is wanted */ + d_dnssec = d_lw->readVariable>("dns_dnssec").get_value_or(false); + if (d_dnssec) { + if (f_get_domain_metadata == nullptr) { + throw PDNSException("dns_dnssec is true but dns_get_domain_metadata is missing"); + } + if (f_get_before_and_after_names_absolute == nullptr) { + 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) { + SLOG(g_log << Logger::Warning << "dns_get_domain_keys missing - cannot do live signing" << endl, + d_slog->info(Logr::Warning, "dns_get_domain_keys missing - cannot perform live signing")); + } + } +} + +unsigned int Lua2BackendAPIv2::getCapabilities() +{ + unsigned int caps = CAP_DIRECT | CAP_LIST; + if (d_dnssec) { + caps |= CAP_DNSSEC; + } + if (f_get_all_domains != nullptr) { + caps |= CAP_SEARCH; + } + return caps; +} + +void Lua2BackendAPIv2::parseLookup(const lookup_result_t& result) +{ + for (const auto& row : result) { + DNSResourceRecord rec; + 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") { + rec.domain_id = boost::get(item.second); + } + else if (item.first == "auth") { + rec.auth = boost::get(item.second); + } + else if (item.first == "last_modified") { + rec.last_modified = static_cast(boost::get(item.second)); + } + else if (item.first == "ttl") { + rec.ttl = boost::get(item.second); + } + else if (item.first == "content") { + rec.setContent(boost::get(item.second)); + } + else if (item.first == "scopeMask") { + rec.scopeMask = boost::get(item.second); + } + else { + SLOG(g_log << Logger::Warning << "Unsupported key '" << item.first << "' in lookup or list result" << endl, + d_slog->info(Logr::Warning, "Unsupported kep in lookup or list result", "key", Logging::Loggable(item.first))); + } + } + if (d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Got result " << "'" << rec.qname << " IN " << rec.qtype.toString() << " " << rec.ttl << " " << rec.getZoneRepresentation() << "'" << endl, + d_slog->info(Logr::Debug, "Got result", "name", Logging::Loggable(rec.qname), "type", Logging::Loggable(rec.qtype), "ttl", Logging::Loggable(rec.ttl), "data", Logging::Loggable(rec.getZoneRepresentation()))); + } + d_result.push_back(std::move(rec)); + } + if (d_result.empty() && d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Got empty result" << endl, + d_slog->info(Logr::Debug, "Got empty result")); + } +} + +bool Lua2BackendAPIv2::list(const ZoneName& target, domainid_t domain_id, bool /* include_disabled */) +{ + if (f_list == nullptr) { + SLOG(g_log << Logger::Error << "[" << getPrefix() << "] dns_list missing - cannot do AXFR" << endl, + d_slog->info(Logr::Error, "dns_list missing - cannot perform AXFR")); + return false; + } + + if (d_result.size() != 0) { + throw PDNSException("list attempted while another was running"); + } + + if (d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "list" << "(" << "target=" << target << ",domain_id=" << domain_id << ")" << endl, + d_slog->info(Logr::Debug, "Calling list", "target", Logging::Loggable(target), "domain id", Logging::Loggable(domain_id))); + } + list_result_t result = f_list(target.operator const DNSName&(), domain_id); + + if (result.which() == 0) { + return false; + } + + parseLookup(boost::get(result)); + + return true; +} + +void Lua2BackendAPIv2::lookup(const QType& qtype, const DNSName& qname, domainid_t domain_id, DNSPacket* p) +{ + if (d_result.size() != 0) { + throw PDNSException("lookup attempted while another was running"); + } + + lookup_context_t ctx; + if (p != NULL) { + ctx.emplace_back(lookup_context_t::value_type{"source_address", p->getInnerRemote().toString()}); + ctx.emplace_back(lookup_context_t::value_type{"real_source_address", p->getRealRemote().toString()}); + } + + if (d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "lookup" << "(" << "qtype=" << qtype.toString() << ",qname=" << qname << ",domain_id=" << domain_id << ")" << endl, + d_slog->info(Logr::Debug, "Calling lookup", "type", Logging::Loggable(qtype), "name", Logging::Loggable(qname), "domain id", Logging::Loggable(domain_id))); + } + lookup_result_t result = f_lookup(qtype, qname, domain_id, ctx); + parseLookup(result); +} + +bool Lua2BackendAPIv2::get(DNSResourceRecord& rr) +{ + if (d_result.size() == 0) { + return false; + } + rr = std::move(d_result.front()); + d_result.pop_front(); + return true; +} + +string Lua2BackendAPIv2::directBackendCmd(const string& querystr) +{ + string::size_type pos = querystr.find_first_of(" \t"); + string cmd = querystr; + string par = ""; + if (pos != string::npos) { + cmd = querystr.substr(0, pos); + par = querystr.substr(pos + 1); + } + direct_backend_cmd_call_t f = d_lw->readVariable>(cmd).get_value_or(0); + if (f == nullptr) { + return cmd + "not found"; + } + if (d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << cmd << "(" << "parameter=" << par << ")" << endl, + d_slog->info(Logr::Debug, "Direct backend command", "command", Logging::Loggable(cmd), "parameters", Logging::Loggable(par))); + } + return f(par); +} + +void Lua2BackendAPIv2::setNotified(domainid_t id, uint32_t serial) +{ + if (f_set_notified == NULL) { + return; + } + if (d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "dns_set_notified" << "(" << "id=" << id << ",serial=" << serial << ")" << endl, + d_slog->info(Logr::Debug, "Calling dns_set_notified", "id", Logging::Loggable(id), "serial", Logging::Loggable(serial))); + } + f_set_notified(id, serial); +} + +void Lua2BackendAPIv2::parseDomainInfo(const domaininfo_result_t& row, DomainInfo& di) +{ + di.id = UnknownDomainID; + for (const auto& item : row) { + if (item.first == "account") { + di.account = boost::get(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& primary : boost::get>(item.second)) { + di.primaries.push_back(ComboAddress(primary, 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 { + SLOG(g_log << Logger::Warning << "Unsupported key '" << item.first << "' in domaininfo result" << endl, + d_slog->info(Logr::Warning, "Unsupported key in domaininfo result", "key", Logging::Loggable(item.first))); + } + } + di.backend = this; + if (d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Got result " << "'" << "zone=" << di.zone << ",serial=" << di.serial << ",kind=" << di.getKindString() << "'" << endl, + d_slog->info(Logr::Debug, "Got domain info", "zone", Logging::Loggable(di.zone), "serial", Logging::Loggable(di.serial), "kind", Logging::Loggable(di.getKindString()))); + } +} + +bool Lua2BackendAPIv2::getDomainInfo(const ZoneName& domain, DomainInfo& di, bool /* getSerial */) +{ + if (f_get_domaininfo == nullptr) { + // use getAuth instead... but getAuth wraps getSOA which will call + // getDomainInfo if this is a domain variant, so protect against this + // would-be infinite recursion. + if (domain.hasVariant()) { + SLOG(g_log << Logger::Info << "Unable to return domain information for '" << domain.toLogString() << "' due to unimplemented dns_get_domaininfo" << endl, + d_slog->info(Logr::Info, "Unable to return domain information due to unimplemented dns_get_domaininfo", "domain", Logging::Loggable(domain))); + return false; + } + SOAData sd; + if (!getAuth(domain, &sd)) { + return false; + } + + di.id = sd.domain_id; + di.zone = domain; + di.backend = this; + di.serial = sd.serial; + return true; + } + + if (d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "get_domaininfo" << "(" << "domain=" << domain << ")" << endl, + d_slog->info(Logr::Debug, "Calling get_domaininfo", "domain", Logging::Loggable(domain))); + } + get_domaininfo_result_t result = f_get_domaininfo(domain.operator const DNSName&()); + + if (result.which() == 0) { + return false; + } + + di.zone = domain; + parseDomainInfo(boost::get(result), di); + + return true; +} + +void Lua2BackendAPIv2::getAllDomains(vector* domains, bool /* getSerial */, bool /* include_disabled */) +{ + if (f_get_all_domains == nullptr) { + return; + } + + if (d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "get_all_domains" << "(" << "" << ")" << endl, + d_slog->info(Logr::Debug, "Calling get_all_domains")); + } + for (const auto& row : f_get_all_domains()) { + DomainInfo di; + di.zone = ZoneName(row.first); + if (d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Got result " << "'" << di.zone << "'" << endl, + d_slog->info(Logr::Debug, "Got result", "domain", Logging::Loggable(di.zone))); + } + parseDomainInfo(row.second, di); + domains->push_back(std::move(di)); + } +} + +bool Lua2BackendAPIv2::getAllDomainMetadata(const ZoneName& name, std::map>& meta) +{ + if (f_get_all_domain_metadata == nullptr) { + return false; + } + + if (d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "get_all_domain_metadata" << "(" << "name=" << name << ")" << endl, + d_slog->info(Logr::Debug, "Calling get_all_domain_metadata", "domain", Logging::Loggable(name))); + } + get_all_domain_metadata_result_t result = f_get_all_domain_metadata(name.operator const DNSName&()); + if (result.which() == 0) { + return false; + } + + for (const auto& row : boost::get>>(result)) { + meta[row.first].clear(); + for (const auto& item : row.second) { + meta[row.first].push_back(item.second); + } + if (d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Got result " << "'" << "kind=" << row.first << ",value=" << boost::algorithm::join(meta[row.first], ", ") << "'" << endl, + d_slog->info(Logr::Debug, "Got result", "kind", Logging::Loggable(row.first), "value", Logging::Loggable(boost::algorithm::join(meta[row.first], ", ")))); + } + } + + return true; +} + +bool Lua2BackendAPIv2::getDomainMetadata(const ZoneName& name, const std::string& kind, std::vector& meta) +{ + if (f_get_domain_metadata == nullptr) { + return false; + } + + if (d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "get_domain_metadata" << "(" << "name=" << name << ",kind=" << kind << ")" << endl, + d_slog->info(Logr::Debug, "Calling get_domain_metadata", "domain", Logging::Loggable(name), "kind", Logging::Loggable(kind))); + } + get_domain_metadata_result_t result = f_get_domain_metadata(name.operator const DNSName&(), kind); + if (result.which() == 0) { + return false; + } + + meta.clear(); + for (const auto& item : boost::get(result)) { + meta.push_back(item.second); + } + + if (d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Got result " << "'" << "value=" << boost::algorithm::join(meta, ", ") << "'" << endl, + d_slog->info(Logr::Debug, "Got result", "value", Logging::Loggable(boost::algorithm::join(meta, ", ")))); + } + return true; +} + +bool Lua2BackendAPIv2::getDomainKeys(const ZoneName& name, std::vector& keys) +{ + if (f_get_domain_keys == nullptr) { + return false; + } + + if (d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "get_domain_keys" << "(" << "name=" << name << ")" << endl, + d_slog->info(Logr::Debug, "Calling get_domain_keys", "domain", Logging::Loggable(name))); + } + get_domain_keys_result_t result = f_get_domain_keys(name.operator const DNSName&()); + + if (result.which() == 0) { + return false; + } + + for (const auto& row : boost::get>>(result)) { + DNSBackend::KeyData key; + key.published = true; + for (const auto& item : row.second) { + if (item.first == "content") { + key.content = boost::get(item.second); + } + else if (item.first == "id") { + key.id = static_cast(boost::get(item.second)); + } + else if (item.first == "flags") { + key.flags = static_cast(boost::get(item.second)); + } + else if (item.first == "active") { + key.active = boost::get(item.second); + } + else if (item.first == "published") { + key.published = boost::get(item.second); + } + else { + SLOG(g_log << Logger::Warning << "[" << getPrefix() << "] Unsupported key '" << item.first << "' in keydata result" << endl, + d_slog->info(Logr::Warning, "Unsupported key in keydata result", "key", Logging::Loggable(item.first))); + } + } + if (d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Got result " << "'" << "id=" << key.id << ",flags=" << key.flags << ",active=" << (key.active ? "true" : "false") << ",published=" << (key.published ? "true" : "false") << "'" << endl, + d_slog->info(Logr::Debug, "Got result", "id", Logging::Loggable(key.id), "flags", Logging::Loggable(key.flags), "active", Logging::Loggable(key.active ? "true" : "false"), "published", Logging::Loggable(key.published ? "true" : "false"))); + } + keys.emplace_back(std::move(key)); + } + + return true; +} + +bool Lua2BackendAPIv2::getBeforeAndAfterNamesAbsolute(domainid_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) +{ + if (f_get_before_and_after_names_absolute == nullptr) { + return false; + } + + if (d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "get_before_and_after_names_absolute" << "(" << "id=<<" << id << ",qname=" << qname << ")" << endl, + d_slog->info(Logr::Debug, "Calling get_before_and_after_names_absolute", "id", Logging::Loggable(id), "name", Logging::Loggable(qname))); + } + get_before_and_after_names_absolute_result_t result = f_get_before_and_after_names_absolute(id, qname); + + if (result.which() == 0) { + return false; + } + + before_and_after_names_result_t row = boost::get(result); + if (row.size() != 3) { + SLOG(g_log << Logger::Error << "Invalid result from dns_get_before_and_after_names_absolute, expected array with 3 items, got " << row.size() << "item(s)" << endl, + d_slog->info(Logr::Error, "Invalid result from dns_get_before_and_after_names_absolute, expected array with 3 rows", "rows returned", Logging::Loggable(row.size()))); + return false; + } + for (const auto& item : row) { + DNSName value; + if (item.second.which() == 0) { + value = DNSName(boost::get(item.second)); + } + else { + value = DNSName(boost::get(item.second)); + } + if (item.first == "unhashed") { + unhashed = std::move(value); + } + else if (item.first == "before") { + before = std::move(value); + } + else if (item.first == "after") { + after = std::move(value); + } + else { + SLOG(g_log << Logger::Error << "Invalid result from dns_get_before_and_after_names_absolute, unexpected key " << item.first << endl, + d_slog->info(Logr::Error, "Invalid result from dns_get_before_and_after_names_absolute, unexpected key", "key", Logging::Loggable(item.first))); + return false; + } + } + + if (d_debug_log) { + SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Got result " << "'" << "unhashed=" << unhashed << ",before=" << before << ",after=" << after << "'" << endl, + d_slog->info(Logr::Debug, "Got result", "unhashed", Logging::Loggable(unhashed), "before", Logging::Loggable(before), "after", Logging::Loggable(after))); + } + return true; +} diff --git a/modules/lua2backend/lua2api2.hh b/modules/lua2backend/lua2api2.hh index a301b8264a..e1981105d9 100644 --- a/modules/lua2backend/lua2api2.hh +++ b/modules/lua2backend/lua2api2.hh @@ -65,487 +65,24 @@ private: typedef std::function direct_backend_cmd_call_t; public: - Lua2BackendAPIv2(Logr::log_t slog, const string& suffix) - { - d_slog = slog; - d_include_path = ::arg()["lua-global-include-dir"]; - setArgPrefix("lua2" + suffix); - d_debug_log = mustDo("query-logging"); - prepareContext(); - loadFile(getArg("filename")); - } - + Lua2BackendAPIv2(Logr::log_t slog, const string& suffix); ~Lua2BackendAPIv2() override; - void postPrepareContext() override - { - AuthLua4::postPrepareContext(); - } - - void postLoad() override - { - f_lookup = d_lw->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); - f_get_domaininfo = d_lw->readVariable>("dns_get_domaininfo").get_value_or(0); - f_get_domain_metadata = d_lw->readVariable>("dns_get_domain_metadata").get_value_or(0); - f_get_all_domain_metadata = d_lw->readVariable>("dns_get_all_domain_metadata").get_value_or(0); - f_get_domain_keys = d_lw->readVariable>("dns_get_domain_keys").get_value_or(0); - f_get_before_and_after_names_absolute = d_lw->readVariable>("dns_get_before_and_after_names_absolute").get_value_or(0); - f_set_notified = d_lw->readVariable>("dns_set_notified").get_value_or(0); - - auto init = d_lw->readVariable>("dns_init").get_value_or(0); - if (init) { - init(); - } - - f_deinit = d_lw->readVariable>("dns_deinit").get_value_or(0); - - if (f_lookup == nullptr) { - throw PDNSException("dns_lookup missing"); - } - - /* see if dnssec support is wanted */ - d_dnssec = d_lw->readVariable>("dns_dnssec").get_value_or(false); - if (d_dnssec) { - if (f_get_domain_metadata == nullptr) { - throw PDNSException("dns_dnssec is true but dns_get_domain_metadata is missing"); - } - if (f_get_before_and_after_names_absolute == nullptr) { - 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) { - SLOG(g_log << Logger::Warning << "dns_get_domain_keys missing - cannot do live signing" << endl, - d_slog->info(Logr::Warning, "dns_get_domain_keys missing - cannot perform live signing")); - } - } - } - - unsigned int getCapabilities() override - { - unsigned int caps = CAP_DIRECT | CAP_LIST; - if (d_dnssec) { - caps |= CAP_DNSSEC; - } - if (f_get_all_domains != nullptr) { - caps |= CAP_SEARCH; - } - return caps; - } - - void parseLookup(const lookup_result_t& result) - { - for (const auto& row : result) { - DNSResourceRecord rec; - 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") { - rec.domain_id = boost::get(item.second); - } - else if (item.first == "auth") { - rec.auth = boost::get(item.second); - } - else if (item.first == "last_modified") { - rec.last_modified = static_cast(boost::get(item.second)); - } - else if (item.first == "ttl") { - rec.ttl = boost::get(item.second); - } - else if (item.first == "content") { - rec.setContent(boost::get(item.second)); - } - else if (item.first == "scopeMask") { - rec.scopeMask = boost::get(item.second); - } - else { - SLOG(g_log << Logger::Warning << "Unsupported key '" << item.first << "' in lookup or list result" << endl, - d_slog->info(Logr::Warning, "Unsupported kep in lookup or list result", "key", Logging::Loggable(item.first))); - } - } - if (d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Got result " << "'" << rec.qname << " IN " << rec.qtype.toString() << " " << rec.ttl << " " << rec.getZoneRepresentation() << "'" << endl, - d_slog->info(Logr::Debug, "Got result", "name", Logging::Loggable(rec.qname), "type", Logging::Loggable(rec.qtype), "ttl", Logging::Loggable(rec.ttl), "data", Logging::Loggable(rec.getZoneRepresentation()))); - } - d_result.push_back(std::move(rec)); - } - if (d_result.empty() && d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Got empty result" << endl, - d_slog->info(Logr::Debug, "Got empty result")); - } - } - - bool list(const ZoneName& target, domainid_t domain_id, bool /* include_disabled */ = false) override - { - if (f_list == nullptr) { - SLOG(g_log << Logger::Error << "[" << getPrefix() << "] dns_list missing - cannot do AXFR" << endl, - d_slog->info(Logr::Error, "dns_list missing - cannot perform AXFR")); - return false; - } - - if (d_result.size() != 0) { - throw PDNSException("list attempted while another was running"); - } - - if (d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "list" << "(" << "target=" << target << ",domain_id=" << domain_id << ")" << endl, - d_slog->info(Logr::Debug, "Calling list", "target", Logging::Loggable(target), "domain id", Logging::Loggable(domain_id))); - } - list_result_t result = f_list(target.operator const DNSName&(), domain_id); - - if (result.which() == 0) { - return false; - } - - parseLookup(boost::get(result)); - - return true; - } - - void lookup(const QType& qtype, const DNSName& qname, domainid_t domain_id, DNSPacket* p = nullptr) override - { - if (d_result.size() != 0) { - throw PDNSException("lookup attempted while another was running"); - } - - lookup_context_t ctx; - if (p != NULL) { - ctx.emplace_back(lookup_context_t::value_type{"source_address", p->getInnerRemote().toString()}); - ctx.emplace_back(lookup_context_t::value_type{"real_source_address", p->getRealRemote().toString()}); - } - - if (d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "lookup" << "(" << "qtype=" << qtype.toString() << ",qname=" << qname << ",domain_id=" << domain_id << ")" << endl, - d_slog->info(Logr::Debug, "Calling lookup", "type", Logging::Loggable(qtype), "name", Logging::Loggable(qname), "domain id", Logging::Loggable(domain_id))); - } - lookup_result_t result = f_lookup(qtype, qname, domain_id, ctx); - parseLookup(result); - } - - bool get(DNSResourceRecord& rr) override - { - if (d_result.size() == 0) { - return false; - } - rr = std::move(d_result.front()); - d_result.pop_front(); - return true; - } - - string directBackendCmd(const string& querystr) override - { - string::size_type pos = querystr.find_first_of(" \t"); - string cmd = querystr; - string par = ""; - if (pos != string::npos) { - cmd = querystr.substr(0, pos); - par = querystr.substr(pos + 1); - } - direct_backend_cmd_call_t f = d_lw->readVariable>(cmd).get_value_or(0); - if (f == nullptr) { - return cmd + "not found"; - } - if (d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << cmd << "(" << "parameter=" << par << ")" << endl, - d_slog->info(Logr::Debug, "Direct backend command", "command", Logging::Loggable(cmd), "parameters", Logging::Loggable(par))); - } - return f(par); - } - - void setNotified(domainid_t id, uint32_t serial) override - { - if (f_set_notified == NULL) { - return; - } - if (d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "dns_set_notified" << "(" << "id=" << id << ",serial=" << serial << ")" << endl, - d_slog->info(Logr::Debug, "Calling dns_set_notified", "id", Logging::Loggable(id), "serial", Logging::Loggable(serial))); - } - f_set_notified(id, serial); - } - - void parseDomainInfo(const domaininfo_result_t& row, DomainInfo& di) - { - di.id = UnknownDomainID; - for (const auto& item : row) { - if (item.first == "account") { - di.account = boost::get(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& primary : boost::get>(item.second)) { - di.primaries.push_back(ComboAddress(primary, 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 { - SLOG(g_log << Logger::Warning << "Unsupported key '" << item.first << "' in domaininfo result" << endl, - d_slog->info(Logr::Warning, "Unsupported key in domaininfo result", "key", Logging::Loggable(item.first))); - } - } - di.backend = this; - if (d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Got result " << "'" << "zone=" << di.zone << ",serial=" << di.serial << ",kind=" << di.getKindString() << "'" << endl, - d_slog->info(Logr::Debug, "Got domain info", "zone", Logging::Loggable(di.zone), "serial", Logging::Loggable(di.serial), "kind", Logging::Loggable(di.getKindString()))); - } - } - - bool getDomainInfo(const ZoneName& domain, DomainInfo& di, bool /* getSerial */ = true) override - { - if (f_get_domaininfo == nullptr) { - // use getAuth instead... but getAuth wraps getSOA which will call - // getDomainInfo if this is a domain variant, so protect against this - // would-be infinite recursion. - if (domain.hasVariant()) { - SLOG(g_log << Logger::Info << "Unable to return domain information for '" << domain.toLogString() << "' due to unimplemented dns_get_domaininfo" << endl, - d_slog->info(Logr::Info, "Unable to return domain information due to unimplemented dns_get_domaininfo", "domain", Logging::Loggable(domain))); - return false; - } - SOAData sd; - if (!getAuth(domain, &sd)) { - return false; - } - - di.id = sd.domain_id; - di.zone = domain; - di.backend = this; - di.serial = sd.serial; - return true; - } - - if (d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "get_domaininfo" << "(" << "domain=" << domain << ")" << endl, - d_slog->info(Logr::Debug, "Calling get_domaininfo", "domain", Logging::Loggable(domain))); - } - get_domaininfo_result_t result = f_get_domaininfo(domain.operator const DNSName&()); - - if (result.which() == 0) { - return false; - } - - di.zone = domain; - parseDomainInfo(boost::get(result), di); - - return true; - } - - void getAllDomains(vector* domains, bool /* getSerial */, bool /* include_disabled */) override - { - if (f_get_all_domains == nullptr) { - return; - } - - if (d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "get_all_domains" << "(" << "" << ")" << endl, - d_slog->info(Logr::Debug, "Calling get_all_domains")); - } - for (const auto& row : f_get_all_domains()) { - DomainInfo di; - di.zone = ZoneName(row.first); - if (d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Got result " << "'" << di.zone << "'" << endl, - d_slog->info(Logr::Debug, "Got result", "domain", Logging::Loggable(di.zone))); - } - parseDomainInfo(row.second, di); - domains->push_back(std::move(di)); - } - } - - bool getAllDomainMetadata(const ZoneName& name, std::map>& meta) override - { - if (f_get_all_domain_metadata == nullptr) { - return false; - } - - if (d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "get_all_domain_metadata" << "(" << "name=" << name << ")" << endl, - d_slog->info(Logr::Debug, "Calling get_all_domain_metadata", "domain", Logging::Loggable(name))); - } - get_all_domain_metadata_result_t result = f_get_all_domain_metadata(name.operator const DNSName&()); - if (result.which() == 0) { - return false; - } - - for (const auto& row : boost::get>>(result)) { - meta[row.first].clear(); - for (const auto& item : row.second) { - meta[row.first].push_back(item.second); - } - if (d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Got result " << "'" << "kind=" << row.first << ",value=" << boost::algorithm::join(meta[row.first], ", ") << "'" << endl, - d_slog->info(Logr::Debug, "Got result", "kind", Logging::Loggable(row.first), "value", Logging::Loggable(boost::algorithm::join(meta[row.first], ", ")))); - } - } - - return true; - } - - bool getDomainMetadata(const ZoneName& name, const std::string& kind, std::vector& meta) override - { - if (f_get_domain_metadata == nullptr) { - return false; - } - - if (d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "get_domain_metadata" << "(" << "name=" << name << ",kind=" << kind << ")" << endl, - d_slog->info(Logr::Debug, "Calling get_domain_metadata", "domain", Logging::Loggable(name), "kind", Logging::Loggable(kind))); - } - get_domain_metadata_result_t result = f_get_domain_metadata(name.operator const DNSName&(), kind); - if (result.which() == 0) { - return false; - } - - meta.clear(); - for (const auto& item : boost::get(result)) { - meta.push_back(item.second); - } - - if (d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Got result " << "'" << "value=" << boost::algorithm::join(meta, ", ") << "'" << endl, - d_slog->info(Logr::Debug, "Got result", "value", Logging::Loggable(boost::algorithm::join(meta, ", ")))); - } - return true; - } - - bool getDomainKeys(const ZoneName& name, std::vector& keys) override - { - if (f_get_domain_keys == nullptr) { - return false; - } - - if (d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "get_domain_keys" << "(" << "name=" << name << ")" << endl, - d_slog->info(Logr::Debug, "Calling get_domain_keys", "domain", Logging::Loggable(name))); - } - get_domain_keys_result_t result = f_get_domain_keys(name.operator const DNSName&()); - - if (result.which() == 0) { - return false; - } - - for (const auto& row : boost::get>>(result)) { - DNSBackend::KeyData key; - key.published = true; - for (const auto& item : row.second) { - if (item.first == "content") { - key.content = boost::get(item.second); - } - else if (item.first == "id") { - key.id = static_cast(boost::get(item.second)); - } - else if (item.first == "flags") { - key.flags = static_cast(boost::get(item.second)); - } - else if (item.first == "active") { - key.active = boost::get(item.second); - } - else if (item.first == "published") { - key.published = boost::get(item.second); - } - else { - SLOG(g_log << Logger::Warning << "[" << getPrefix() << "] Unsupported key '" << item.first << "' in keydata result" << endl, - d_slog->info(Logr::Warning, "Unsupported key in keydata result", "key", Logging::Loggable(item.first))); - } - } - if (d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Got result " << "'" << "id=" << key.id << ",flags=" << key.flags << ",active=" << (key.active ? "true" : "false") << ",published=" << (key.published ? "true" : "false") << "'" << endl, - d_slog->info(Logr::Debug, "Got result", "id", Logging::Loggable(key.id), "flags", Logging::Loggable(key.flags), "active", Logging::Loggable(key.active ? "true" : "false"), "published", Logging::Loggable(key.published ? "true" : "false"))); - } - keys.emplace_back(std::move(key)); - } - - return true; - } - - bool getBeforeAndAfterNamesAbsolute(domainid_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) override - { - if (f_get_before_and_after_names_absolute == nullptr) { - return false; - } - - if (d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Calling " << "get_before_and_after_names_absolute" << "(" << "id=<<" << id << ",qname=" << qname << ")" << endl, - d_slog->info(Logr::Debug, "Calling get_before_and_after_names_absolute", "id", Logging::Loggable(id), "name", Logging::Loggable(qname))); - } - get_before_and_after_names_absolute_result_t result = f_get_before_and_after_names_absolute(id, qname); - - if (result.which() == 0) { - return false; - } - - before_and_after_names_result_t row = boost::get(result); - if (row.size() != 3) { - SLOG(g_log << Logger::Error << "Invalid result from dns_get_before_and_after_names_absolute, expected array with 3 items, got " << row.size() << "item(s)" << endl, - d_slog->info(Logr::Error, "Invalid result from dns_get_before_and_after_names_absolute, expected array with 3 rows", "rows returned", Logging::Loggable(row.size()))); - return false; - } - for (const auto& item : row) { - DNSName value; - if (item.second.which() == 0) { - value = DNSName(boost::get(item.second)); - } - else { - value = DNSName(boost::get(item.second)); - } - if (item.first == "unhashed") { - unhashed = std::move(value); - } - else if (item.first == "before") { - before = std::move(value); - } - else if (item.first == "after") { - after = std::move(value); - } - else { - SLOG(g_log << Logger::Error << "Invalid result from dns_get_before_and_after_names_absolute, unexpected key " << item.first << endl, - d_slog->info(Logr::Error, "Invalid result from dns_get_before_and_after_names_absolute, unexpected key", "key", Logging::Loggable(item.first))); - return false; - } - } - - if (d_debug_log) { - SLOG(g_log << Logger::Debug << "[" << getPrefix() << "] Got result " << "'" << "unhashed=" << unhashed << ",before=" << before << ",after=" << after << "'" << endl, - d_slog->info(Logr::Debug, "Got result", "unhashed", Logging::Loggable(unhashed), "before", Logging::Loggable(before), "after", Logging::Loggable(after))); - } - return true; - } + void postPrepareContext() override; + void postLoad() override; + unsigned int getCapabilities() override; + bool list(const ZoneName& target, domainid_t domain_id, bool /* include_disabled */ = false) override; + void lookup(const QType& qtype, const DNSName& qname, domainid_t domain_id, DNSPacket* p = nullptr) override; + bool get(DNSResourceRecord& rr) override; + string directBackendCmd(const string& querystr) override; + void setNotified(domainid_t id, uint32_t serial) override; + void parseDomainInfo(const domaininfo_result_t& row, DomainInfo& di); + bool getDomainInfo(const ZoneName& domain, DomainInfo& di, bool /* getSerial */ = true) override; + void getAllDomains(vector* domains, bool /* getSerial */, bool /* include_disabled */) override; + bool getAllDomainMetadata(const ZoneName& name, std::map>& meta) override; + bool getDomainMetadata(const ZoneName& name, const std::string& kind, std::vector& meta) override; + bool getDomainKeys(const ZoneName& name, std::vector& keys) override; + bool getBeforeAndAfterNamesAbsolute(domainid_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) override; private: std::list d_result; @@ -568,4 +105,6 @@ private: set_notified_call_t f_set_notified; deinit_call_t f_deinit; + + void parseLookup(const lookup_result_t& result); };