subnet.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. // Copyright (C) 2012-2014 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 <asiolink/io_address.h>
  17. #include <dhcp/option.h>
  18. #include <dhcp/classify.h>
  19. #include <dhcpsrv/cfg_option.h>
  20. #include <dhcpsrv/option_space_container.h>
  21. #include <dhcpsrv/pool.h>
  22. #include <dhcpsrv/triplet.h>
  23. #include <dhcpsrv/lease.h>
  24. #include <boost/shared_ptr.hpp>
  25. namespace isc {
  26. namespace dhcp {
  27. /// @brief a base class for Subnet4 and Subnet6
  28. ///
  29. /// This class presents a common base for IPv4 and IPv6 subnets.
  30. /// In a physical sense, a subnet defines a single network link with all devices
  31. /// attached to it. In most cases all devices attached to a single link can
  32. /// share the same parameters. Therefore Subnet holds several values that are
  33. /// typically shared by all hosts: renew timer (T1), rebind timer (T2) and
  34. /// leased addresses lifetime (valid-lifetime). It also holds the set
  35. /// of DHCP option instances configured for the subnet. These options are
  36. /// included in DHCP messages being sent to clients which are connected
  37. /// to the particular subnet.
  38. ///
  39. /// @todo: Implement support for options here
  40. /// @brief Unique identifier for a subnet (both v4 and v6)
  41. typedef uint32_t SubnetID;
  42. class Subnet {
  43. public:
  44. /// @brief Holds optional information about relay.
  45. ///
  46. /// In some cases it is beneficial to have additional information about
  47. /// a relay configured in the subnet. For now, the structure holds only
  48. /// IP address, but there may potentially be additional parameters added
  49. /// later, e.g. relay interface-id or relay-id.
  50. struct RelayInfo {
  51. /// @brief default and the only constructor
  52. ///
  53. /// @param addr an IP address of the relay (may be :: or 0.0.0.0)
  54. RelayInfo(const isc::asiolink::IOAddress& addr);
  55. /// @brief IP address of the relay
  56. isc::asiolink::IOAddress addr_;
  57. };
  58. /// Pointer to the RelayInfo structure
  59. typedef boost::shared_ptr<Subnet::RelayInfo> RelayInfoPtr;
  60. /// @brief checks if specified address is in range
  61. bool inRange(const isc::asiolink::IOAddress& addr) const;
  62. /// @brief checks if the specified address is in pools
  63. ///
  64. /// Note the difference between inSubnet() and inPool(). For a given
  65. /// subnet (e.g. 2001::/64) there may be one or more pools defined
  66. /// that may or may not cover entire subnet, e.g. pool 2001::1-2001::10).
  67. /// inPool() returning true implies inSubnet(), but the reverse implication
  68. /// is not always true. For the given example, 2001::1234:abcd would return
  69. /// true for inSubnet(), but false for inPool() check.
  70. ///
  71. /// @param type type of pools to iterate over
  72. /// @param addr this address will be checked if it belongs to any pools in
  73. /// that subnet
  74. /// @return true if the address is in any of the pools
  75. bool inPool(Lease::Type type, const isc::asiolink::IOAddress& addr) const;
  76. /// @brief Return valid-lifetime for addresses in that prefix
  77. Triplet<uint32_t> getValid() const {
  78. return (valid_);
  79. }
  80. /// @brief Returns T1 (renew timer), expressed in seconds
  81. Triplet<uint32_t> getT1() const {
  82. return (t1_);
  83. }
  84. /// @brief Returns T2 (rebind timer), expressed in seconds
  85. Triplet<uint32_t> getT2() const {
  86. return (t2_);
  87. }
  88. /// @brief Returns pointer to the option data configuration for this subnet.
  89. CfgOptionPtr getCfgOption() {
  90. return (cfg_option_);
  91. }
  92. /// @brief returns the last address that was tried from this pool
  93. ///
  94. /// This method returns the last address that was attempted to be allocated
  95. /// from this subnet. This is used as helper information for the next
  96. /// iteration of the allocation algorithm.
  97. ///
  98. /// @todo: Define map<SubnetID, IOAddress> somewhere in the
  99. /// AllocEngine::IterativeAllocator and keep the data there
  100. ///
  101. /// @param type lease type to be returned
  102. /// @return address/prefix that was last tried from this pool
  103. isc::asiolink::IOAddress getLastAllocated(Lease::Type type) const;
  104. /// @brief sets the last address that was tried from this pool
  105. ///
  106. /// This method sets the last address that was attempted to be allocated
  107. /// from this subnet. This is used as helper information for the next
  108. /// iteration of the allocation algorithm.
  109. ///
  110. /// @todo: Define map<SubnetID, IOAddress> somewhere in the
  111. /// AllocEngine::IterativeAllocator and keep the data there
  112. /// @param addr address/prefix to that was tried last
  113. /// @param type lease type to be set
  114. void setLastAllocated(Lease::Type type,
  115. const isc::asiolink::IOAddress& addr);
  116. /// @brief Returns unique ID for that subnet
  117. /// @return unique ID for that subnet
  118. SubnetID getID() const { return (id_); }
  119. /// @brief Returns subnet parameters (prefix and prefix length)
  120. ///
  121. /// @return (prefix, prefix length) pair
  122. std::pair<isc::asiolink::IOAddress, uint8_t> get() const {
  123. return (std::make_pair(prefix_, prefix_len_));
  124. }
  125. /// @brief Adds a new pool.
  126. /// @param pool pool to be added
  127. void addPool(const PoolPtr& pool);
  128. /// @brief Deletes all pools of specified type
  129. ///
  130. /// This method is used for testing purposes only
  131. /// @param type type of pools to be deleted
  132. void delPools(Lease::Type type);
  133. /// @brief Returns a pool that specified address belongs to
  134. ///
  135. /// If there is no pool that the address belongs to (hint is invalid), other
  136. /// pool of specified type will be returned.
  137. ///
  138. /// With anypool set to true, this is means give me a pool, preferably
  139. /// the one that addr belongs to. With anypool set to false, it means
  140. /// give me a pool that addr belongs to (or NULL if here is no such pool)
  141. ///
  142. /// @param type pool type that the pool is looked for
  143. /// @param addr address that the returned pool should cover (optional)
  144. /// @param anypool other pool may be returned as well, not only the one
  145. /// that addr belongs to
  146. /// @return found pool (or NULL)
  147. const PoolPtr getPool(Lease::Type type, const isc::asiolink::IOAddress& addr,
  148. bool anypool = true) const;
  149. /// @brief Returns a pool without any address specified
  150. ///
  151. /// @param type pool type that the pool is looked for
  152. /// @return returns one of the pools defined
  153. PoolPtr getAnyPool(Lease::Type type) {
  154. return (getPool(type, default_pool()));
  155. }
  156. /// @brief Returns the default address that will be used for pool selection
  157. ///
  158. /// It must be implemented in derived classes (should return :: for Subnet6
  159. /// and 0.0.0.0 for Subnet4)
  160. virtual isc::asiolink::IOAddress default_pool() const = 0;
  161. /// @brief Returns all pools (const variant)
  162. ///
  163. /// The reference is only valid as long as the object that returned it.
  164. ///
  165. /// @param type lease type to be set
  166. /// @return a collection of all pools
  167. const PoolCollection& getPools(Lease::Type type) const;
  168. /// @brief Sets name of the network interface for directly attached networks
  169. ///
  170. /// @param iface_name name of the interface
  171. void setIface(const std::string& iface_name);
  172. /// @brief Network interface name used to reach subnet (or "" for remote
  173. /// subnets)
  174. /// @return network interface name for directly attached subnets or ""
  175. std::string getIface() const;
  176. /// @brief Returns textual representation of the subnet (e.g.
  177. /// "2001:db8::/64")
  178. ///
  179. /// @return textual representation
  180. virtual std::string toText() const;
  181. /// @brief Resets subnet-id counter to its initial value (1)
  182. ///
  183. /// This should be called during reconfiguration, before any new
  184. /// subnet objects are created. It will ensure that the subnet_id will
  185. /// be consistent between reconfigures.
  186. static void resetSubnetID() {
  187. static_id_ = 1;
  188. }
  189. /// @brief Sets information about relay
  190. ///
  191. /// In some situations where there are shared subnets (i.e. two different
  192. /// subnets are available on the same physical link), there is only one
  193. /// relay that handles incoming requests from clients. In such a case,
  194. /// the usual subnet selection criteria based on relay belonging to the
  195. /// subnet being selected are no longer sufficient and we need to explicitly
  196. /// specify a relay. One notable example of such uncommon, but valid
  197. /// scenario is a cable network, where there is only one CMTS (one relay),
  198. /// but there are 2 distinct subnets behind it: one for cable modems
  199. /// and another one for CPEs and other user equipment behind modems.
  200. /// From manageability perspective, it is essential that modems get addresses
  201. /// from different subnet, so users won't tinker with their modems.
  202. ///
  203. /// Setting this parameter is not needed in most deployments.
  204. /// This structure holds IP address only for now, but it is expected to
  205. /// be extended in the future.
  206. ///
  207. /// @param relay structure that contains relay information
  208. void setRelayInfo(const isc::dhcp::Subnet::RelayInfo& relay);
  209. /// @brief Returns const reference to relay information
  210. ///
  211. /// @note The returned reference is only valid as long as the object
  212. /// returned it is valid.
  213. ///
  214. /// @return const reference to the relay information
  215. const isc::dhcp::Subnet::RelayInfo& getRelayInfo() {
  216. return (relay_);
  217. }
  218. /// @brief checks whether this subnet supports client that belongs to
  219. /// specified classes.
  220. ///
  221. /// This method checks whether a client that belongs to given classes can
  222. /// use this subnet. For example, if this class is reserved for client
  223. /// class "foo" and the client belongs to classes "foo", "bar" and "baz",
  224. /// it is supported. On the other hand, client belonging to classes
  225. /// "foobar" and "zyxxy" is not supported.
  226. ///
  227. /// @todo: Currently the logic is simple: client is supported if it belongs
  228. /// to any class mentioned in white_list_. We will eventually need a
  229. /// way to specify more fancy logic (e.g. to meet all classes, not just
  230. /// any)
  231. ///
  232. /// @param client_classes list of all classes the client belongs to
  233. /// @return true if client can be supported, false otherwise
  234. bool
  235. clientSupported(const isc::dhcp::ClientClasses& client_classes) const;
  236. /// @brief adds class class_name to the list of supported classes
  237. ///
  238. /// Also see explanation note in @ref white_list_.
  239. ///
  240. /// @param class_name client class to be supported by this subnet
  241. void
  242. allowClientClass(const isc::dhcp::ClientClass& class_name);
  243. protected:
  244. /// @brief Returns all pools (non-const variant)
  245. ///
  246. /// The reference is only valid as long as the object that returned it.
  247. ///
  248. /// @param type lease type to be set
  249. /// @return a collection of all pools
  250. PoolCollection& getPoolsWritable(Lease::Type type);
  251. /// @brief Protected constructor
  252. //
  253. /// By making the constructor protected, we make sure that no one will
  254. /// ever instantiate that class. Subnet4 and Subnet6 should be used instead.
  255. ///
  256. /// This constructor assigns a new subnet-id (see @ref generateNextID).
  257. /// This subnet-id has unique value that is strictly monotonously increasing
  258. /// for each subnet, until it is explicitly reset back to 1 during
  259. /// reconfiguration process.
  260. ///
  261. /// @param prefix subnet prefix
  262. /// @param len prefix length for the subnet
  263. /// @param t1 T1 (renewal-time) timer, expressed in seconds
  264. /// @param t2 T2 (rebind-time) timer, expressed in seconds
  265. /// @param valid_lifetime valid lifetime of leases in this subnet (in seconds)
  266. /// @param relay optional relay information (currently with address only)
  267. /// @param id arbitraty subnet id, value of 0 triggers autogeneration
  268. /// of subnet id
  269. Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
  270. const Triplet<uint32_t>& t1,
  271. const Triplet<uint32_t>& t2,
  272. const Triplet<uint32_t>& valid_lifetime,
  273. const isc::dhcp::Subnet::RelayInfo& relay,
  274. const SubnetID id);
  275. /// @brief virtual destructor
  276. ///
  277. /// A virtual destructor is needed because other classes
  278. /// derive from this class.
  279. virtual ~Subnet() { };
  280. /// @brief keeps the subnet-id value
  281. ///
  282. /// It is inreased every time a new Subnet object is created. It is reset
  283. /// (@ref resetSubnetID) every time reconfiguration
  284. /// occurs.
  285. ///
  286. /// Static value initialized in subnet.cc.
  287. static SubnetID static_id_;
  288. /// @brief returns the next unique Subnet-ID
  289. ///
  290. /// This method generates and returns the next unique subnet-id.
  291. /// It is a strictly monotonously increasing value (1,2,3,...) for
  292. /// each new Subnet object created. It can be explicitly reset
  293. /// back to 1 during reconfiguration (@ref resetSubnetID).
  294. ///
  295. /// @return the next unique Subnet-ID
  296. static SubnetID generateNextID() {
  297. return (static_id_++);
  298. }
  299. /// @brief Checks if used pool type is valid
  300. ///
  301. /// Allowed type for Subnet4 is Pool::TYPE_V4.
  302. /// Allowed types for Subnet6 are Pool::TYPE_{IA,TA,PD}.
  303. /// This method is implemented in derived classes.
  304. ///
  305. /// @param type type to be checked
  306. /// @throw BadValue if invalid value is used
  307. virtual void checkType(Lease::Type type) const = 0;
  308. /// @brief subnet-id
  309. ///
  310. /// Subnet-id is a unique value that can be used to find or identify
  311. /// a Subnet4 or Subnet6.
  312. SubnetID id_;
  313. /// @brief collection of IPv4 or non-temporary IPv6 pools in that subnet
  314. PoolCollection pools_;
  315. /// @brief collection of IPv6 temporary address pools in that subnet
  316. PoolCollection pools_ta_;
  317. /// @brief collection of IPv6 prefix pools in that subnet
  318. PoolCollection pools_pd_;
  319. /// @brief a prefix of the subnet
  320. isc::asiolink::IOAddress prefix_;
  321. /// @brief a prefix length of the subnet
  322. uint8_t prefix_len_;
  323. /// @brief a tripet (min/default/max) holding allowed renew timer values
  324. Triplet<uint32_t> t1_;
  325. /// @brief a tripet (min/default/max) holding allowed rebind timer values
  326. Triplet<uint32_t> t2_;
  327. /// @brief a tripet (min/default/max) holding allowed valid lifetime values
  328. Triplet<uint32_t> valid_;
  329. /// @brief last allocated address
  330. ///
  331. /// This is the last allocated address that was previously allocated from
  332. /// this particular subnet. Some allocation algorithms (e.g. iterative) use
  333. /// that value, others do not. It should be noted that although the value
  334. /// is usually correct, there are cases when it is invalid, e.g. after
  335. /// removing a pool, restarting or changing allocation algorithms. For
  336. /// that purpose it should be only considered a help that should not be
  337. /// fully trusted.
  338. isc::asiolink::IOAddress last_allocated_ia_;
  339. /// @brief last allocated temporary address
  340. ///
  341. /// See @ref last_allocated_ia_ for details.
  342. isc::asiolink::IOAddress last_allocated_ta_;
  343. /// @brief last allocated IPv6 prefix
  344. ///
  345. /// See @ref last_allocated_ia_ for details.
  346. isc::asiolink::IOAddress last_allocated_pd_;
  347. /// @brief Name of the network interface (if connected directly)
  348. std::string iface_;
  349. /// @brief Relay information
  350. ///
  351. /// See @ref RelayInfo for detailed description. This structure is public,
  352. /// so its fields are easily accessible. Making it protected would bring in
  353. /// the issue of returning references that may become stale after its parent
  354. /// subnet object disappears.
  355. RelayInfo relay_;
  356. /// @brief optional definition of a client class
  357. ///
  358. /// If defined, only clients belonging to that class will be allowed to use
  359. /// this particular subnet. The default value for this is an empty list,
  360. /// which means that any client is allowed, regardless of its class.
  361. ///
  362. /// @todo This is just a single list of allowed classes. We'll also need
  363. /// to add a black-list (only classes on the list are rejected, the rest
  364. /// are allowed). Implementing this will require more fancy parser logic,
  365. /// so it may be a while until we support this.
  366. ClientClasses white_list_;
  367. private:
  368. /// @brief Pointer to the option data configuration for this subnet.
  369. CfgOptionPtr cfg_option_;
  370. };
  371. /// @brief A generic pointer to either Subnet4 or Subnet6 object
  372. typedef boost::shared_ptr<Subnet> SubnetPtr;
  373. /// @brief A configuration holder for IPv4 subnet.
  374. ///
  375. /// This class represents an IPv4 subnet.
  376. class Subnet4 : public Subnet {
  377. public:
  378. /// @brief Constructor with all parameters
  379. ///
  380. /// This constructor calls Subnet::Subnet, where subnet-id is generated.
  381. ///
  382. /// @param prefix Subnet4 prefix
  383. /// @param length prefix length
  384. /// @param t1 renewal timer (in seconds)
  385. /// @param t2 rebind timer (in seconds)
  386. /// @param valid_lifetime preferred lifetime of leases (in seconds)
  387. /// @param id arbitraty subnet id, default value of 0 triggers
  388. /// autogeneration of subnet id
  389. Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length,
  390. const Triplet<uint32_t>& t1,
  391. const Triplet<uint32_t>& t2,
  392. const Triplet<uint32_t>& valid_lifetime,
  393. const SubnetID id = 0);
  394. /// @brief Sets siaddr for the Subnet4
  395. ///
  396. /// Will be used for siaddr field (the next server) that typically is used
  397. /// as TFTP server. If not specified, the default value of 0.0.0.0 is
  398. /// used.
  399. void setSiaddr(const isc::asiolink::IOAddress& siaddr);
  400. /// @brief Returns siaddr for this subnet
  401. ///
  402. /// @return siaddr value
  403. isc::asiolink::IOAddress getSiaddr() const;
  404. protected:
  405. /// @brief Returns default address for pool selection
  406. /// @return ANY IPv4 address
  407. virtual isc::asiolink::IOAddress default_pool() const {
  408. return (isc::asiolink::IOAddress("0.0.0.0"));
  409. }
  410. /// @brief Checks if used pool type is valid
  411. ///
  412. /// Allowed type for Subnet4 is Pool::TYPE_V4.
  413. ///
  414. /// @param type type to be checked
  415. /// @throw BadValue if invalid value is used
  416. virtual void checkType(Lease::Type type) const;
  417. /// @brief siaddr value for this subnet
  418. isc::asiolink::IOAddress siaddr_;
  419. };
  420. /// @brief A pointer to a Subnet4 object
  421. typedef boost::shared_ptr<Subnet4> Subnet4Ptr;
  422. /// @brief A collection of Subnet6 objects
  423. typedef std::vector<Subnet4Ptr> Subnet4Collection;
  424. /// @brief A configuration holder for IPv6 subnet.
  425. ///
  426. /// This class represents an IPv6 subnet.
  427. class Subnet6 : public Subnet {
  428. public:
  429. /// @brief Constructor with all parameters
  430. ///
  431. /// This constructor calls Subnet::Subnet, where subnet-id is generated.
  432. ///
  433. /// @param prefix Subnet6 prefix
  434. /// @param length prefix length
  435. /// @param t1 renewal timer (in seconds)
  436. /// @param t2 rebind timer (in seconds)
  437. /// @param preferred_lifetime preferred lifetime of leases (in seconds)
  438. /// @param valid_lifetime preferred lifetime of leases (in seconds)
  439. /// @param id arbitraty subnet id, default value of 0 triggers
  440. /// autogeneration of subnet id
  441. Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
  442. const Triplet<uint32_t>& t1,
  443. const Triplet<uint32_t>& t2,
  444. const Triplet<uint32_t>& preferred_lifetime,
  445. const Triplet<uint32_t>& valid_lifetime,
  446. const SubnetID id = 0);
  447. /// @brief Returns preverred lifetime (in seconds)
  448. ///
  449. /// @return a triplet with preferred lifetime
  450. Triplet<uint32_t> getPreferred() const {
  451. return (preferred_);
  452. }
  453. /// @brief sets interface-id option (if defined)
  454. ///
  455. /// @param ifaceid pointer to interface-id option
  456. void setInterfaceId(const OptionPtr& ifaceid) {
  457. interface_id_ = ifaceid;
  458. }
  459. /// @brief returns interface-id value (if specified)
  460. /// @return interface-id option (if defined)
  461. OptionPtr getInterfaceId() const {
  462. return interface_id_;
  463. }
  464. protected:
  465. /// @brief Returns default address for pool selection
  466. /// @return ANY IPv6 address
  467. virtual isc::asiolink::IOAddress default_pool() const {
  468. return (isc::asiolink::IOAddress("::"));
  469. }
  470. /// @brief Checks if used pool type is valid
  471. ///
  472. /// allowed types for Subnet6 are Pool::TYPE_{IA,TA,PD}.
  473. ///
  474. /// @param type type to be checked
  475. /// @throw BadValue if invalid value is used
  476. virtual void checkType(Lease::Type type) const;
  477. /// @brief specifies optional interface-id
  478. OptionPtr interface_id_;
  479. /// @brief a triplet with preferred lifetime (in seconds)
  480. Triplet<uint32_t> preferred_;
  481. };
  482. /// @brief A pointer to a Subnet6 object
  483. typedef boost::shared_ptr<Subnet6> Subnet6Ptr;
  484. /// @brief A collection of Subnet6 objects
  485. typedef std::vector<Subnet6Ptr> Subnet6Collection;
  486. } // end of isc::dhcp namespace
  487. } // end of isc namespace
  488. #endif // SUBNET_H