host.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. // Copyright (C) 2014-2015 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 HOST_H
  15. #define HOST_H
  16. #include <asiolink/io_address.h>
  17. #include <dhcp/classify.h>
  18. #include <dhcp/duid.h>
  19. #include <dhcp/hwaddr.h>
  20. #include <dhcpsrv/subnet_id.h>
  21. #include <boost/shared_ptr.hpp>
  22. #include <list>
  23. #include <map>
  24. #include <string>
  25. #include <utility>
  26. namespace isc {
  27. namespace dhcp {
  28. /// @brief IPv6 reservation for a host.
  29. ///
  30. /// This class represents a reservation for a host of a single IPv6
  31. /// address or prefix (in @c Host object).
  32. ///
  33. /// The class holds the address and prefix length, a value of 128
  34. /// for the latter implying that the reservation is for a single
  35. /// IPv6 address.
  36. class IPv6Resrv {
  37. public:
  38. /// @brief Type of the reservation.
  39. ///
  40. /// Currently supported types are NA and PD.
  41. enum Type {
  42. TYPE_NA,
  43. TYPE_PD
  44. };
  45. /// @brief Constructor.
  46. ///
  47. /// Creates a reservation from the IPv6 address and prefix length
  48. /// value. If the prefix length is not specified, the default value
  49. /// of 128 is used. This value indicates that the reservation is made
  50. /// for an IPv6 address.
  51. ///
  52. /// @param type Reservation type: NA or PD.
  53. /// @param prefix Address or prefix to be reserved.
  54. /// @param prefix_len Prefix length.
  55. ///
  56. /// @throw isc::BadValue if prefix is not IPv6 prefix, is a
  57. /// multicast address or the prefix length is greater than 128.
  58. IPv6Resrv(const Type& type,
  59. const asiolink::IOAddress& prefix,
  60. const uint8_t prefix_len = 128);
  61. /// @brief Returns prefix for the reservation.
  62. const asiolink::IOAddress& getPrefix() const {
  63. return (prefix_);
  64. }
  65. /// @brief Returns prefix length.
  66. uint8_t getPrefixLen() const {
  67. return (prefix_len_);
  68. }
  69. /// @brief Returns reservation type.
  70. ///
  71. /// The type of reservation is determined using a prefix length.
  72. ///
  73. /// @return NA for prefix length equal to 128, PD otherwise.
  74. Type getType() const {
  75. return (type_);
  76. }
  77. /// @brief Sets a new prefix and prefix length.
  78. ///
  79. /// @param type Reservation type: NA or PD.
  80. /// @param prefix New prefix.
  81. /// @param prefix_len New prefix length.
  82. ///
  83. /// @throw isc::BadValue if prefix is not IPv6 prefix, is a
  84. /// multicast address or the prefix length is greater than 128.
  85. void set(const Type& type, const asiolink::IOAddress& prefix,
  86. const uint8_t prefix_len);
  87. /// @brief Returns information about the reservation in the textual format.
  88. std::string toText() const;
  89. /// @brief Equality operator.
  90. ///
  91. /// @param other Reservation to compare to.
  92. bool operator==(const IPv6Resrv& other) const;
  93. /// @brief Inequality operator.
  94. ///
  95. /// @param other Reservation to compare to.
  96. bool operator!=(const IPv6Resrv& other) const;
  97. private:
  98. Type type_; ///< Reservation type.
  99. asiolink::IOAddress prefix_; ///< Prefix
  100. uint8_t prefix_len_; ///< Prefix length.
  101. };
  102. /// @brief Collection of IPv6 reservations for the host.
  103. typedef std::multimap<IPv6Resrv::Type, IPv6Resrv> IPv6ResrvCollection;
  104. typedef IPv6ResrvCollection::const_iterator IPv6ResrvIterator;
  105. typedef std::pair<IPv6Resrv::Type, IPv6Resrv> IPv6ResrvTuple;
  106. typedef std::pair<IPv6ResrvIterator, IPv6ResrvIterator> IPv6ResrvRange;
  107. /// @brief Represents a device with IPv4 and/or IPv6 reservations.
  108. ///
  109. /// This class represents a network device which can be identified
  110. /// by a unique property, such as MAC address on the interface or
  111. /// client identifier (DUID), and for which some resources are statically
  112. /// assigned:
  113. /// - IPv4 address which the device obtains when it contacts a DHCPv4 server
  114. /// - IPv6 address(es) which the device obtains when it contacts a DHCPv6
  115. /// server
  116. /// - IPv6 prefix(es) obtained when the device contacts the DHCPv6 server
  117. /// and requests allocation of prefixes using prefix delegation mechanism
  118. /// - hostname which is used for dynamic DNS updates for both DHCPv4 and
  119. /// DHCPv6 exchanges.
  120. /// - client classes which the client is associated with
  121. /// - DHCP options specifically configured for the device
  122. ///
  123. /// Note, that "host" in this context has a different meaning from
  124. /// host construed as device attached to a network with (possibly) multiple
  125. /// interfaces. For the MAC address based reservations, each interface on a
  126. /// network device maps to a single @c Host object as each @c Host object
  127. /// contains at most one MAC address. So, it is possible that a single
  128. /// device is associated with multiple distinct @c Host objects if the
  129. /// device has multiple interfaces. Under normal circumstances, a non-mobile
  130. /// dual stack device using one interface should be represented by a single
  131. /// @c Host object.
  132. ///
  133. /// A DHCPv6 DUID is common for all interfaces on a device. Therefore, for
  134. /// DUID based reservations a @c Host object may represent a network device with
  135. /// multiple interfaces. However, since @c Host objects are grouped by
  136. /// subnets to which device's interfaces are connected a single instance of
  137. /// @c Host object usually defines reservations for a single interface.
  138. ///
  139. /// The @c Host object combines reservations for both IPv4 and IPv6 resources
  140. /// to allow for correlation of the information about the dual stack devices
  141. /// using DHCPv4 and DHCPv6 respectively. For example: both the DHCPv4 and
  142. /// DHCPv6 servers may use the same database for storing host reservations, so
  143. /// the information about the DHCPv4 reservations are available for the
  144. /// DHCPv6 server and vice versa. Also, this approach allows for reserving
  145. /// common resources such as host name for DHCPv4 and DHCPv6 clients.
  146. ///
  147. /// @todo This class offers basic functionality for storing host information.
  148. /// It will need to be extended to allow for the following operations:
  149. /// - store DHCPv4 and DHCPv6 options for the host,
  150. /// - remove and replace IPv6 reservations
  151. /// - remove and replace client classes
  152. /// - disable IPv4 reservation without a need to set it to the 0.0.0.0 address
  153. /// Note that the last three operations are mainly required for managing
  154. /// host reservations which will be implemented later.
  155. class Host {
  156. public:
  157. /// @brief Type of the host identifier.
  158. ///
  159. /// Currently hardware address assigned to an interface and the
  160. /// DHCPv6 client's DUID are supported.
  161. enum IdentifierType {
  162. IDENT_HWADDR,
  163. IDENT_DUID
  164. };
  165. /// @brief Constructor.
  166. ///
  167. /// Creates a @c Host object using an identifier in a binary format. This
  168. /// is most useful in cases where the identifier is obtained from the
  169. /// database. The constructor will create an instance of the @c HWAddr
  170. /// or @c DUID object depending on the identifier type.
  171. ///
  172. /// @param identifier Pointer to the binary value holding an identifier.
  173. /// @param identifier_len Length of the identifier.
  174. /// @param identifier_type Type of the identifier (hardware address or
  175. /// DUID).
  176. /// @param ipv4_subnet_id Identifier of the IPv4 subnet to which the host
  177. /// is connected.
  178. /// @param ipv6_subnet_id Identifier of the IPv6 subnet to which the host
  179. /// is connected.
  180. /// @param ipv4_reservation An IPv4 address reserved for the client. If
  181. /// this address is set to 0, there is no reservation.
  182. /// @param hostname Hostname to be allocated to both DHCPv4 and DHCPv6
  183. /// clients. This is empty string if hostname is not allocated.
  184. /// @param dhcp4_client_classes A string holding DHCPv4 client class names
  185. /// separated by commas. The names get trimmed by this constructor.
  186. /// @param dhcp6_client_classes A string holding DHCPv6 client class names
  187. /// separated by commas. The names get trimmed by this constructor.
  188. ///
  189. /// @throw BadValue if the provided values are invalid. In particular,
  190. /// if the identifier is invalid.
  191. Host(const uint8_t* identifier, const size_t identifier_len,
  192. const IdentifierType& identifier_type,
  193. const SubnetID ipv4_subnet_id, const SubnetID ipv6_subnet_id,
  194. const asiolink::IOAddress& ipv4_reservation,
  195. const std::string& hostname = "",
  196. const std::string& dhcp4_client_classes = "",
  197. const std::string& dhcp6_client_classes = "");
  198. /// @brief Constructor.
  199. ///
  200. /// Creates @c Host object using an identifier in a textual format. This
  201. /// is useful in cases when the reservation is specified in the server
  202. /// configuration file, where:
  203. /// - MAC address is specified as: "01:02:03:04:05:06"
  204. /// - DUID is specified as: "010203040506abcd"
  205. ///
  206. /// @param identifier Identifier in the textual format. The expected formats
  207. /// for the hardware address and DUID have been shown above.
  208. /// @param identifier_name One of "hw-address" or "duid"
  209. /// @param ipv4_subnet_id Identifier of the IPv4 subnet to which the host
  210. /// is connected.
  211. /// @param ipv6_subnet_id Identifier of the IPv6 subnet to which the host
  212. /// is connected.
  213. /// @param ipv4_reservation An IPv4 address reserved for the client. If
  214. /// this address is set to 0, there is no reservation.
  215. /// @param hostname Hostname to be allocated to both DHCPv4 and DHCPv6
  216. /// clients. This is empty string if hostname is not allocated.
  217. /// @param dhcp4_client_classes A string holding DHCPv4 client class names
  218. /// separated by commas. The names get trimmed by this constructor.
  219. /// @param dhcp6_client_classes A string holding DHCPv6 client class names
  220. /// separated by commas. The names get trimmed by this constructor.
  221. ///
  222. /// @throw BadValue if the provided values are invalid. In particular,
  223. /// if the identifier is invalid.
  224. Host(const std::string& identifier, const std::string& identifier_name,
  225. const SubnetID ipv4_subnet_id, const SubnetID ipv6_subnet_id,
  226. const asiolink::IOAddress& ipv4_reservation,
  227. const std::string& hostname = "",
  228. const std::string& dhcp4_client_classes = "",
  229. const std::string& dhcp6_client_classes = "");
  230. /// @brief Replaces currently used identifier with a new identifier.
  231. ///
  232. /// This method initializes hardware address or DUID (@c hw_address_ or
  233. /// @c duid_ respectively). The other (not initialized member) is
  234. /// deallocated.
  235. ///
  236. /// This method is called by the @c Host constructor.
  237. ///
  238. /// @param identifier Pointer to the new identifier in the textual format.
  239. /// @param len Length of the identifier that the @c identifier points to.
  240. /// @param type Identifier type.
  241. ///
  242. /// @throw BadValue if the identifier is invalid.
  243. void setIdentifier(const uint8_t* identifier, const size_t len,
  244. const IdentifierType& type);
  245. /// @brief Replaces currently used identifier with a new identifier.
  246. ///
  247. /// This method initializes hardware address or DUID (@c hw_address_ or
  248. /// @c duid_ respectively). The other (not initialized member) is
  249. /// deallocated.
  250. ///
  251. /// This method is called by the @c Host constructor.
  252. ///
  253. /// @param identifier Pointer to the new identifier in the textual format.
  254. /// @param name One of "hw-address" or "duid".
  255. ///
  256. /// @throw BadValue if the identifier is invalid.
  257. void setIdentifier(const std::string& identifier, const std::string& name);
  258. /// @brief Returns hardware address for which the reservations are made.
  259. ///
  260. /// @return Pointer to the @c HWAddr structure or null if the reservation
  261. /// is not associated with a hardware address.
  262. HWAddrPtr getHWAddress() const {
  263. return (hw_address_);
  264. }
  265. /// @brief Returns DUID for which the reservations are made.
  266. ///
  267. /// @return Pointer to the @c DUID structure or null if the reservation
  268. /// is not associated with a DUID.
  269. DuidPtr getDuid() const {
  270. return (duid_);
  271. }
  272. const std::vector<uint8_t>& getIdentifier() const;
  273. IdentifierType getIdentifierType() const;
  274. /// @brief Sets new IPv4 subnet identifier.
  275. ///
  276. /// @param ipv4_subnet_id New subnet identifier.
  277. void setIPv4SubnetID(const SubnetID ipv4_subnet_id) {
  278. ipv4_subnet_id_ = ipv4_subnet_id;
  279. }
  280. /// @brief Sets new IPv6 subnet identifier.
  281. ///
  282. /// @param ipv6_subnet_id New subnet identifier.
  283. void setIPv6SubnetID(const SubnetID ipv6_subnet_id) {
  284. ipv6_subnet_id_ = ipv6_subnet_id;
  285. }
  286. /// @brief Returns subnet identifier for IPv4 reservation.
  287. SubnetID getIPv4SubnetID() const {
  288. return (ipv4_subnet_id_);
  289. }
  290. /// @brief Returns subnet identifier for IPv6 reservations.
  291. SubnetID getIPv6SubnetID() const {
  292. return (ipv6_subnet_id_);
  293. }
  294. /// @brief Sets new IPv4 reservation.
  295. ///
  296. /// The new reservation removes a previous reservation.
  297. ///
  298. /// @param address Address to be reserved for the client.
  299. ///
  300. /// @throw isc::BadValue if the provided address is not an IPv4 address.
  301. void setIPv4Reservation(const asiolink::IOAddress& address);
  302. /// @brief Returns reserved IPv4 address.
  303. ///
  304. /// @return IPv4 address or 0.0.0.0 if no IPv4 reservation specified.
  305. const asiolink::IOAddress& getIPv4Reservation() const {
  306. return (ipv4_reservation_);
  307. }
  308. /// @brief Adds new IPv6 reservation.
  309. ///
  310. /// @param reservation New IPv6 reservation to be appended.
  311. void addReservation(const IPv6Resrv& reservation);
  312. /// @brief Returns IPv6 reservations of a specified type.
  313. ///
  314. /// @param type Type of the reservations to be returned (NA or PD).
  315. ///
  316. /// @return A range of iterators pointing to the reservations of
  317. /// the specified type.
  318. IPv6ResrvRange getIPv6Reservations(const IPv6Resrv::Type& type) const;
  319. /// @brief Returns all IPv6 reservations.
  320. ///
  321. /// @return A range of iterators pointing to the reservations of
  322. /// the specified type.
  323. IPv6ResrvRange getIPv6Reservations() const;
  324. /// @brief Checks if there is at least one IPv6 reservation for this host.
  325. ///
  326. /// @return true if there is a reservation for the host, false otherwise.
  327. bool hasIPv6Reservation() const;
  328. /// @brief Checks if specified IPv6 reservation exists for the host.
  329. ///
  330. /// @param reservation A reservation to be checked for the host.
  331. ///
  332. /// @return true if the reservation already exists for the host, false
  333. /// otherwise.
  334. bool hasReservation(const IPv6Resrv& reservation) const;
  335. /// @brief Sets new hostname.
  336. ///
  337. /// @param hostname New hostname.
  338. void setHostname(const std::string& hostname) {
  339. hostname_ = hostname;
  340. }
  341. /// @brief Returns reserved hostname.
  342. const std::string& getHostname() const {
  343. return (hostname_);
  344. }
  345. /// @brief Adds new client class for DHCPv4.
  346. ///
  347. /// @param class_name Class name.
  348. void addClientClass4(const std::string& class_name) {
  349. addClientClassInternal(dhcp4_client_classes_, class_name);
  350. }
  351. /// @brief Returns classes which DHCPv4 client is associated with.
  352. const ClientClasses& getClientClasses4() const {
  353. return (dhcp4_client_classes_);
  354. }
  355. /// @brief Adds new client class for DHCPv6.
  356. ///
  357. /// @param class_name Class name.
  358. void addClientClass6(const std::string& class_name) {
  359. addClientClassInternal(dhcp6_client_classes_, class_name);
  360. }
  361. /// @brief Returns classes which DHCPv6 client is associated with.
  362. const ClientClasses& getClientClasses6() const {
  363. return (dhcp6_client_classes_);
  364. }
  365. private:
  366. /// @brief Adds new client class for DHCPv4 or DHCPv6.
  367. ///
  368. /// This method is called internally by the @c addClientClass4 and
  369. /// @c addClientClass6 functions. It adds the class of the specified name
  370. /// to the supplied class set. The class names are trimmed before they are
  371. /// added. Empty class names are ignored.
  372. ///
  373. /// @param [out] classes Set of classes to which the new class should be
  374. /// inserted.
  375. /// @param class_name Class name.
  376. void addClientClassInternal(ClientClasses& classes,
  377. const std::string& class_name);
  378. /// @brief Pointer to the hardware address associated with the reservations
  379. /// for the host.
  380. HWAddrPtr hw_address_;
  381. /// @brief Pointer to the DUID associated with the reservations for the
  382. /// host.
  383. DuidPtr duid_;
  384. /// @brief Subnet identifier for the DHCPv4 client.
  385. SubnetID ipv4_subnet_id_;
  386. /// @brief Subnet identifier for the DHCPv6 client.
  387. SubnetID ipv6_subnet_id_;
  388. /// @brief Reserved IPv4 address.
  389. asiolink::IOAddress ipv4_reservation_;
  390. /// @brief Collection of IPv6 reservations for the host.
  391. IPv6ResrvCollection ipv6_reservations_;
  392. /// @brief Name reserved for the host.
  393. std::string hostname_;
  394. /// @brief Collection of classes associated with a DHCPv4 client.
  395. ClientClasses dhcp4_client_classes_;
  396. /// @brief Collection of classes associated with a DHCPv6 client.
  397. ClientClasses dhcp6_client_classes_;
  398. };
  399. /// @brief Pointer to the @c Host object.
  400. typedef boost::shared_ptr<Host> HostPtr;
  401. /// @brief Const pointer to the @c Host object.
  402. typedef boost::shared_ptr<const Host> ConstHostPtr;
  403. /// @brief Collection of the const Host objects.
  404. typedef std::vector<ConstHostPtr> ConstHostCollection;
  405. /// @brief Collection of the @c Host objects.
  406. typedef std::vector<HostPtr> HostCollection;
  407. }
  408. }
  409. #endif // HOST_H