cfgmgr.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. // Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef CFGMGR_H
  15. #define CFGMGR_H
  16. #include <asiolink/io_address.h>
  17. #include <dhcp/option.h>
  18. #include <dhcp/option_definition.h>
  19. #include <dhcp/option_space.h>
  20. #include <dhcpsrv/option_space_container.h>
  21. #include <dhcpsrv/pool.h>
  22. #include <dhcpsrv/subnet.h>
  23. #include <util/buffer.h>
  24. #include <boost/shared_ptr.hpp>
  25. #include <boost/noncopyable.hpp>
  26. #include <map>
  27. #include <string>
  28. #include <vector>
  29. namespace isc {
  30. namespace dhcp {
  31. /// @brief Configuration Manager
  32. ///
  33. /// This singleton class holds the whole configuration for DHCPv4 and DHCPv6
  34. /// servers. It currently holds information about:
  35. /// - Zero or more subnets. Each subnet may contain zero or more pools. Pool4
  36. /// and Pool6 is the most basic "chunk" of configuration. It contains a range
  37. /// of assignable addresses.
  38. /// - Hook libraries. Hooks library names are stored here, but only up to the
  39. /// point that the libraries are reloaded. In more detail: libraries
  40. /// containing hooks callouts can only be loaded and reloaded safely (or, more
  41. /// accurately, unloaded safely) when no data structure in the server contains
  42. /// a reference to any memory allocated by a function in them. In practice
  43. /// this means when there are no packets being activly processed. Rather than
  44. /// take a chance that the configuration code will do the unload/load at the
  45. /// right time, the configuration code sets the names of the new libraries in
  46. /// this object and the server decides when to reconfigure the hooks. The
  47. /// presence or absence of the names of the hooks libraries here is an
  48. /// indication of whether the libraries should be reloaded.
  49. ///
  50. /// Below is a sketch of configuration inheritance (not implemented yet).
  51. /// Let's investigate the following configuration:
  52. ///
  53. /// @code
  54. /// preferred-lifetime 500;
  55. /// valid-lifetime 1000;
  56. /// subnet6 2001:db8:1::/48 {
  57. /// pool6 2001::db8:1::1 - 2001::db8:1::ff;
  58. /// };
  59. /// subnet6 2001:db8:2::/48 {
  60. /// valid-lifetime 2000;
  61. /// pool6 2001::db8:2::1 - 2001::db8:2::ff;
  62. /// };
  63. /// @endcode
  64. ///
  65. /// Parameters defined in a global scope are applicable to everything until
  66. /// they are overwritten in a smaller scope, in this case subnet6.
  67. /// In the example above, the first subnet6 has preferred lifetime of 500s
  68. /// and a valid lifetime of 1000s. The second subnet has preferred lifetime
  69. /// of 500s, but valid lifetime of 2000s.
  70. ///
  71. /// Parameter inheritance is likely to be implemented in configuration handling
  72. /// routines, so there is no storage capability in a global scope for
  73. /// subnet-specific parameters.
  74. ///
  75. /// ARE THESE DONE?
  76. /// @todo: Implement Subnet4 support (ticket #2237)
  77. /// @todo: Implement option definition support
  78. /// @todo: Implement parameter inheritance
  79. class CfgMgr : public boost::noncopyable {
  80. public:
  81. /// @brief returns a single instance of Configuration Manager
  82. ///
  83. /// CfgMgr is a singleton and this method is the only way of
  84. /// accessing it.
  85. static CfgMgr& instance();
  86. /// @brief Add new option definition.
  87. ///
  88. /// @param def option definition to be added.
  89. /// @param option_space name of the option space to add definition to.
  90. ///
  91. /// @throw isc::dhcp::DuplicateOptionDefinition when the particular
  92. /// option definition already exists.
  93. /// @throw isc::dhcp::MalformedOptionDefinition when the pointer to
  94. /// an option definition is NULL.
  95. /// @throw isc::BadValue when the option space name is empty or
  96. /// when trying to override the standard option (in dhcp4 or dhcp6
  97. /// option space).
  98. void addOptionDef(const OptionDefinitionPtr& def,
  99. const std::string& option_space);
  100. /// @brief Return option definitions for particular option space.
  101. ///
  102. /// @param option_space option space.
  103. ///
  104. /// @return pointer to the collection of option definitions for
  105. /// the particular option space. The option collection is empty
  106. /// if no option exists for the option space specified.
  107. OptionDefContainerPtr
  108. getOptionDefs(const std::string& option_space) const;
  109. /// @brief Return option definition for a particular option space and code.
  110. ///
  111. /// @param option_space option space.
  112. /// @param option_code option code.
  113. ///
  114. /// @return an option definition or NULL pointer if option definition
  115. /// has not been found.
  116. OptionDefinitionPtr getOptionDef(const std::string& option_space,
  117. const uint16_t option_code) const;
  118. /// @brief Adds new DHCPv4 option space to the collection.
  119. ///
  120. /// @param space option space to be added.
  121. ///
  122. /// @throw isc::dhcp::InvalidOptionSpace invalid option space
  123. /// has been specified.
  124. void addOptionSpace4(const OptionSpacePtr& space);
  125. /// @brief Adds new DHCPv6 option space to the collection.
  126. ///
  127. /// @param space option space to be added.
  128. ///
  129. /// @throw isc::dhcp::InvalidOptionSpace invalid option space
  130. /// has been specified.
  131. void addOptionSpace6(const OptionSpacePtr& space);
  132. /// @brief Return option spaces for DHCPv4.
  133. ///
  134. /// @return A collection of option spaces.
  135. const OptionSpaceCollection& getOptionSpaces4() const {
  136. return (spaces4_);
  137. }
  138. /// @brief Return option spaces for DHCPv6.
  139. ///
  140. /// @return A collection of option spaces.
  141. const OptionSpaceCollection& getOptionSpaces6() const {
  142. return (spaces6_);
  143. }
  144. /// @brief get IPv6 subnet by address
  145. ///
  146. /// Finds a matching subnet, based on an address. This can be used
  147. /// in two cases: when trying to find an appropriate lease based on
  148. /// a) relay link address (that must be the address that is on link)
  149. /// b) our global address on the interface the message was received on
  150. /// (for directly connected clients)
  151. ///
  152. /// @param hint an address that belongs to a searched subnet
  153. ///
  154. /// @return a subnet object (or NULL if no suitable match was fount)
  155. Subnet6Ptr getSubnet6(const isc::asiolink::IOAddress& hint);
  156. /// @brief get IPv6 subnet by interface name
  157. ///
  158. /// Finds a matching local subnet, based on interface name. This
  159. /// is used for selecting subnets that were explicitly marked by the
  160. /// user as reachable over specified network interface.
  161. /// @param iface_name interface name
  162. /// @return a subnet object (or NULL if no suitable match was fount)
  163. Subnet6Ptr getSubnet6(const std::string& iface_name);
  164. /// @brief get IPv6 subnet by interface-id
  165. ///
  166. /// Another possibility to find a subnet is based on interface-id.
  167. ///
  168. /// @param interface_id content of interface-id option returned by a relay
  169. ///
  170. /// @return a subnet object
  171. Subnet6Ptr getSubnet6(OptionPtr interface_id);
  172. /// @brief adds an IPv6 subnet
  173. ///
  174. /// @param subnet new subnet to be added.
  175. void addSubnet6(const Subnet6Ptr& subnet);
  176. /// @brief Delete all option definitions.
  177. void deleteOptionDefs();
  178. /// @todo: Add subnet6 removal routines. Currently it is not possible
  179. /// to remove subnets. The only case where subnet6 removal would be
  180. /// needed is a dynamic server reconfiguration - a use case that is not
  181. /// planned to be supported any time soon.
  182. /// @brief removes all IPv6 subnets
  183. ///
  184. /// This method removes all existing IPv6 subnets. It is used during
  185. /// reconfiguration - old configuration is wiped and new definitions
  186. /// are used to recreate subnets.
  187. ///
  188. /// @todo Implement more intelligent approach. Note that comparison
  189. /// between old and new configuration is tricky. For example: is
  190. /// 2000::/64 and 2000::/48 the same subnet or is it something
  191. /// completely new?
  192. void deleteSubnets6();
  193. /// @brief get IPv4 subnet by address
  194. ///
  195. /// Finds a matching subnet, based on an address. This can be used
  196. /// in two cases: when trying to find an appropriate lease based on
  197. /// a) relay link address (that must be the address that is on link)
  198. /// b) our global address on the interface the message was received on
  199. /// (for directly connected clients)
  200. ///
  201. /// @param hint an address that belongs to a searched subnet
  202. ///
  203. /// @return a subnet object
  204. Subnet4Ptr getSubnet4(const isc::asiolink::IOAddress& hint);
  205. /// @brief adds a subnet4
  206. void addSubnet4(const Subnet4Ptr& subnet);
  207. /// @brief removes all IPv4 subnets
  208. ///
  209. /// This method removes all existing IPv4 subnets. It is used during
  210. /// reconfiguration - old configuration is wiped and new definitions
  211. /// are used to recreate subnets.
  212. ///
  213. /// @todo Implement more intelligent approach. Note that comparison
  214. /// between old and new configuration is tricky. For example: is
  215. /// 192.0.2.0/23 and 192.0.2.0/24 the same subnet or is it something
  216. /// completely new?
  217. void deleteSubnets4();
  218. /// @brief returns path do the data directory
  219. ///
  220. /// This method returns a path to writeable directory that DHCP servers
  221. /// can store data in.
  222. /// @return data directory
  223. std::string getDataDir();
  224. /// @brief Sets list of hooks libraries
  225. ///
  226. /// Sets the list of hooks libraries. It is possible for there to be no
  227. /// hooks libraries, in which case this is indicated by an emopty vector.
  228. ///
  229. /// @param hooks_libraries Vector (possibly empty) of current hook libraries.
  230. void setHooksLibraries(const std::vector<std::string>& hooks_libraries);
  231. /// @brief Get and clear list of hooks libraries
  232. ///
  233. /// Gets the currently-set vector of hooks libraries. If there is no data
  234. /// (as opposed to an empty vector), there has been no change to the data
  235. /// since the last time this method was called. Should there be a necessity
  236. /// to know this information, it can be obtained from the HooksManager.
  237. ///
  238. /// @return Pointer to vector of strings listing the hooks libraries. This
  239. /// may be empty.
  240. boost::shared_ptr<std::vector<std::string> > getAndClearHooksLibraries();
  241. protected:
  242. /// @brief Protected constructor.
  243. ///
  244. /// This constructor is protected for 2 reasons. First, it forbids any
  245. /// instantiations of this class (CfgMgr is a singleton). Second, it
  246. /// allows derived class to instantiate it. That is useful for testing
  247. /// purposes.
  248. CfgMgr();
  249. /// @brief virtual destructor
  250. virtual ~CfgMgr();
  251. /// @brief a container for IPv6 subnets.
  252. ///
  253. /// That is a simple vector of pointers. It does not make much sense to
  254. /// optimize access time (e.g. using a map), because typical search
  255. /// pattern will use calling inRange() method on each subnet until
  256. /// a match is found.
  257. Subnet6Collection subnets6_;
  258. /// @brief a container for IPv4 subnets.
  259. ///
  260. /// That is a simple vector of pointers. It does not make much sense to
  261. /// optimize access time (e.g. using a map), because typical search
  262. /// pattern will use calling inRange() method on each subnet until
  263. /// a match is found.
  264. Subnet4Collection subnets4_;
  265. private:
  266. /// @brief A collection of option definitions.
  267. ///
  268. /// A collection of option definitions that can be accessed
  269. /// using option space name they belong to.
  270. OptionSpaceContainer<OptionDefContainer,
  271. OptionDefinitionPtr> option_def_spaces_;
  272. /// @brief Container for defined DHCPv6 option spaces.
  273. OptionSpaceCollection spaces6_;
  274. /// @brief Container for defined DHCPv4 option spaces.
  275. OptionSpaceCollection spaces4_;
  276. /// @brief directory where data files (e.g. server-id) are stored
  277. std::string datadir_;
  278. /// @brief Hooks libraries
  279. ///
  280. /// Unlike other configuration items that can be referenced all the time,
  281. /// this is a "one-shot" item. When the list of libraries is altered, the
  282. /// server needs to know about the change: once the libraries are loaded,
  283. /// the list is ignored. As configuration updates cause an update of the
  284. /// entire configuration and we wish to reload the libraries only if the
  285. /// list has changed, we could check the library list against that stored
  286. /// in the hooks manager. Unfortunately, since the libraries are reloaded
  287. /// when a new packet is received, this would mean a set of string
  288. /// comparisons on each packet. Instead, the data is flagged to indicate
  289. /// that it has changed.
  290. ///
  291. /// The parsing checks the set of hooks libraries in the configuration
  292. /// against the list stored in the HooksManager and only updates the data
  293. /// here if they have changed. Although a flag could be used to indicate
  294. /// a change, a more streamlined approach is used: the data in this object
  295. /// is cleared when it is read. As the data is a vector of strings and as
  296. /// an empty vector is valid data, we'll store the data as a shared pointer
  297. /// to a vector of strings. The pointer is zeroed when the data is read.
  298. boost::shared_ptr<std::vector<std::string> > hooks_libraries_;
  299. };
  300. } // namespace isc::dhcp
  301. } // namespace isc
  302. #endif // CFGMGR_H