diff options
Diffstat (limited to 'src/lib/dhcpsrv/cfgmgr.h')
-rw-r--r-- | src/lib/dhcpsrv/cfgmgr.h | 357 |
1 files changed, 357 insertions, 0 deletions
diff --git a/src/lib/dhcpsrv/cfgmgr.h b/src/lib/dhcpsrv/cfgmgr.h new file mode 100644 index 0000000..d34b1c5 --- /dev/null +++ b/src/lib/dhcpsrv/cfgmgr.h @@ -0,0 +1,357 @@ +// Copyright (C) 2012-2022 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef CFGMGR_H +#define CFGMGR_H + +#include <asiolink/io_address.h> +#include <dhcp/option.h> +#include <dhcp/option_space.h> +#include <dhcp/classify.h> +#include <dhcpsrv/d2_client_mgr.h> +#include <dhcpsrv/pool.h> +#include <dhcpsrv/srv_config.h> +#include <util/buffer.h> +#include <util/optional.h> + +#include <boost/shared_ptr.hpp> +#include <boost/noncopyable.hpp> + +#include <map> +#include <string> +#include <vector> +#include <list> + +namespace isc { +namespace dhcp { + +/// @brief Exception thrown when the same interface has been specified twice. +/// +/// In particular, this exception is thrown when adding interface to the set +/// of interfaces on which server is supposed to listen. +class DuplicateListeningIface : public Exception { +public: + DuplicateListeningIface(const char* file, size_t line, const char* what) : + isc::Exception(file, line, what) { }; +}; + +/// @brief Configuration Manager +/// +/// This singleton class holds the whole configuration for DHCPv4 and DHCPv6 +/// servers. +/// +/// Below is a sketch of configuration inheritance. +/// Let's investigate the following configuration: +/// +/// @code +/// preferred-lifetime 500; +/// valid-lifetime 1000; +/// subnet6 2001:db8:1::/48 { +/// pool6 2001::db8:1::1 - 2001::db8:1::ff; +/// }; +/// subnet6 2001:db8:2::/48 { +/// valid-lifetime 2000; +/// pool6 2001::db8:2::1 - 2001::db8:2::ff; +/// }; +/// @endcode +/// +/// Parameters defined in a global scope are applicable to everything until +/// they are overwritten in a smaller scope, in this case subnet6. +/// In the example above, the first subnet6 has preferred lifetime of 500s +/// and a valid lifetime of 1000s. The second subnet has preferred lifetime +/// of 500s, but valid lifetime of 2000s. +/// +/// Parameter inheritance is implemented in dedicated classes. See +/// @ref isc::dhcp::SimpleParser4::deriveParameters and +/// @ref isc::dhcp::SimpleParser6::deriveParameters. +class CfgMgr : public boost::noncopyable { +public: + + /// @brief A number of configurations held by @c CfgMgr. + /// + /// @todo Make it configurable. + static const size_t CONFIG_LIST_SIZE; + + /// @brief returns a single instance of Configuration Manager + /// + /// CfgMgr is a singleton and this method is the only way of + /// accessing it. + static CfgMgr& instance(); + + /// @brief returns path do the data directory + /// + /// This method returns a path to writable directory that DHCP servers + /// can store data in. + /// @return data directory + util::Optional<std::string> getDataDir() const; + + /// @brief Sets new data directory. + /// + /// @param datadir New data directory. + /// @param unspecified Initial state. Default is "unspecified". + void setDataDir(const std::string& datadir, bool unspecified = true); + + /// @brief Updates the DHCP-DDNS client configuration to the given value. + /// + /// Passes the new configuration to the D2ClientMgr instance, + /// d2_client_mgr_, which will attempt to apply the new configuration + /// by shutting down its sender and opening a new connection per the new + /// configuration (see @c D2ClientMgr::setD2ClientConfig()). + /// + /// @param new_config pointer to the new client configuration. + /// + /// @throw Underlying method(s) will throw D2ClientError if given an empty + /// pointer. + void setD2ClientConfig(D2ClientConfigPtr& new_config); + + /// @brief Convenience method for checking if DHCP-DDNS updates are enabled. + /// + /// @return True if the D2 configuration is enabled. + bool ddnsEnabled(); + + /// @brief Fetches the DHCP-DDNS configuration pointer. + /// + /// @return a reference to the current configuration pointer. + const D2ClientConfigPtr& getD2ClientConfig() const; + + /// @brief Fetches the DHCP-DDNS manager. + /// + /// @return a reference to the DHCP-DDNS manager. + D2ClientMgr& getD2ClientMgr(); + + /// @name Methods managing the collection of configurations. + /// + /// The following methods manage the process of preparing a configuration + /// without affecting a currently used configuration and then committing + /// the configuration to replace current configuration atomically. + /// They also allow for keeping a history of previous configurations so + /// as the @c CfgMgr can revert to the historical configuration when + /// required. + /// + /// @todo Migrate all configuration parameters to use the model supported + /// by these functions. + /// + /// @todo Make the size of the configurations history configurable. + /// + //@{ + + /// @brief Removes current, staging and all previous configurations. + /// + /// This function removes all configurations, including current, + /// staging and external configurations. It creates a new current + /// configuration with default settings. + /// + /// This function is exception safe. + void clear(); + + /// @brief Commits the staging configuration. + /// + /// The staging configuration becomes current configuration when this + /// function is called. It removes the oldest configuration held in the + /// history so as the size of the list of configuration does not exceed + /// the @c CONFIG_LIST_SIZE. + /// + /// This function is exception safe. + void commit(); + + /// @brief Removes staging configuration. + /// + /// This function should be called when there is a staging configuration + /// (likely created in the previous configuration attempt) but the entire + /// new configuration should be created. It removes the existing staging + /// configuration and the next call to @c CfgMgr::getStagingCfg will return a + /// fresh (default) configuration. + /// + /// This function is exception safe. + void rollback(); + + /// @brief Reverts to one of the previous configurations. + /// + /// This function reverts to selected previous configuration. The previous + /// configuration is entirely copied to a new @c SrvConfig instance. This + /// new instance has a unique sequence id (sequence id is not copied). The + /// previous configuration (being copied) is not modified by this operation. + /// + /// The configuration to be copied is identified by the index value which + /// is the distance between the current (most recent) and desired + /// configuration. If the index is out of range an exception is thrown. + /// + /// @warning Revert operation will rollback any changes to the staging + /// configuration (if it exists). + /// + /// @warning This function requires that the entire previous configuration + /// is copied to the new configuration object. This is not working for + /// some of the complex configuration objects, e.g. subnets. Hence, the + /// "revert" operation is not really usable at this point. + /// + /// @param index A distance from the current configuration to the + /// past configuration to be reverted. The minimal value is 1 which points + /// to the nearest configuration. + /// + /// @throw isc::OutOfRange if the specified index is out of range. + void revert(const size_t index); + + /// @brief Returns a pointer to the current configuration. + /// + /// This function returns pointer to the current configuration. If the + /// current configuration is not set it will create a default configuration + /// and return it. + /// + /// In the previous Kea releases this method used to return a const pointer + /// to the current configuration to ensure that it is not accidentally + /// modified while the server is running. This has been changed in Kea 1.3 + /// release and now this function returns a non-const pointer. The reason + /// is that there are certain use cases when current configuration must + /// be modified without going through a full cycle of server + /// reconfiguration, e.g. add a subnet to the current configuration as + /// a result of receiving a command over control API. In such case the + /// performance of processing such command is critical and rebuilding the + /// whole configuration just for this small configuration change is out + /// of question. + /// + /// Nevertheless, such configuration updates should always be made with + /// caution and one has to make sure that the configuration data integrity + /// is preserved. + /// + /// @return Non-null pointer to the current configuration. + SrvConfigPtr getCurrentCfg(); + + /// @brief Returns a pointer to the staging configuration. + /// + /// The staging configuration is used by the configuration parsers to + /// create new configuration. The staging configuration doesn't affect the + /// server's operation until it is committed. The staging configuration + /// is a non-const object which can be modified by the caller. + /// + /// Multiple consecutive calls to this function return the same object + /// which can be modified from various places of the code (e.g. various + /// configuration parsers). + /// + /// @return non-null pointer to the staging configuration. + SrvConfigPtr getStagingCfg(); + + /// @brief Creates an external configuration and returns pointer to it. + /// + /// External configurations are those that come from other sources than + /// from the configuration file, e.g. a database or a command. They + /// are created aside and merged into the staging or current configuration. + /// External configurations are accessed by their sequence numbers. The + /// sequence numbers are autogenerated when the external configuration + /// instance is created. + /// + /// @return non-null pointer to created external configuration. + SrvConfigPtr createExternalCfg(); + + /// @brief Merges external configuration with the given sequence number + /// into the staging configuration. + /// + /// After the merge, the source configuration is discarded from the + /// @c CfgMgr as it should not be used anymore. + /// + /// @param seq Source configuration sequence number. + /// + /// @throw BadValue if the external configuration with the given sequence + /// number doesn't exist. + void mergeIntoStagingCfg(const uint32_t seq); + + /// @brief Merges external configuration with the given sequence number + /// into the current configuration. + /// + /// After the merge, the source configuration is discarded from the + /// @c CfgMgr as it should not be used anymore. + /// + /// @param seq Source configuration sequence number. + /// + /// @throw BadValue if the external configuration with the given sequence + /// number doesn't exist. + void mergeIntoCurrentCfg(const uint32_t seq); + + //@} + + /// @brief Sets address family (AF_INET or AF_INET6) + void setFamily(uint16_t family) { + family_ = family == AF_INET ? AF_INET : AF_INET6; + } + + /// @brief Returns address family. + uint16_t getFamily() const { + return (family_); + } + + //@} + +protected: + + /// @brief Protected constructor. + /// + /// This constructor is protected for 2 reasons. First, it forbids any + /// instantiations of this class (CfgMgr is a singleton). Second, it + /// allows derived class to instantiate it. That is useful for testing + /// purposes. + CfgMgr(); + + /// @brief virtual destructor + virtual ~CfgMgr(); + +private: + + /// @brief Checks if current configuration is created and creates it if needed. + /// + /// This private method is called to ensure that the current configuration + /// is created. If current configuration is not set, it creates the + /// default current configuration. + void ensureCurrentAllocated(); + + + /// @brief Merges external configuration with the given sequence number + /// into the specified configuration. + /// + /// @param target_config Pointer to the configuration into which the + /// external configuration should be merged. + /// @param seq Source configuration sequence number. + void mergeIntoCfg(const SrvConfigPtr& taget_config, const uint32_t seq); + + /// @brief directory where data files (e.g. server-id) are stored + util::Optional<std::string> datadir_; + + /// @brief Manages the DHCP-DDNS client and its configuration. + D2ClientMgr d2_client_mgr_; + + /// @brief Server configuration + /// + /// This is a structure that will hold all configuration. + /// @todo: migrate all other parameters to that structure. + SrvConfigPtr configuration_; + + /// @name Configuration List. + /// + //@{ + /// @brief Server configuration list type. + typedef std::list<SrvConfigPtr> SrvConfigList; + + /// @brief Container holding all previous and current configurations. + SrvConfigList configs_; + //@} + + /// @name Map of external configurations. + /// + //@{ + /// @brief Server configuration map type. + typedef std::map<uint32_t, SrvConfigPtr> SrvConfigMap; + + /// @brief Map of external configurations with sequence numbers used + /// as keys. + SrvConfigMap external_configs_; + //@} + + /// @brief Address family. + uint16_t family_; +}; + +} // namespace isc::dhcp +} // namespace isc + +#endif // CFGMGR_H |