cfgmgr.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  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. #include <list>
  30. namespace isc {
  31. namespace dhcp {
  32. /// @brief Exception thrown when the same interface has been specified twice.
  33. ///
  34. /// In particular, this exception is thrown when adding interface to the set
  35. /// of interfaces on which server is supposed to listen.
  36. class DuplicateListeningIface : public Exception {
  37. public:
  38. DuplicateListeningIface(const char* file, size_t line, const char* what) :
  39. isc::Exception(file, line, what) { };
  40. };
  41. /// @brief Configuration Manager
  42. ///
  43. /// This singleton class holds the whole configuration for DHCPv4 and DHCPv6
  44. /// servers. It currently holds information about zero or more subnets6.
  45. /// Each subnet may contain zero or more pools. Pool4 and Pool6 is the most
  46. /// basic "chunk" of configuration. It contains a range of assignable
  47. /// addresses.
  48. ///
  49. /// Below is a sketch of configuration inheritance (not implemented yet).
  50. /// Let's investigate the following configuration:
  51. ///
  52. /// @code
  53. /// preferred-lifetime 500;
  54. /// valid-lifetime 1000;
  55. /// subnet6 2001:db8:1::/48 {
  56. /// pool6 2001::db8:1::1 - 2001::db8:1::ff;
  57. /// };
  58. /// subnet6 2001:db8:2::/48 {
  59. /// valid-lifetime 2000;
  60. /// pool6 2001::db8:2::1 - 2001::db8:2::ff;
  61. /// };
  62. /// @endcode
  63. ///
  64. /// Parameters defined in a global scope are applicable to everything until
  65. /// they are overwritten in a smaller scope, in this case subnet6.
  66. /// In the example above, the first subnet6 has preferred lifetime of 500s
  67. /// and a valid lifetime of 1000s. The second subnet has preferred lifetime
  68. /// of 500s, but valid lifetime of 2000s.
  69. ///
  70. /// Parameter inheritance is likely to be implemented in configuration handling
  71. /// routines, so there is no storage capability in a global scope for
  72. /// subnet-specific parameters.
  73. ///
  74. /// @todo: Implement Subnet4 support (ticket #2237)
  75. /// @todo: Implement option definition support
  76. /// @todo: Implement parameter inheritance
  77. class CfgMgr : public boost::noncopyable {
  78. public:
  79. /// @brief returns a single instance of Configuration Manager
  80. ///
  81. /// CfgMgr is a singleton and this method is the only way of
  82. /// accessing it.
  83. static CfgMgr& instance();
  84. /// @brief Add new option definition.
  85. ///
  86. /// @param def option definition to be added.
  87. /// @param option_space name of the option space to add definition to.
  88. ///
  89. /// @throw isc::dhcp::DuplicateOptionDefinition when the particular
  90. /// option definition already exists.
  91. /// @throw isc::dhcp::MalformedOptionDefinition when the pointer to
  92. /// an option definition is NULL.
  93. /// @throw isc::BadValue when the option space name is empty or
  94. /// when trying to override the standard option (in dhcp4 or dhcp6
  95. /// option space).
  96. void addOptionDef(const OptionDefinitionPtr& def,
  97. const std::string& option_space);
  98. /// @brief Return option definitions for particular option space.
  99. ///
  100. /// @param option_space option space.
  101. ///
  102. /// @return pointer to the collection of option definitions for
  103. /// the particular option space. The option collection is empty
  104. /// if no option exists for the option space specified.
  105. OptionDefContainerPtr
  106. getOptionDefs(const std::string& option_space) const;
  107. /// @brief Return option definition for a particular option space and code.
  108. ///
  109. /// @param option_space option space.
  110. /// @param option_code option code.
  111. ///
  112. /// @return an option definition or NULL pointer if option definition
  113. /// has not been found.
  114. OptionDefinitionPtr getOptionDef(const std::string& option_space,
  115. const uint16_t option_code) const;
  116. /// @brief Adds new DHCPv4 option space to the collection.
  117. ///
  118. /// @param space option space to be added.
  119. ///
  120. /// @throw isc::dhcp::InvalidOptionSpace invalid option space
  121. /// has been specified.
  122. void addOptionSpace4(const OptionSpacePtr& space);
  123. /// @brief Adds new DHCPv6 option space to the collection.
  124. ///
  125. /// @param space option space to be added.
  126. ///
  127. /// @throw isc::dhcp::InvalidOptionSpace invalid option space
  128. /// has been specified.
  129. void addOptionSpace6(const OptionSpacePtr& space);
  130. /// @brief Return option spaces for DHCPv4.
  131. ///
  132. /// @return A collection of option spaces.
  133. const OptionSpaceCollection& getOptionSpaces4() const {
  134. return (spaces4_);
  135. }
  136. /// @brief Return option spaces for DHCPv6.
  137. ///
  138. /// @return A collection of option spaces.
  139. const OptionSpaceCollection& getOptionSpaces6() const {
  140. return (spaces6_);
  141. }
  142. /// @brief get IPv6 subnet by address
  143. ///
  144. /// Finds a matching subnet, based on an address. This can be used
  145. /// in two cases: when trying to find an appropriate lease based on
  146. /// a) relay link address (that must be the address that is on link)
  147. /// b) our global address on the interface the message was received on
  148. /// (for directly connected clients)
  149. ///
  150. /// @param hint an address that belongs to a searched subnet
  151. ///
  152. /// @return a subnet object (or NULL if no suitable match was fount)
  153. Subnet6Ptr getSubnet6(const isc::asiolink::IOAddress& hint);
  154. /// @brief get IPv6 subnet by interface name
  155. ///
  156. /// Finds a matching local subnet, based on interface name. This
  157. /// is used for selecting subnets that were explicitly marked by the
  158. /// user as reachable over specified network interface.
  159. /// @param iface_name interface name
  160. /// @return a subnet object (or NULL if no suitable match was fount)
  161. Subnet6Ptr getSubnet6(const std::string& iface_name);
  162. /// @brief get IPv6 subnet by interface-id
  163. ///
  164. /// Another possibility to find a subnet is based on interface-id.
  165. ///
  166. /// @param interface_id content of interface-id option returned by a relay
  167. ///
  168. /// @return a subnet object
  169. Subnet6Ptr getSubnet6(OptionPtr interface_id);
  170. /// @brief adds an IPv6 subnet
  171. ///
  172. /// @param subnet new subnet to be added.
  173. void addSubnet6(const Subnet6Ptr& subnet);
  174. /// @brief Delete all option definitions.
  175. void deleteOptionDefs();
  176. /// @todo: Add subnet6 removal routines. Currently it is not possible
  177. /// to remove subnets. The only case where subnet6 removal would be
  178. /// needed is a dynamic server reconfiguration - a use case that is not
  179. /// planned to be supported any time soon.
  180. /// @brief removes all IPv6 subnets
  181. ///
  182. /// This method removes all existing IPv6 subnets. It is used during
  183. /// reconfiguration - old configuration is wiped and new definitions
  184. /// are used to recreate subnets.
  185. ///
  186. /// @todo Implement more intelligent approach. Note that comparison
  187. /// between old and new configuration is tricky. For example: is
  188. /// 2000::/64 and 2000::/48 the same subnet or is it something
  189. /// completely new?
  190. void deleteSubnets6();
  191. /// @brief returns const reference to all subnets6
  192. ///
  193. /// This is used in a hook (subnet4_select), where the hook is able
  194. /// to choose a different subnet. Server code has to offer a list
  195. /// of possible choices (i.e. all subnets).
  196. /// @return a pointer to const Subnet6 collection
  197. const Subnet4Collection* getSubnets4() {
  198. return (&subnets4_);
  199. }
  200. /// @brief returns const reference to all subnets6
  201. ///
  202. /// This is used in a hook (subnet6_select), where the hook is able
  203. /// to choose a different subnet. Server code has to offer a list
  204. /// of possible choices (i.e. all subnets).
  205. /// @return a pointer to const Subnet6 collection
  206. const Subnet6Collection* getSubnets6() {
  207. return (&subnets6_);
  208. }
  209. /// @brief get IPv4 subnet by address
  210. ///
  211. /// Finds a matching subnet, based on an address. This can be used
  212. /// in two cases: when trying to find an appropriate lease based on
  213. /// a) relay link address (that must be the address that is on link)
  214. /// b) our global address on the interface the message was received on
  215. /// (for directly connected clients)
  216. ///
  217. /// @param hint an address that belongs to a searched subnet
  218. ///
  219. /// @return a subnet object
  220. Subnet4Ptr getSubnet4(const isc::asiolink::IOAddress& hint);
  221. /// @brief adds a subnet4
  222. void addSubnet4(const Subnet4Ptr& subnet);
  223. /// @brief removes all IPv4 subnets
  224. ///
  225. /// This method removes all existing IPv4 subnets. It is used during
  226. /// reconfiguration - old configuration is wiped and new definitions
  227. /// are used to recreate subnets.
  228. ///
  229. /// @todo Implement more intelligent approach. Note that comparison
  230. /// between old and new configuration is tricky. For example: is
  231. /// 192.0.2.0/23 and 192.0.2.0/24 the same subnet or is it something
  232. /// completely new?
  233. void deleteSubnets4();
  234. /// @brief returns path do the data directory
  235. ///
  236. /// This method returns a path to writeable directory that DHCP servers
  237. /// can store data in.
  238. /// @return data directory
  239. std::string getDataDir();
  240. /// @brief Adds the name of the interface to the set of interfaces on which
  241. /// server should listen.
  242. ///
  243. /// @param iface A name of the interface being added to the listening set.
  244. void addActiveIface(const std::string& iface);
  245. /// @brief Sets the flag which indicates that server is supposed to listen
  246. /// on all available interfaces.
  247. ///
  248. /// This function does not close or open sockets. It simply marks that
  249. /// server should start to listen on all interfaces the next time sockets
  250. /// are reopened. Server should examine this flag when it gets reconfigured
  251. /// and configuration changes the interfaces that server should listen on.
  252. void activateAllIfaces();
  253. /// @brief Clear the collection of the interfaces that server should listen
  254. /// on.
  255. ///
  256. /// Apart from clearing the list of interfaces specified with
  257. /// @c CfgMgr::addListeningInterface, it also disables listening on all
  258. /// interfaces if it has been enabled using
  259. /// @c CfgMgr::activateAllInterfaces.
  260. /// Likewise @c CfgMgr::activateAllIfaces, this function does not close or
  261. /// open sockets. It marks all interfaces inactive for DHCP traffic.
  262. /// Server should examine this new setting when it attempts to
  263. /// reopen sockets (as a result of reconfiguration).
  264. void deleteActiveIfaces();
  265. /// @brief Check if specified interface should be used to listen to DHCP
  266. /// traffic.
  267. ///
  268. /// @param iface A name of the interface to be checked.
  269. ///
  270. /// @return true if the specified interface belongs to the set of the
  271. /// interfaces on which server is configured to listen.
  272. bool isActiveIface(const std::string& iface) const;
  273. /// @brief returns unicast a given interface should listen on (or NULL)
  274. ///
  275. /// This method will return an address for a specified interface, if the
  276. /// server is supposed to listen on unicast address. This address is
  277. /// intended to be used immediately. This pointer is valid only until
  278. /// the next configuration change.
  279. ///
  280. /// @return IOAddress pointer (or NULL if none)
  281. const isc::asiolink::IOAddress*
  282. getUnicast(const std::string& iface) const;
  283. /// @brief sets whether server should send back client-id in DHCPv4
  284. ///
  285. /// This is a compatibility flag. The default (true) is compliant with
  286. /// RFC6842. False is for backward compatibility.
  287. ///
  288. /// @param echo should the client-id be sent or not
  289. void echoClientId(bool echo) {
  290. echo_v4_client_id_ = echo;
  291. }
  292. /// @brief returns whether server should send back client-id in DHCPv4
  293. /// @param returns whether v4 client-id should be returned or not
  294. bool echoClientId() const {
  295. return (echo_v4_client_id_);
  296. }
  297. protected:
  298. /// @brief Protected constructor.
  299. ///
  300. /// This constructor is protected for 2 reasons. First, it forbids any
  301. /// instantiations of this class (CfgMgr is a singleton). Second, it
  302. /// allows derived class to instantiate it. That is useful for testing
  303. /// purposes.
  304. CfgMgr();
  305. /// @brief virtual destructor
  306. virtual ~CfgMgr();
  307. /// @brief a container for IPv6 subnets.
  308. ///
  309. /// That is a simple vector of pointers. It does not make much sense to
  310. /// optimize access time (e.g. using a map), because typical search
  311. /// pattern will use calling inRange() method on each subnet until
  312. /// a match is found.
  313. Subnet6Collection subnets6_;
  314. /// @brief a container for IPv4 subnets.
  315. ///
  316. /// That is a simple vector of pointers. It does not make much sense to
  317. /// optimize access time (e.g. using a map), because typical search
  318. /// pattern will use calling inRange() method on each subnet until
  319. /// a match is found.
  320. Subnet4Collection subnets4_;
  321. private:
  322. /// @brief Checks if the specified interface is listed as active.
  323. ///
  324. /// This function searches for the specified interface name on the list of
  325. /// active interfaces: @c CfgMgr::active_ifaces_. It does not take into
  326. /// account @c CfgMgr::all_ifaces_active_ flag. If this flag is set to true
  327. /// but the specified interface does not belong to
  328. /// @c CfgMgr::active_ifaces_, it will return false.
  329. ///
  330. /// @param iface interface name.
  331. ///
  332. /// @return true if specified interface belongs to
  333. /// @c CfgMgr::active_ifaces_.
  334. bool isIfaceListedActive(const std::string& iface) const;
  335. /// @brief A collection of option definitions.
  336. ///
  337. /// A collection of option definitions that can be accessed
  338. /// using option space name they belong to.
  339. OptionSpaceContainer<OptionDefContainer,
  340. OptionDefinitionPtr> option_def_spaces_;
  341. /// @brief Container for defined DHCPv6 option spaces.
  342. OptionSpaceCollection spaces6_;
  343. /// @brief Container for defined DHCPv4 option spaces.
  344. OptionSpaceCollection spaces4_;
  345. /// @brief directory where data files (e.g. server-id) are stored
  346. std::string datadir_;
  347. /// @name A collection of interface names on which server listens.
  348. //@{
  349. typedef std::list<std::string> ActiveIfacesCollection;
  350. std::list<std::string> active_ifaces_;
  351. //@}
  352. /// @name a collection of unicast addresses and the interfaces names the
  353. // server is supposed to listen on
  354. //@{
  355. typedef std::map<std::string, isc::asiolink::IOAddress> UnicastIfacesCollection;
  356. UnicastIfacesCollection unicast_addrs_;
  357. /// A flag which indicates that server should listen on all available
  358. /// interfaces.
  359. bool all_ifaces_active_;
  360. /// Indicates whether v4 server should send back client-id
  361. bool echo_v4_client_id_;
  362. };
  363. } // namespace isc::dhcp
  364. } // namespace isc
  365. #endif // CFGMGR_H