123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446 |
- // Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- // PERFORMANCE OF THIS SOFTWARE.
- #ifndef CFGMGR_H
- #define CFGMGR_H
- #include <asiolink/io_address.h>
- #include <dhcp/option.h>
- #include <dhcp/option_definition.h>
- #include <dhcp/option_space.h>
- #include <dhcp/classify.h>
- #include <dhcpsrv/d2_client.h>
- #include <dhcpsrv/option_space_container.h>
- #include <dhcpsrv/pool.h>
- #include <dhcpsrv/subnet.h>
- #include <util/buffer.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. It currently holds information about zero or more subnets6.
- /// Each subnet may contain zero or more pools. Pool4 and Pool6 is the most
- /// basic "chunk" of configuration. It contains a range of assignable
- /// addresses.
- ///
- /// Below is a sketch of configuration inheritance (not implemented yet).
- /// 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 likely to be implemented in configuration handling
- /// routines, so there is no storage capability in a global scope for
- /// subnet-specific parameters.
- ///
- /// @todo: Implement Subnet4 support (ticket #2237)
- /// @todo: Implement option definition support
- /// @todo: Implement parameter inheritance
- class CfgMgr : public boost::noncopyable {
- public:
- /// @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 Add new option definition.
- ///
- /// @param def option definition to be added.
- /// @param option_space name of the option space to add definition to.
- ///
- /// @throw isc::dhcp::DuplicateOptionDefinition when the particular
- /// option definition already exists.
- /// @throw isc::dhcp::MalformedOptionDefinition when the pointer to
- /// an option definition is NULL.
- /// @throw isc::BadValue when the option space name is empty or
- /// when trying to override the standard option (in dhcp4 or dhcp6
- /// option space).
- void addOptionDef(const OptionDefinitionPtr& def,
- const std::string& option_space);
- /// @brief Return option definitions for particular option space.
- ///
- /// @param option_space option space.
- ///
- /// @return pointer to the collection of option definitions for
- /// the particular option space. The option collection is empty
- /// if no option exists for the option space specified.
- OptionDefContainerPtr
- getOptionDefs(const std::string& option_space) const;
- /// @brief Return option definition for a particular option space and code.
- ///
- /// @param option_space option space.
- /// @param option_code option code.
- ///
- /// @return an option definition or NULL pointer if option definition
- /// has not been found.
- OptionDefinitionPtr getOptionDef(const std::string& option_space,
- const uint16_t option_code) const;
- /// @brief Adds new DHCPv4 option space to the collection.
- ///
- /// @param space option space to be added.
- ///
- /// @throw isc::dhcp::InvalidOptionSpace invalid option space
- /// has been specified.
- void addOptionSpace4(const OptionSpacePtr& space);
- /// @brief Adds new DHCPv6 option space to the collection.
- ///
- /// @param space option space to be added.
- ///
- /// @throw isc::dhcp::InvalidOptionSpace invalid option space
- /// has been specified.
- void addOptionSpace6(const OptionSpacePtr& space);
- /// @brief Return option spaces for DHCPv4.
- ///
- /// @return A collection of option spaces.
- const OptionSpaceCollection& getOptionSpaces4() const {
- return (spaces4_);
- }
- /// @brief Return option spaces for DHCPv6.
- ///
- /// @return A collection of option spaces.
- const OptionSpaceCollection& getOptionSpaces6() const {
- return (spaces6_);
- }
- /// @brief get IPv6 subnet by address
- ///
- /// Finds a matching subnet, based on an address. This can be used
- /// in two cases: when trying to find an appropriate lease based on
- /// a) relay link address (that must be the address that is on link)
- /// b) our global address on the interface the message was received on
- /// (for directly connected clients)
- ///
- /// @param hint an address that belongs to a searched subnet
- ///
- /// @return a subnet object (or NULL if no suitable match was fount)
- Subnet6Ptr getSubnet6(const isc::asiolink::IOAddress& hint,
- const isc::dhcp::ClientClasses& classes);
- /// @brief get IPv6 subnet by interface name
- ///
- /// Finds a matching local subnet, based on interface name. This
- /// is used for selecting subnets that were explicitly marked by the
- /// user as reachable over specified network interface.
- /// @param iface_name interface name
- /// @return a subnet object (or NULL if no suitable match was fount)
- Subnet6Ptr getSubnet6(const std::string& iface_name,
- const isc::dhcp::ClientClasses& classes);
- /// @brief get IPv6 subnet by interface-id
- ///
- /// Another possibility to find a subnet is based on interface-id.
- ///
- /// @param interface_id content of interface-id option returned by a relay
- ///
- /// @return a subnet object
- Subnet6Ptr getSubnet6(OptionPtr interface_id,
- const isc::dhcp::ClientClasses& classes);
- /// @brief adds an IPv6 subnet
- ///
- /// @param subnet new subnet to be added.
- void addSubnet6(const Subnet6Ptr& subnet);
- /// @brief Delete all option definitions.
- void deleteOptionDefs();
- /// @todo: Add subnet6 removal routines. Currently it is not possible
- /// to remove subnets. The only case where subnet6 removal would be
- /// needed is a dynamic server reconfiguration - a use case that is not
- /// planned to be supported any time soon.
- /// @brief removes all IPv6 subnets
- ///
- /// This method removes all existing IPv6 subnets. It is used during
- /// reconfiguration - old configuration is wiped and new definitions
- /// are used to recreate subnets.
- ///
- /// @todo Implement more intelligent approach. Note that comparison
- /// between old and new configuration is tricky. For example: is
- /// 2000::/64 and 2000::/48 the same subnet or is it something
- /// completely new?
- void deleteSubnets6();
- /// @brief returns const reference to all subnets6
- ///
- /// This is used in a hook (subnet4_select), where the hook is able
- /// to choose a different subnet. Server code has to offer a list
- /// of possible choices (i.e. all subnets).
- /// @return a pointer to const Subnet6 collection
- const Subnet4Collection* getSubnets4() {
- return (&subnets4_);
- }
- /// @brief returns const reference to all subnets6
- ///
- /// This is used in a hook (subnet6_select), where the hook is able
- /// to choose a different subnet. Server code has to offer a list
- /// of possible choices (i.e. all subnets).
- /// @return a pointer to const Subnet6 collection
- const Subnet6Collection* getSubnets6() {
- return (&subnets6_);
- }
- /// @brief get IPv4 subnet by address
- ///
- /// Finds a matching subnet, based on an address. This can be used
- /// in two cases: when trying to find an appropriate lease based on
- /// a) relay link address (that must be the address that is on link)
- /// b) our global address on the interface the message was received on
- /// (for directly connected clients)
- ///
- /// @param hint an address that belongs to a searched subnet
- ///
- /// @return a subnet object
- Subnet4Ptr getSubnet4(const isc::asiolink::IOAddress& hint,
- const isc::dhcp::ClientClasses& classes);
- /// @brief adds a subnet4
- void addSubnet4(const Subnet4Ptr& subnet);
- /// @brief removes all IPv4 subnets
- ///
- /// This method removes all existing IPv4 subnets. It is used during
- /// reconfiguration - old configuration is wiped and new definitions
- /// are used to recreate subnets.
- ///
- /// @todo Implement more intelligent approach. Note that comparison
- /// between old and new configuration is tricky. For example: is
- /// 192.0.2.0/23 and 192.0.2.0/24 the same subnet or is it something
- /// completely new?
- void deleteSubnets4();
- /// @brief returns path do the data directory
- ///
- /// This method returns a path to writeable directory that DHCP servers
- /// can store data in.
- /// @return data directory
- std::string getDataDir();
- /// @brief Adds the name of the interface to the set of interfaces on which
- /// server should listen.
- ///
- /// @param iface A name of the interface being added to the listening set.
- void addActiveIface(const std::string& iface);
- /// @brief Sets the flag which indicates that server is supposed to listen
- /// on all available interfaces.
- ///
- /// This function does not close or open sockets. It simply marks that
- /// server should start to listen on all interfaces the next time sockets
- /// are reopened. Server should examine this flag when it gets reconfigured
- /// and configuration changes the interfaces that server should listen on.
- void activateAllIfaces();
- /// @brief Clear the collection of the interfaces that server should listen
- /// on.
- ///
- /// Apart from clearing the list of interfaces specified with
- /// @c CfgMgr::addListeningInterface, it also disables listening on all
- /// interfaces if it has been enabled using
- /// @c CfgMgr::activateAllInterfaces.
- /// Likewise @c CfgMgr::activateAllIfaces, this function does not close or
- /// open sockets. It marks all interfaces inactive for DHCP traffic.
- /// Server should examine this new setting when it attempts to
- /// reopen sockets (as a result of reconfiguration).
- void deleteActiveIfaces();
- /// @brief Check if specified interface should be used to listen to DHCP
- /// traffic.
- ///
- /// @param iface A name of the interface to be checked.
- ///
- /// @return true if the specified interface belongs to the set of the
- /// interfaces on which server is configured to listen.
- bool isActiveIface(const std::string& iface) const;
- /// @brief returns unicast a given interface should listen on (or NULL)
- ///
- /// This method will return an address for a specified interface, if the
- /// server is supposed to listen on unicast address. This address is
- /// intended to be used immediately. This pointer is valid only until
- /// the next configuration change.
- ///
- /// @return IOAddress pointer (or NULL if none)
- const isc::asiolink::IOAddress*
- getUnicast(const std::string& iface) const;
- /// @brief Sets whether server should send back client-id in DHCPv4
- ///
- /// This is a compatibility flag. The default (true) is compliant with
- /// RFC6842. False is for backward compatibility.
- ///
- /// @param echo should the client-id be sent or not
- void echoClientId(const bool echo) {
- echo_v4_client_id_ = echo;
- }
- /// @brief Returns whether server should send back client-id in DHCPv4.
- /// @return true if client-id should be returned, false otherwise.
- bool echoClientId() const {
- return (echo_v4_client_id_);
- }
- /// @brief Updates the DHCP-DDNS client configuration to the given value.
- ///
- /// @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);
- /// @param 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;
- 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();
- /// @brief a container for IPv6 subnets.
- ///
- /// That is a simple vector of pointers. It does not make much sense to
- /// optimize access time (e.g. using a map), because typical search
- /// pattern will use calling inRange() method on each subnet until
- /// a match is found.
- Subnet6Collection subnets6_;
- /// @brief a container for IPv4 subnets.
- ///
- /// That is a simple vector of pointers. It does not make much sense to
- /// optimize access time (e.g. using a map), because typical search
- /// pattern will use calling inRange() method on each subnet until
- /// a match is found.
- Subnet4Collection subnets4_;
- private:
- /// @brief Checks if the specified interface is listed as active.
- ///
- /// This function searches for the specified interface name on the list of
- /// active interfaces: @c CfgMgr::active_ifaces_. It does not take into
- /// account @c CfgMgr::all_ifaces_active_ flag. If this flag is set to true
- /// but the specified interface does not belong to
- /// @c CfgMgr::active_ifaces_, it will return false.
- ///
- /// @param iface interface name.
- ///
- /// @return true if specified interface belongs to
- /// @c CfgMgr::active_ifaces_.
- bool isIfaceListedActive(const std::string& iface) const;
- /// @brief A collection of option definitions.
- ///
- /// A collection of option definitions that can be accessed
- /// using option space name they belong to.
- OptionSpaceContainer<OptionDefContainer,
- OptionDefinitionPtr, std::string> option_def_spaces_;
- /// @brief Container for defined DHCPv6 option spaces.
- OptionSpaceCollection spaces6_;
- /// @brief Container for defined DHCPv4 option spaces.
- OptionSpaceCollection spaces4_;
- /// @brief directory where data files (e.g. server-id) are stored
- std::string datadir_;
- /// @name A collection of interface names on which server listens.
- //@{
- typedef std::list<std::string> ActiveIfacesCollection;
- std::list<std::string> active_ifaces_;
- //@}
- /// @name a collection of unicast addresses and the interfaces names the
- // server is supposed to listen on
- //@{
- typedef std::map<std::string, isc::asiolink::IOAddress> UnicastIfacesCollection;
- UnicastIfacesCollection unicast_addrs_;
- /// A flag which indicates that server should listen on all available
- /// interfaces.
- bool all_ifaces_active_;
- /// Indicates whether v4 server should send back client-id
- bool echo_v4_client_id_;
- /// @brief Manages the DHCP-DDNS client and its configuration.
- D2ClientMgr d2_client_mgr_;
- };
- } // namespace isc::dhcp
- } // namespace isc
- #endif // CFGMGR_H
|