namespace isc {
namespace d2 {
+// *********************** D2Params *************************
+
+const char *D2Params::DFT_IP_ADDRESS = "127.0.0.1";
+const size_t D2Params::DFT_PORT = 53001;
+const size_t D2Params::DFT_DNS_SERVER_TIMEOUT = 100;
+const char *D2Params::DFT_NCR_PROTOCOL = "UDP";
+const char *D2Params::DFT_NCR_FORMAT = "JSON";
+
+D2Params::D2Params(const isc::asiolink::IOAddress& ip_address,
+ const size_t port,
+ const size_t dns_server_timeout,
+ const dhcp_ddns::NameChangeProtocol& ncr_protocol,
+ const dhcp_ddns::NameChangeFormat& ncr_format)
+ : ip_address_(ip_address),
+ port_(port),
+ dns_server_timeout_(dns_server_timeout),
+ ncr_protocol_(ncr_protocol),
+ ncr_format_(ncr_format) {
+ validateContents();
+}
+
+D2Params::D2Params()
+ : ip_address_(isc::asiolink::IOAddress(DFT_IP_ADDRESS)),
+ port_(DFT_PORT),
+ dns_server_timeout_(DFT_DNS_SERVER_TIMEOUT),
+ ncr_protocol_(dhcp_ddns::NCR_UDP),
+ ncr_format_(dhcp_ddns::FMT_JSON) {
+ validateContents();
+}
+
+D2Params::~D2Params(){};
+
+void
+D2Params::validateContents() {
+ if ((ip_address_.toText() == "0.0.0.0") || (ip_address_.toText() == "::")) {
+ isc_throw(D2CfgError,
+ "D2Params: IP address cannot be \"" << ip_address_ << "\"");
+ }
+
+ if (port_ == 0) {
+ isc_throw(D2CfgError, "D2Params: port cannot be 0");
+ }
+
+ if (dns_server_timeout_ < 1) {
+ isc_throw(D2CfgError,
+ "D2Params: DNS server timeout must be larger than 0");
+ }
+
+ if (ncr_format_ != dhcp_ddns::FMT_JSON) {
+ isc_throw(D2CfgError, "D2Params: NCR Format:"
+ << dhcp_ddns::ncrFormatToString(ncr_format_)
+ << " is not yet supported");
+ }
+
+ if (ncr_protocol_ != dhcp_ddns::NCR_UDP) {
+ isc_throw(D2CfgError, "D2Params: NCR Protocol:"
+ << dhcp_ddns::ncrProtocolToString(ncr_protocol_)
+ << " is not yet supported");
+ }
+}
+
+bool
+D2Params::operator == (const D2Params& other) const {
+ return ((ip_address_ == other.ip_address_) &&
+ (port_ == other.port_) &&
+ (dns_server_timeout_ == other.dns_server_timeout_) &&
+ (ncr_protocol_ == other.ncr_protocol_) &&
+ (ncr_format_ == other.ncr_format_));
+}
+
+bool
+D2Params::operator != (const D2Params& other) const {
+ return (!(*this == other));
+}
+
+std::string
+D2Params::toText() const {
+ std::ostringstream stream;
+
+ stream << ", ip_address: " << ip_address_.toText()
+ << ", port: " << port_
+ << ", dns_server_timeout_: " << dns_server_timeout_
+ << ", ncr_protocol: "
+ << dhcp_ddns::ncrProtocolToString(ncr_protocol_)
+ << ", ncr_format: " << ncr_format_
+ << dhcp_ddns::ncrFormatToString(ncr_format_);
+
+ return (stream.str());
+}
+
+std::ostream&
+operator<<(std::ostream& os, const D2Params& config) {
+ os << config.toText();
+ return (os);
+}
+
// *********************** TSIGKeyInfo *************************
+ // Note these values match correpsonding values for Bind9's
+ // dnssec-keygen
+ const char* TSIGKeyInfo::HMAC_MD5_STR = "HMAC-MD5";
+ const char* TSIGKeyInfo::HMAC_SHA1_STR = "HMAC-SHA1";
+ const char* TSIGKeyInfo::HMAC_SHA224_STR = "HMAC-SHA224";
+ const char* TSIGKeyInfo::HMAC_SHA256_STR = "HMAC-SHA256";
+ const char* TSIGKeyInfo::HMAC_SHA384_STR = "HMAC-SHA384";
+ const char* TSIGKeyInfo::HMAC_SHA512_STR = "HMAC-SHA512";
TSIGKeyInfo::TSIGKeyInfo(const std::string& name, const std::string& algorithm,
const std::string& secret)
isc::Exception(file, line, what) { };
};
+/// @brief Acts as a storage vault for D2 global scalar parameters
+class D2Params {
+public:
+ /// @brief Default configuration constants.
+ //@{
+ /// @todo For now these are hard-coded as configuration layer cannot
+ /// readily provide them (see Trac #3358).
+ static const char *DFT_IP_ADDRESS;
+ static const size_t DFT_PORT;
+ static const size_t DFT_DNS_SERVER_TIMEOUT;
+ static const char *DFT_NCR_PROTOCOL;
+ static const char *DFT_NCR_FORMAT;
+ //@}
+
+ /// @brief Constructor
+ ///
+ /// @param ip_address IP address at which D2 should listen for NCRs
+ /// @param port port on which D2 should listen NCRs
+ /// @param dns_server_timeout maximum amount of time in milliseconds to
+ /// wait for a response to a single DNS update request.
+ /// @param ncr_protocol socket protocol D2 should use to receive NCRS
+ /// @param ncr_format packet format of the inbound NCRs
+ ///
+ /// @throw D2CfgError if:
+ /// -# ip_address is 0.0.0.0 or ::
+ /// -# port is 0
+ /// -# dns_server_timeout is < 1
+ /// -# ncr_protocol is invalid, currently only NCR_UDP is supported
+ /// -# ncr_format is invalid, currently only FMT_JSON is supported
+ D2Params(const isc::asiolink::IOAddress& ip_address,
+ const size_t port,
+ const size_t dns_server_timeout,
+ const dhcp_ddns::NameChangeProtocol& ncr_protocol,
+ const dhcp_ddns::NameChangeFormat& ncr_format);
+
+ /// @brief Default constructor
+ /// The default constructor creates an instance that has updates disabled.
+ D2Params();
+
+ /// @brief Destructor
+ virtual ~D2Params();
+
+ /// @brief Return the IP address D2 listens on.
+ const isc::asiolink::IOAddress& getIpAddress() const {
+ return(ip_address_);
+ }
+
+ /// @brief Return the TCP/UPD port D2 listens on.
+ size_t getPort() const {
+ return(port_);
+ }
+
+ /// @brief Return the DNS server timeout value.
+ size_t getDnsServerTimeout() const {
+ return(dns_server_timeout_);
+ }
+
+ /// @brief Return the socket protocol in use.
+ const dhcp_ddns::NameChangeProtocol& getNcrProtocol() const {
+ return(ncr_protocol_);
+ }
+
+ /// @brief Return the expected format of inbound requests (NCRs).
+ const dhcp_ddns::NameChangeFormat& getNcrFormat() const {
+ return(ncr_format_);
+ }
+
+ /// @brief Compares two D2Paramss for equality
+ bool operator == (const D2Params& other) const;
+
+ /// @brief Compares two D2Paramss for inequality
+ bool operator != (const D2Params& other) const;
+
+ /// @brief Generates a string representation of the class contents.
+ std::string toText() const;
+
+protected:
+ /// @brief Validates member values.
+ ///
+ /// Method is used by the constructor to validate member contents.
+ /// Currently checks:
+ /// -# ip_address is not 0.0.0.0 or ::
+ /// -# port is not 0
+ /// -# dns_server_timeout is 0
+ /// -# ncr_protocol is UDP
+ /// -# ncr_format is JSON
+ ///
+ /// @throw D2CfgError if contents are invalid
+ virtual void validateContents();
+
+private:
+ /// @brief IP address D2 listens on.
+ isc::asiolink::IOAddress ip_address_;
+
+ /// @brief IP port D2 listens on.
+ size_t port_;
+
+ /// @brief Timeout for a single DNS packet exchange in milliseconds.
+ size_t dns_server_timeout_;
+
+ /// @brief The socket protocol to use.
+ /// Currently only UDP is supported.
+ dhcp_ddns::NameChangeProtocol ncr_protocol_;
+
+ /// @brief Format of the inbound requests (NCRs).
+ /// Currently only JSON format is supported.
+ dhcp_ddns::NameChangeFormat ncr_format_;
+};
+
+/// @brief Dumps the contents of a D2Params as text to an output stream
+///
+/// @param os output stream to which text should be sent
+/// @param config D2Param instnace to dump
+std::ostream&
+operator<<(std::ostream& os, const D2Params& config);
+
+/// @brief Defines a pointer for D2Params instances.
+typedef boost::shared_ptr<D2Params> D2ParamsPtr;
+
/// @brief Represents a TSIG Key.
///
- /// Currently, this is simple storage class containing the basic attributes of
- /// a TSIG Key. It is intended primarily as a reference for working with
- /// actual keys and may eventually be replaced by isc::dns::TSIGKey. TSIG Key
- /// functionality at this stage is strictly limited to configuration parsing.
- /// @todo full functionality for using TSIG during DNS updates will be added
- /// in a future release.
+ /// Acts as both a storage class containing the basic attributes which
+ /// describe a TSIG Key, as well as owning and providing access to an
+ /// instance of the actual key (@ref isc::dns::TSIGKey) that can be used
+ /// by the IO layer for signing and verifying messages.
+ ///
class TSIGKeyInfo {
public:
+ /// @brief Defines string values for the supported TSIG algorithms
+ //@{
+ static const char* HMAC_MD5_STR;
+ static const char* HMAC_SHA1_STR;
+ static const char* HMAC_SHA256_STR;
+ static const char* HMAC_SHA224_STR;
+ static const char* HMAC_SHA384_STR;
+ static const char* HMAC_SHA512_STR;
+ //}@
/// @brief Constructor
///
dns_update_status_(DNSClient::OTHER), dns_update_response_(),
forward_change_completed_(false), reverse_change_completed_(false),
current_server_list_(), current_server_(), next_server_pos_(0),
- update_attempts_(0), cfg_mgr_(cfg_mgr) {
- update_attempts_(0), tsig_key_() {
- // @todo if io_service is NULL we are multi-threading and should
- // instantiate our own
++ update_attempts_(0), cfg_mgr_(cfg_mgr), tsig_key_() {
+ /// @todo if io_service is NULL we are multi-threading and should
+ /// instantiate our own
if (!io_service_) {
isc_throw(NameChangeTransactionError, "IOServicePtr cannot be null");
}
// use_tsig_ is true. We should be able to navigate to the TSIG key
// for the current server. If not we would need to add that.
- // @todo time out should ultimately be configurable, down to
- // server level?
+ D2ParamsPtr d2_params = cfg_mgr_->getD2Params();
dns_client_->doUpdate(*io_service_, current_server_->getIpAddress(),
- current_server_->getPort(),
- *dns_update_request_,
- DNS_UPDATE_DEFAULT_TIMEOUT,
- tsig_key_);
-
+ current_server_->getPort(), *dns_update_request_,
- d2_params->getDnsServerTimeout());
-
++ d2_params->getDnsServerTimeout(), tsig_key_);
// Message is on its way, so the next event should be NOP_EVT.
postNextEvent(NOP_EVT);
LOG_DEBUG(dctl_logger, DBGLVL_TRACE_DETAIL,
/// @brief Number of transmit attempts for the current request.
size_t update_attempts_;
+ /// @brief Pointer to the configuration manager.
+ D2CfgMgrPtr cfg_mgr_;
++
+ /// @brief Pointer to the TSIG key which should be used (if any).
+ dns::TSIGKeyPtr tsig_key_;
};
/// @brief Defines a pointer to a NameChangeTransaction.