subnet.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  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 SUBNET_H
  15. #define SUBNET_H
  16. #include <boost/shared_ptr.hpp>
  17. #include <boost/multi_index_container.hpp>
  18. #include <boost/multi_index/hashed_index.hpp>
  19. #include <boost/multi_index/sequenced_index.hpp>
  20. #include <boost/multi_index/mem_fun.hpp>
  21. #include <boost/multi_index/member.hpp>
  22. #include <asiolink/io_address.h>
  23. #include <dhcp/option.h>
  24. #include <dhcpsrv/key_from_key.h>
  25. #include <dhcpsrv/option_space_container.h>
  26. #include <dhcpsrv/pool.h>
  27. #include <dhcpsrv/triplet.h>
  28. namespace isc {
  29. namespace dhcp {
  30. /// @brief a base class for Subnet4 and Subnet6
  31. ///
  32. /// This class presents a common base for IPv4 and IPv6 subnets.
  33. /// In a physical sense, a subnet defines a single network link with all devices
  34. /// attached to it. In most cases all devices attached to a single link can
  35. /// share the same parameters. Therefore Subnet holds several values that are
  36. /// typically shared by all hosts: renew timer (T1), rebind timer (T2) and
  37. /// leased addresses lifetime (valid-lifetime). It also holds the set
  38. /// of DHCP option instances configured for the subnet. These options are
  39. /// included in DHCP messages being sent to clients which are connected
  40. /// to the particular subnet.
  41. ///
  42. /// @todo: Implement support for options here
  43. /// @brief Unique identifier for a subnet (both v4 and v6)
  44. typedef uint32_t SubnetID;
  45. class Subnet {
  46. public:
  47. /// @brief Option descriptor.
  48. ///
  49. /// Option descriptor holds information about option configured for
  50. /// a particular subnet. This information comprises the actual option
  51. /// instance and information whether this option is sent to DHCP client
  52. /// only on request (persistent = false) or always (persistent = true).
  53. struct OptionDescriptor {
  54. /// Option instance.
  55. OptionPtr option;
  56. /// Persistent flag, if true option is always sent to the client,
  57. /// if false option is sent to the client on request.
  58. bool persistent;
  59. /// @brief Constructor.
  60. ///
  61. /// @param opt option
  62. /// @param persist if true option is always sent.
  63. OptionDescriptor(const OptionPtr& opt, bool persist)
  64. : option(opt), persistent(persist) {};
  65. /// @brief Constructor
  66. ///
  67. /// @param persist if true option is always sent.
  68. OptionDescriptor(bool persist)
  69. : option(OptionPtr()), persistent(persist) {};
  70. };
  71. /// A pointer to option descriptor.
  72. typedef boost::shared_ptr<OptionDescriptor> OptionDescriptorPtr;
  73. /// @brief Multi index container for DHCP option descriptors.
  74. ///
  75. /// This container comprises three indexes to access option
  76. /// descriptors:
  77. /// - sequenced index: used to access elements in the order they
  78. /// have been added to the container,
  79. /// - option type index: used to search option descriptors containing
  80. /// options with specific option code (aka option type).
  81. /// - persistency flag index: used to search option descriptors with
  82. /// 'persistent' flag set to true.
  83. ///
  84. /// This container is the equivalent of three separate STL containers:
  85. /// - std::list of all options,
  86. /// - std::multimap of options with option code used as a multimap key,
  87. /// - std::multimap of option descriptors with option persistency flag
  88. /// used as a multimap key.
  89. /// The major advantage of this container over 3 separate STL containers
  90. /// is automatic synchronization of all indexes when elements are added,
  91. /// removed or modified in the container. With separate containers,
  92. /// the synchronization would have to be guaranteed by the Subnet class
  93. /// code. This would increase code complexity and presumably it would
  94. /// be much harder to add new search criteria (indexes).
  95. ///
  96. /// @todo we may want to search for options using option spaces when
  97. /// they are implemented.
  98. ///
  99. /// @see http://www.boost.org/doc/libs/1_51_0/libs/multi_index/doc/index.html
  100. typedef boost::multi_index_container<
  101. // Container comprises elements of OptionDescriptor type.
  102. OptionDescriptor,
  103. // Here we start enumerating various indexes.
  104. boost::multi_index::indexed_by<
  105. // Sequenced index allows accessing elements in the same way
  106. // as elements in std::list.
  107. // Sequenced is an index #0.
  108. boost::multi_index::sequenced<>,
  109. // Start definition of index #1.
  110. boost::multi_index::hashed_non_unique<
  111. // KeyFromKeyExtractor is the index key extractor that allows
  112. // accessing option type being held by the OptionPtr through
  113. // OptionDescriptor structure.
  114. KeyFromKeyExtractor<
  115. // Use option type as the index key. The type is held
  116. // in OptionPtr object so we have to call Option::getType
  117. // to retrieve this key for each element.
  118. boost::multi_index::const_mem_fun<
  119. Option,
  120. uint16_t,
  121. &Option::getType
  122. >,
  123. // Indicate that OptionPtr is a member of
  124. // OptionDescriptor structure.
  125. boost::multi_index::member<
  126. OptionDescriptor,
  127. OptionPtr,
  128. &OptionDescriptor::option
  129. >
  130. >
  131. >,
  132. // Start definition of index #2.
  133. // Use 'persistent' struct member as a key.
  134. boost::multi_index::hashed_non_unique<
  135. boost::multi_index::member<
  136. OptionDescriptor,
  137. bool,
  138. &OptionDescriptor::persistent
  139. >
  140. >
  141. >
  142. > OptionContainer;
  143. // Pointer to the OptionContainer object.
  144. typedef boost::shared_ptr<OptionContainer> OptionContainerPtr;
  145. /// Type of the index #1 - option type.
  146. typedef OptionContainer::nth_index<1>::type OptionContainerTypeIndex;
  147. /// Pair of iterators to represent the range of options having the
  148. /// same option type value. The first element in this pair represents
  149. /// the beginning of the range, the second element represents the end.
  150. typedef std::pair<OptionContainerTypeIndex::const_iterator,
  151. OptionContainerTypeIndex::const_iterator> OptionContainerTypeRange;
  152. /// Type of the index #2 - option persistency flag.
  153. typedef OptionContainer::nth_index<2>::type OptionContainerPersistIndex;
  154. /// @brief checks if specified address is in range
  155. bool inRange(const isc::asiolink::IOAddress& addr) const;
  156. /// @brief Add new option instance to the collection.
  157. ///
  158. /// @param option option instance.
  159. /// @param persistent if true, send an option regardless if client
  160. /// requested it or not.
  161. /// @param option_space name of the option space to add an option to.
  162. ///
  163. /// @throw isc::BadValue if invalid option provided.
  164. void addOption(const OptionPtr& option, bool persistent,
  165. const std::string& option_space);
  166. /// @brief Delete all options configured for the subnet.
  167. void delOptions();
  168. /// @brief checks if the specified address is in pools
  169. ///
  170. /// Note the difference between inSubnet() and inPool(). For a given
  171. /// subnet (e.g. 2001::/64) there may be one or more pools defined
  172. /// that may or may not cover entire subnet, e.g. pool 2001::1-2001::10).
  173. /// inPool() returning true implies inSubnet(), but the reverse implication
  174. /// is not always true. For the given example, 2001::1234:abcd would return
  175. /// true for inSubnet(), but false for inPool() check.
  176. ///
  177. /// @param addr this address will be checked if it belongs to any pools in
  178. /// that subnet
  179. /// @return true if the address is in any of the pools
  180. bool inPool(const isc::asiolink::IOAddress& addr) const;
  181. /// @brief return valid-lifetime for addresses in that prefix
  182. Triplet<uint32_t> getValid() const {
  183. return (valid_);
  184. }
  185. /// @brief returns T1 (renew timer), expressed in seconds
  186. Triplet<uint32_t> getT1() const {
  187. return (t1_);
  188. }
  189. /// @brief returns T2 (rebind timer), expressed in seconds
  190. Triplet<uint32_t> getT2() const {
  191. return (t2_);
  192. }
  193. /// @brief Return a collection of option descriptors.
  194. ///
  195. /// @param option_space name of the option space.
  196. ///
  197. /// @return pointer to collection of options configured for a subnet.
  198. OptionContainerPtr
  199. getOptionDescriptors(const std::string& option_space) const;
  200. /// @brief Return single option descriptor.
  201. ///
  202. /// @param option_space name of the option space.
  203. /// @param option_code code of the option to be returned.
  204. ///
  205. /// @return option descriptor found for the specified option space
  206. /// and option code.
  207. OptionDescriptor
  208. getOptionDescriptor(const std::string& option_space,
  209. const uint16_t option_code);
  210. /// @brief returns the last address that was tried from this pool
  211. ///
  212. /// This method returns the last address that was attempted to be allocated
  213. /// from this subnet. This is used as helper information for the next
  214. /// iteration of the allocation algorithm.
  215. ///
  216. /// @todo: Define map<SubnetID, IOAddress> somewhere in the
  217. /// AllocEngine::IterativeAllocator and keep the data there
  218. ///
  219. /// @param type lease type to be returned
  220. /// @return address/prefix that was last tried from this pool
  221. isc::asiolink::IOAddress getLastAllocated(Pool::PoolType type) const;
  222. /// @brief sets the last address that was tried from this pool
  223. ///
  224. /// This method sets the last address that was attempted to be allocated
  225. /// from this subnet. This is used as helper information for the next
  226. /// iteration of the allocation algorithm.
  227. ///
  228. /// @todo: Define map<SubnetID, IOAddress> somewhere in the
  229. /// AllocEngine::IterativeAllocator and keep the data there
  230. /// @param addr address/prefix to that was tried last
  231. /// @param type lease type to be set
  232. void setLastAllocated(Pool::PoolType type,
  233. const isc::asiolink::IOAddress& addr);
  234. /// @brief returns unique ID for that subnet
  235. /// @return unique ID for that subnet
  236. SubnetID getID() const { return (id_); }
  237. /// @brief returns subnet parameters (prefix and prefix length)
  238. ///
  239. /// @return (prefix, prefix length) pair
  240. std::pair<isc::asiolink::IOAddress, uint8_t> get() const {
  241. return (std::make_pair(prefix_, prefix_len_));
  242. }
  243. /// @brief Adds a new pool.
  244. /// @param pool pool to be added
  245. void addPool(const PoolPtr& pool);
  246. /// @brief Returns a pool that specified address belongs to
  247. ///
  248. /// If there is no pool that the address belongs to (hint is invalid), other
  249. /// pool of specified type will be returned.
  250. ///
  251. /// @param type pool type that the pool is looked for
  252. /// @param addr address that the returned pool should cover (optional)
  253. /// @return found pool (or NULL)
  254. PoolPtr getPool(Pool::PoolType type, isc::asiolink::IOAddress addr);
  255. /// @brief Returns a pool without any address specified
  256. ///
  257. /// @param type pool type that the pool is looked for
  258. /// @return returns one of the pools defined
  259. PoolPtr getAnyPool(Pool::PoolType type) {
  260. return (getPool(type, default_pool()));
  261. }
  262. /// @brief Returns the default address that will be used for pool selection
  263. ///
  264. /// It must be implemented in derived classes (should return :: for Subnet6
  265. /// and 0.0.0.0 for Subnet4)
  266. virtual isc::asiolink::IOAddress default_pool() const = 0;
  267. /// @brief returns all pools
  268. ///
  269. /// The reference is only valid as long as the object that returned it.
  270. ///
  271. /// @param type lease type to be set
  272. /// @return a collection of all pools
  273. const PoolCollection& getPools(Pool::PoolType type) const;
  274. /// @brief sets name of the network interface for directly attached networks
  275. ///
  276. /// @param iface_name name of the interface
  277. void setIface(const std::string& iface_name);
  278. /// @brief network interface name used to reach subnet (or "" for remote
  279. /// subnets)
  280. /// @return network interface name for directly attached subnets or ""
  281. std::string getIface() const;
  282. /// @brief returns textual representation of the subnet (e.g.
  283. /// "2001:db8::/64")
  284. ///
  285. /// @return textual representation
  286. virtual std::string toText() const;
  287. protected:
  288. /// @brief protected constructor
  289. //
  290. /// By making the constructor protected, we make sure that noone will
  291. /// ever instantiate that class. Pool4 and Pool6 should be used instead.
  292. Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
  293. const Triplet<uint32_t>& t1,
  294. const Triplet<uint32_t>& t2,
  295. const Triplet<uint32_t>& valid_lifetime);
  296. /// @brief virtual destructor
  297. ///
  298. /// A virtual destructor is needed because other classes
  299. /// derive from this class.
  300. virtual ~Subnet() { };
  301. /// @brief returns the next unique Subnet-ID
  302. ///
  303. /// @return the next unique Subnet-ID
  304. static SubnetID getNextID() {
  305. static SubnetID id = 0;
  306. return (id++);
  307. }
  308. /// @brief Checks if used pool type is valid
  309. ///
  310. /// Allowed type for Subnet4 is Pool::TYPE_V4.
  311. /// Allowed types for Subnet6 are Pool::TYPE_{IA,TA,PD}.
  312. /// This method is implemented in derived classes.
  313. ///
  314. /// @param type type to be checked
  315. /// @throw BadValue if invalid value is used
  316. virtual void checkType(Pool::PoolType type) const = 0;
  317. /// @brief Check if option is valid and can be added to a subnet.
  318. ///
  319. /// @param option option to be validated.
  320. virtual void validateOption(const OptionPtr& option) const = 0;
  321. /// @brief subnet-id
  322. ///
  323. /// Subnet-id is a unique value that can be used to find or identify
  324. /// a Subnet4 or Subnet6.
  325. SubnetID id_;
  326. /// @brief collection of IPv4 or non-temporary IPv6 pools in that subnet
  327. PoolCollection pools_;
  328. /// @brief collection of IPv6 temporary address pools in that subnet
  329. PoolCollection pools_ta_;
  330. /// @brief collection of IPv6 prefix pools in that subnet
  331. PoolCollection pools_pd_;
  332. /// @brief a prefix of the subnet
  333. isc::asiolink::IOAddress prefix_;
  334. /// @brief a prefix length of the subnet
  335. uint8_t prefix_len_;
  336. /// @brief a tripet (min/default/max) holding allowed renew timer values
  337. Triplet<uint32_t> t1_;
  338. /// @brief a tripet (min/default/max) holding allowed rebind timer values
  339. Triplet<uint32_t> t2_;
  340. /// @brief a tripet (min/default/max) holding allowed valid lifetime values
  341. Triplet<uint32_t> valid_;
  342. /// @brief last allocated address
  343. ///
  344. /// This is the last allocated address that was previously allocated from
  345. /// this particular subnet. Some allocation algorithms (e.g. iterative) use
  346. /// that value, others do not. It should be noted that although the value
  347. /// is usually correct, there are cases when it is invalid, e.g. after
  348. /// removing a pool, restarting or changing allocation algorithms. For
  349. /// that purpose it should be only considered a help that should not be
  350. /// fully trusted.
  351. isc::asiolink::IOAddress last_allocated_ia_;
  352. /// @brief last allocated temporary address
  353. ///
  354. /// See @ref last_allocated_ia_ for details.
  355. isc::asiolink::IOAddress last_allocated_ta_;
  356. /// @brief last allocated IPv6 prefix
  357. ///
  358. /// See @ref last_allocated_ia_ for details.
  359. isc::asiolink::IOAddress last_allocated_pd_;
  360. /// @brief Name of the network interface (if connected directly)
  361. std::string iface_;
  362. private:
  363. /// A collection of option spaces grouping option descriptors.
  364. typedef OptionSpaceContainer<OptionContainer,
  365. OptionDescriptor> OptionSpaceCollection;
  366. OptionSpaceCollection option_spaces_;
  367. };
  368. /// @brief A generic pointer to either Subnet4 or Subnet6 object
  369. typedef boost::shared_ptr<Subnet> SubnetPtr;
  370. /// @brief A configuration holder for IPv4 subnet.
  371. ///
  372. /// This class represents an IPv4 subnet.
  373. class Subnet4 : public Subnet {
  374. public:
  375. /// @brief Constructor with all parameters
  376. ///
  377. /// @param prefix Subnet4 prefix
  378. /// @param length prefix length
  379. /// @param t1 renewal timer (in seconds)
  380. /// @param t2 rebind timer (in seconds)
  381. /// @param valid_lifetime preferred lifetime of leases (in seconds)
  382. Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length,
  383. const Triplet<uint32_t>& t1,
  384. const Triplet<uint32_t>& t2,
  385. const Triplet<uint32_t>& valid_lifetime);
  386. protected:
  387. /// @brief Check if option is valid and can be added to a subnet.
  388. ///
  389. /// @param option option to be validated.
  390. ///
  391. /// @throw isc::BadValue if provided option is invalid.
  392. virtual void validateOption(const OptionPtr& option) const;
  393. /// @brief Returns default address for pool selection
  394. /// @return ANY IPv4 address
  395. virtual isc::asiolink::IOAddress default_pool() const {
  396. return (isc::asiolink::IOAddress("0.0.0.0"));
  397. }
  398. /// @brief Checks if used pool type is valid
  399. ///
  400. /// Allowed type for Subnet4 is Pool::TYPE_V4.
  401. ///
  402. /// @param type type to be checked
  403. /// @throw BadValue if invalid value is used
  404. virtual void checkType(Pool::PoolType type) const;
  405. };
  406. /// @brief A pointer to a Subnet4 object
  407. typedef boost::shared_ptr<Subnet4> Subnet4Ptr;
  408. /// @brief A collection of Subnet6 objects
  409. typedef std::vector<Subnet4Ptr> Subnet4Collection;
  410. /// @brief A configuration holder for IPv6 subnet.
  411. ///
  412. /// This class represents an IPv6 subnet.
  413. class Subnet6 : public Subnet {
  414. public:
  415. /// @brief Constructor with all parameters
  416. ///
  417. /// @param prefix Subnet6 prefix
  418. /// @param length prefix length
  419. /// @param t1 renewal timer (in seconds)
  420. /// @param t2 rebind timer (in seconds)
  421. /// @param preferred_lifetime preferred lifetime of leases (in seconds)
  422. /// @param valid_lifetime preferred lifetime of leases (in seconds)
  423. Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
  424. const Triplet<uint32_t>& t1,
  425. const Triplet<uint32_t>& t2,
  426. const Triplet<uint32_t>& preferred_lifetime,
  427. const Triplet<uint32_t>& valid_lifetime);
  428. /// @brief Returns preverred lifetime (in seconds)
  429. ///
  430. /// @return a triplet with preferred lifetime
  431. Triplet<uint32_t> getPreferred() const {
  432. return (preferred_);
  433. }
  434. /// @brief sets interface-id option (if defined)
  435. ///
  436. /// @param ifaceid pointer to interface-id option
  437. void setInterfaceId(const OptionPtr& ifaceid) {
  438. interface_id_ = ifaceid;
  439. }
  440. /// @brief returns interface-id value (if specified)
  441. /// @return interface-id option (if defined)
  442. OptionPtr getInterfaceId() const {
  443. return interface_id_;
  444. }
  445. protected:
  446. /// @brief Check if option is valid and can be added to a subnet.
  447. ///
  448. /// @param option option to be validated.
  449. ///
  450. /// @throw isc::BadValue if provided option is invalid.
  451. virtual void validateOption(const OptionPtr& option) const;
  452. /// @brief Returns default address for pool selection
  453. /// @return ANY IPv6 address
  454. virtual isc::asiolink::IOAddress default_pool() const {
  455. return (isc::asiolink::IOAddress("::"));
  456. }
  457. /// @brief Checks if used pool type is valid
  458. ///
  459. /// allowed types for Subnet6 are Pool::TYPE_{IA,TA,PD}.
  460. ///
  461. /// @param type type to be checked
  462. /// @throw BadValue if invalid value is used
  463. virtual void checkType(Pool::PoolType type) const;
  464. /// @brief specifies optional interface-id
  465. OptionPtr interface_id_;
  466. /// @brief a triplet with preferred lifetime (in seconds)
  467. Triplet<uint32_t> preferred_;
  468. };
  469. /// @brief A pointer to a Subnet6 object
  470. typedef boost::shared_ptr<Subnet6> Subnet6Ptr;
  471. /// @brief A collection of Subnet6 objects
  472. typedef std::vector<Subnet6Ptr> Subnet6Collection;
  473. } // end of isc::dhcp namespace
  474. } // end of isc namespace
  475. #endif // SUBNET_T