From 5126b3d30b17cecd30256f3eb976d87b98df40b4 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Wed, 4 Aug 2021 14:56:35 +0200 Subject: [PATCH] [#2011] Checkpoint: added callout --- doc/devel/Doxyfile | 1 - src/bin/d2/d2_hooks.dox | 13 ++++ src/bin/d2/d2_process.cc | 2 +- src/bin/d2/nc_trans.cc | 98 ++++++++++++++++++++++++------- src/bin/d2/nc_trans.h | 8 +++ src/bin/d2/simple_add.cc | 2 +- src/bin/d2/tests/nc_test_utils.cc | 2 +- src/lib/d2srv/d2_config.cc | 5 +- src/lib/d2srv/d2_config.h | 6 +- 9 files changed, 106 insertions(+), 31 deletions(-) diff --git a/doc/devel/Doxyfile b/doc/devel/Doxyfile index 3c41f8aa7c..e190a0fada 100644 --- a/doc/devel/Doxyfile +++ b/doc/devel/Doxyfile @@ -898,7 +898,6 @@ INPUT = ../../src/bin/agent \ ../../src/lib/util \ ../../src/lib/util/encode \ ../../src/lib/util/io \ - ../../src/lib/util/random \ ../../src/lib/util/unittests \ ../../src/lib/yang \ . diff --git a/src/bin/d2/d2_hooks.dox b/src/bin/d2/d2_hooks.dox index 7cf4ee38a7..e1bde28c57 100644 --- a/src/bin/d2/d2_hooks.dox +++ b/src/bin/d2/d2_hooks.dox @@ -66,4 +66,17 @@ to the end of this list. considers the configuration is incorrect and rejects it using the error string as an error message. + @subsection d2HooksSelectKey select_key + - @b Arguments: + - name: @b current_server, type: isc::d2::DnsServerInfoPtr, direction: in + - name: @b tsig_key, type: isc::dns::TSIGKeyPtr, direction: in/out + + - @b Description: this callout is executed when the DNS server to send the + next DNS update was selected and a TSIG key to protect the DNS update + is looking for. Pointers to the selected DNS server and the current TSIG + key are provided. If a hook library wants to use another TSIG key the + pointer must be updated. + + - Next step status: IF any callout sets the status to value different + from CONTINUE the selected server is skipped. */ diff --git a/src/bin/d2/d2_process.cc b/src/bin/d2/d2_process.cc index f6f2a32cb5..973e98e248 100644 --- a/src/bin/d2/d2_process.cc +++ b/src/bin/d2/d2_process.cc @@ -24,7 +24,7 @@ namespace { struct D2ProcessHooks { int hooks_index_d2_srv_configured_; - /// Constructor that registers hook points for the DHCPv4 server. + /// Constructor that registers hook points for the D2 server. D2ProcessHooks() { hooks_index_d2_srv_configured_ = HooksManager::registerHook("d2_srv_configured"); } diff --git a/src/bin/d2/nc_trans.cc b/src/bin/d2/nc_trans.cc index 2321ee72e9..bca27aa70e 100644 --- a/src/bin/d2/nc_trans.cc +++ b/src/bin/d2/nc_trans.cc @@ -10,11 +10,35 @@ #include #include #include +#include +#include #include +using namespace isc::hooks; using namespace isc::util; +namespace { + +/// Structure that holds registered hook indexes. +struct NcTransHooks { + int hooks_index_select_key_; + + /// Constructor that registers hook points for the D2 server. + NcTransHooks() { + hooks_index_select_key_ = HooksManager::registerHook("select_key"); + } +}; + +// Declare a Hooks object. As this is outside any function or method, it +// will be instantiated (and the constructor run) when the module is loaded. +// As a result, the hook indexes will be defined before any method in this +// module is called. + +NcTransHooks Hooks; + +} + namespace isc { namespace d2 { @@ -437,33 +461,65 @@ NameChangeTransaction::initServerSelection(const DdnsDomainPtr& domain) { bool NameChangeTransaction::selectNextServer() { - if ((current_server_list_) && - (next_server_pos_ < current_server_list_->size())) { - current_server_ = (*current_server_list_)[next_server_pos_]; - // Toss out any previous response. - dns_update_response_.reset(); - - // Set the tsig_key to that of the current server.. - TSIGKeyInfoPtr tsig_key_info = current_server_->getTSIGKeyInfo(); - if (tsig_key_info) { - tsig_key_ = tsig_key_info->getTSIGKey(); - } else { - tsig_key_.reset(); + for (;;) { + if ((current_server_list_) && + (next_server_pos_ < current_server_list_->size())) { + current_server_ = (*current_server_list_)[next_server_pos_]; + // Toss out any previous response. + dns_update_response_.reset(); + + // Set the tsig_key to that of the current server.. + if (!selectTSIGKey()) { + ++next_server_pos_; + continue; + } + + // @todo Protocol is set on DNSClient constructor. We need + // to propagate a configuration value downward, probably starting + // at global, then domain, then server + // Once that is supported we need to add it here. + dns_client_.reset(new DNSClient(dns_update_response_ , this, + DNSClient::UDP)); + ++next_server_pos_; + return (true); } - // @todo Protocol is set on DNSClient constructor. We need - // to propagate a configuration value downward, probably starting - // at global, then domain, then server - // Once that is supported we need to add it here. - dns_client_.reset(new DNSClient(dns_update_response_ , this, - DNSClient::UDP)); - ++next_server_pos_; - return (true); + return (false); } +} - return (false); +bool +NameChangeTransaction::selectTSIGKey() { + TSIGKeyInfoPtr tsig_key_info = current_server_->getTSIGKeyInfo(); + if (tsig_key_info) { + tsig_key_ = tsig_key_info->getTSIGKey(); + } else { + tsig_key_.reset(); + } + + // This hook point allows hooks libraries to overwrite the TSIG key. + if (HooksManager::calloutsPresent(Hooks.hooks_index_select_key_)) { + CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle(); + + callout_handle->setArgument("current_server", current_server_); + callout_handle->setArgument("tsig_key", tsig_key_); + + HooksManager::callCallouts(Hooks.hooks_index_select_key_, + *callout_handle); + + // This server is skipped not NEXT_STEP_CONTINUE status. + if (callout_handle->getStatus() != CalloutHandle::NEXT_STEP_CONTINUE) { + return (false); + } + + // Reread the TSIG key. + callout_handle->getArgument("tsig_key", tsig_key_); + } + + return (true); } + const DNSClientPtr& NameChangeTransaction::getDNSClient() const { return (dns_client_); diff --git a/src/bin/d2/nc_trans.h b/src/bin/d2/nc_trans.h index ba8ddad760..a25b5da57f 100644 --- a/src/bin/d2/nc_trans.h +++ b/src/bin/d2/nc_trans.h @@ -343,6 +343,14 @@ protected: /// servers from which to select. bool selectNextServer(); + /// @brief Selects the TSIG key. + /// + /// This method uses the current server and the select_key callout. + /// When no TSIG key is selected the tsig_key_ pointer is null. + /// + /// @return False when the current server should be skipped. + bool selectTSIGKey(); + /// @brief Sets the update attempt count to the given value. /// /// @param value is the new value to assign. diff --git a/src/bin/d2/simple_add.cc b/src/bin/d2/simple_add.cc index 957e67bc1e..7c7b0cf2c4 100644 --- a/src/bin/d2/simple_add.cc +++ b/src/bin/d2/simple_add.cc @@ -511,7 +511,7 @@ SimpleAddTransaction::buildReplaceRevPtrsRequest() { // There are no prerequisites. - // Create the FQDN/IP PTR 'delete' RR for this IP and add it to + // Create the FQDN/IP PTR 'delete' RR for this IP and add it to // the update section. dns::RRsetPtr update(new dns::RRset(rev_ip, dns::RRClass::ANY(), dns::RRType::PTR(), dns::RRTTL(0))); diff --git a/src/bin/d2/tests/nc_test_utils.cc b/src/bin/d2/tests/nc_test_utils.cc index 8608182cb5..f4888d492a 100644 --- a/src/bin/d2/tests/nc_test_utils.cc +++ b/src/bin/d2/tests/nc_test_utils.cc @@ -500,7 +500,7 @@ void addDomainServer(DdnsDomainPtr& domain, const std::string& name, const std::string& ip, const size_t port, const TSIGKeyInfoPtr &tsig_key_info) { DnsServerInfoPtr server(new DnsServerInfo(name, asiolink::IOAddress(ip), - port, true, tsig_key_info, true)); + port, true, tsig_key_info)); domain->getServers()->push_back(server); } diff --git a/src/lib/d2srv/d2_config.cc b/src/lib/d2srv/d2_config.cc index a6c2d162e5..40baf5f609 100644 --- a/src/lib/d2srv/d2_config.cc +++ b/src/lib/d2srv/d2_config.cc @@ -495,13 +495,14 @@ DnsServerInfoParser::parse(ConstElementPtr server_config, // Key name is optional. If it is not blank, then find the key in the // list of defined keys. TSIGKeyInfoPtr tsig_key_info; - bool inherited_key = false; + bool inherited_key = true; if (key_name.empty()) { std::string domain_key_name = getString(domain_config, "key-name"); if (!domain_key_name.empty()) { key_name = domain_key_name; - inherited_key = true; } + } else { + inherited_key = false; } if (!key_name.empty()) { if (keys) { diff --git a/src/lib/d2srv/d2_config.h b/src/lib/d2srv/d2_config.h index d687695743..9faf097f17 100644 --- a/src/lib/d2srv/d2_config.h +++ b/src/lib/d2srv/d2_config.h @@ -438,14 +438,13 @@ public: /// @param tsig_key_info pointer to the TSIGKeyInfo for the server's key /// It defaults to an empty pointer, signifying the server has no key. /// @param inherited_key is a flag that indicates whether the key was - /// inherited from the domain or not. It defaults to false i.e. not - /// inherited. + /// inherited from the domain or not. It defaults to true i.e. inherited. DnsServerInfo(const std::string& hostname, isc::asiolink::IOAddress ip_address, uint32_t port = STANDARD_DNS_PORT, bool enabled = true, const TSIGKeyInfoPtr& tsig_key_info = TSIGKeyInfoPtr(), - bool inherited_key = false); + bool inherited_key = true); /// @brief Destructor virtual ~DnsServerInfo(); @@ -801,7 +800,6 @@ public: /// 3. Add the new TSIGKeyInfo instance to the key map /// /// @param key_list_config is the list of "tsig_key" elements to parse. - /// @param keys map of defined TSIG keys /// /// @return a map containing the TSIGKeyInfo instances TSIGKeyInfoMapPtr parse(data::ConstElementPtr key_list_config); -- 2.47.3