pgsql_host_data_source.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. // Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #ifndef PGSQL_HOST_DATA_SOURCE_H
  7. #define PGSQL_HOST_DATA_SOURCE_H
  8. #include <dhcpsrv/base_host_data_source.h>
  9. #include <dhcpsrv/pgsql_connection.h>
  10. #include <dhcpsrv/pgsql_exchange.h>
  11. namespace isc {
  12. namespace dhcp {
  13. /// Forward declaration to the implementation of the @ref PgSqlHostDataSource.
  14. class PgSqlHostDataSourceImpl;
  15. /// @brief PostgreSQL Host Data Source
  16. ///
  17. /// This class implements the @ref isc::dhcp::BaseHostDataSource interface to
  18. /// the PostgreSQL database. Use of this backend presupposes that a PostgreSQL
  19. /// database is available and that the Kea schema has been created within it.
  20. ///
  21. /// Reservations are uniquely identified by identifier type and value.
  22. /// The currently supported values are defined in @ref Host::IdentifierType
  23. /// as well as in host_identifier_table:
  24. ///
  25. /// - IDENT_HWADDR
  26. /// - IDENT_DUID
  27. /// - IDENT_CIRCUIT_ID
  28. /// - IDENT_CLIENT_ID
  29. ///
  30. class PgSqlHostDataSource: public BaseHostDataSource {
  31. public:
  32. /// @brief Constructor
  33. ///
  34. /// Uses the following keywords in the parameters passed to it to
  35. /// connect to the database:
  36. /// - name - Name of the database to which to connect (mandatory)
  37. /// - host - Host to which to connect (optional, defaults to "localhost")
  38. /// - user - Username under which to connect (optional)
  39. /// - password - Password for "user" on the database (optional)
  40. ///
  41. /// If the database is successfully opened, the version number in the
  42. /// schema_version table will be checked against hard-coded value in
  43. /// the implementation file.
  44. ///
  45. /// Finally, all the SQL commands are pre-compiled.
  46. ///
  47. /// @param parameters A data structure relating keywords and values
  48. /// concerned with the database.
  49. ///
  50. /// @throw isc::dhcp::NoDatabaseName Mandatory database name not given
  51. /// @throw isc::dhcp::DbOpenError Error opening the database
  52. /// @throw isc::dhcp::DbOperationError An operation on the open database has
  53. /// failed.
  54. PgSqlHostDataSource(const DatabaseConnection::ParameterMap& parameters);
  55. /// @brief Virtual destructor.
  56. /// Frees database resources and closes the database connection through
  57. /// the destruction of member impl_.
  58. virtual ~PgSqlHostDataSource();
  59. /// @brief Return all hosts for the specified HW address or DUID.
  60. ///
  61. /// This method returns all @c Host objects which represent reservations
  62. /// for the specified HW address or DUID. Note, that this method may
  63. /// return multiple reservations because a particular client may have
  64. /// reservations in multiple subnets and the same client may be identified
  65. /// by HW address or DUID. The server is unable to verify that the specific
  66. /// DUID and HW address belong to the same client, until the client sends
  67. /// a DHCP message.
  68. ///
  69. /// Specifying both hardware address and DUID is allowed for this method
  70. /// and results in returning all objects that are associated with hardware
  71. /// address OR duid. For example: if one host is associated with the
  72. /// specified hardware address and another host is associated with the
  73. /// specified DUID, two hosts will be returned.
  74. ///
  75. /// @param hwaddr HW address of the client or NULL if no HW address
  76. /// available.
  77. /// @param duid client id or NULL if not available, e.g. DHCPv4 client case.
  78. ///
  79. /// @return Collection of const @c Host objects.
  80. virtual ConstHostCollection
  81. getAll(const HWAddrPtr& hwaddr, const DuidPtr& duid = DuidPtr()) const;
  82. /// @brief Return all hosts connected to any subnet for which reservations
  83. /// have been made using a specified identifier.
  84. ///
  85. /// This method returns all @c Host objects which represent reservations
  86. /// for a specified identifier. This method may return multiple hosts
  87. /// because a particular client may have reservations in multiple subnets.
  88. ///
  89. /// @param identifier_type Identifier type.
  90. /// @param identifier_begin Pointer to a begining of a buffer containing
  91. /// an identifier.
  92. /// @param identifier_len Identifier length.
  93. ///
  94. /// @return Collection of const @c Host objects.
  95. virtual ConstHostCollection
  96. getAll(const Host::IdentifierType& identifier_type,
  97. const uint8_t* identifier_begin, const size_t identifier_len) const;
  98. /// @brief Returns a collection of hosts using the specified IPv4 address.
  99. ///
  100. /// This method may return multiple @c Host objects if they are connected
  101. /// to different subnets.
  102. ///
  103. /// @param address IPv4 address for which the @c Host object is searched.
  104. ///
  105. /// @return Collection of const @c Host objects.
  106. virtual ConstHostCollection
  107. getAll4(const asiolink::IOAddress& address) const;
  108. /// @brief Returns a host connected to the IPv4 subnet.
  109. ///
  110. /// Implementations of this method should guard against the case when
  111. /// mutliple instances of the @c Host are present, e.g. when two
  112. /// @c Host objects are found, one for the DUID, another one for the
  113. /// HW address. In such case, an implementation of this method
  114. /// should throw an MultipleRecords exception.
  115. ///
  116. /// @param subnet_id Subnet identifier.
  117. /// @param hwaddr HW address of the client or NULL if no HW address
  118. /// available.
  119. /// @param duid client id or NULL if not available.
  120. ///
  121. /// @return Const @c Host object using a specified HW address or DUID.
  122. virtual ConstHostPtr
  123. get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
  124. const DuidPtr& duid = DuidPtr()) const;
  125. /// @brief Returns a host connected to the IPv4 subnet.
  126. ///
  127. /// @param subnet_id Subnet identifier.
  128. /// @param identifier_type Identifier type.
  129. /// @param identifier_begin Pointer to a begining of a buffer containing
  130. /// an identifier.
  131. /// @param identifier_len Identifier length.
  132. ///
  133. /// @return Const @c Host object for which reservation has been made using
  134. /// the specified identifier.
  135. virtual ConstHostPtr
  136. get4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
  137. const uint8_t* identifier_begin, const size_t identifier_len) const;
  138. /// @brief Returns a host connected to the IPv4 subnet and having
  139. /// a reservation for a specified IPv4 address.
  140. ///
  141. /// One of the use cases for this method is to detect collisions between
  142. /// dynamically allocated addresses and reserved addresses. When the new
  143. /// address is assigned to a client, the allocation mechanism should check
  144. /// if this address is not reserved for some other host and do not allocate
  145. /// this address if reservation is present.
  146. ///
  147. /// @param subnet_id Subnet identifier.
  148. /// @param address reserved IPv4 address.
  149. ///
  150. /// @return Const @c Host object using a specified IPv4 address.
  151. /// @throw BadValue is given an IPv6 address
  152. virtual ConstHostPtr
  153. get4(const SubnetID& subnet_id, const asiolink::IOAddress& address) const;
  154. /// @brief Returns a host connected to the IPv6 subnet.
  155. ///
  156. /// Implementations of this method should guard against the case when
  157. /// mutliple instances of the @c Host are present, e.g. when two
  158. /// @c Host objects are found, one for the DUID, another one for the
  159. /// HW address. In such case, an implementation of this method
  160. /// should throw an MultipleRecords exception.
  161. ///
  162. /// @param subnet_id Subnet identifier.
  163. /// @param hwaddr HW address of the client or NULL if no HW address
  164. /// available.
  165. /// @param duid DUID or NULL if not available.
  166. ///
  167. /// @return Const @c Host object using a specified HW address or DUID.
  168. virtual ConstHostPtr
  169. get6(const SubnetID& subnet_id, const DuidPtr& duid,
  170. const HWAddrPtr& hwaddr = HWAddrPtr()) const;
  171. /// @brief Returns a host connected to the IPv6 subnet.
  172. ///
  173. /// @param subnet_id Subnet identifier.
  174. /// @param identifier_type Identifier type.
  175. /// @param identifier_begin Pointer to a begining of a buffer containing
  176. /// an identifier.
  177. /// @param identifier_len Identifier length.
  178. ///
  179. /// @return Const @c Host object for which reservation has been made using
  180. /// the specified identifier.
  181. virtual ConstHostPtr
  182. get6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
  183. const uint8_t* identifier_begin, const size_t identifier_len) const;
  184. /// @brief Returns a host using the specified IPv6 prefix.
  185. ///
  186. /// @param prefix IPv6 prefix for which the @c Host object is searched.
  187. /// @param prefix_len IPv6 prefix length.
  188. ///
  189. /// @return Const @c Host object using a specified HW address or DUID.
  190. virtual ConstHostPtr
  191. get6(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const;
  192. /// @brief Adds a new host to the collection.
  193. ///
  194. /// The method will insert the given host and all of its children (v4
  195. /// options, v6 options, and v6 reservations) into the database. It
  196. /// relies on constraints defined as part of the PostgreSQL schema to
  197. /// defend against duplicate entries and to ensure referential
  198. /// integrity.
  199. ///
  200. /// Violation of any of these constraints for a host will result in a
  201. /// DuplicateEntry exception:
  202. ///
  203. /// -# IPV4_ADDRESS and DHCP4_SUBNET_ID combination must be unique
  204. /// -# IPV6 ADDRESS and PREFIX_LEN combination must be unique
  205. /// -# DHCP ID, DHCP ID TYPE, and DHCP4_SUBNET_ID combination must be unique
  206. /// -# DHCP ID, DHCP ID TYPE, and DHCP6_SUBNET_ID combination must be unique
  207. ///
  208. /// In addition, violating the following referential contraints will
  209. /// a DbOperationError exception:
  210. ///
  211. /// -# DHCP ID TYPE must be defined in the HOST_IDENTIFIER_TYPE table
  212. /// -# For DHCP4 Options:
  213. /// -# HOST_ID must exist with HOSTS
  214. /// -# SCOPE_ID must be defined in DHCP_OPTION_SCOPE
  215. /// -# For DHCP6 Options:
  216. /// -# HOST_ID must exist with HOSTS
  217. /// -# SCOPE_ID must be defined in DHCP_OPTION_SCOPE
  218. /// -# For IPV6 Reservations:
  219. /// -# HOST_ID must exist with HOSTS
  220. /// -# Address and Prefix Length must be unique (DuplicateEntry)
  221. ///
  222. /// @param host Pointer to the new @c Host object being added.
  223. /// @throw DuplicateEntry or DbOperationError dependent on the constraint
  224. /// violation
  225. virtual void add(const HostPtr& host);
  226. /// @brief Return backend type
  227. ///
  228. /// Returns the type of database as the string "postgresql". This is
  229. /// same value as used for configuration purposes.
  230. ///
  231. /// @return Type of the backend.
  232. virtual std::string getType() const {
  233. return (std::string("postgresql"));
  234. }
  235. /// @brief Returns the name of the open database
  236. ///
  237. /// @return String containing the name of the database
  238. virtual std::string getName() const;
  239. /// @brief Returns description of the backend.
  240. ///
  241. /// This description may be multiline text that describes the backend.
  242. ///
  243. /// @return Description of the backend.
  244. virtual std::string getDescription() const;
  245. /// @brief Returns backend version.
  246. ///
  247. /// @return Version number stored in the database, as a pair of unsigned
  248. /// integers. "first" is the major version number, "second" the
  249. /// minor number.
  250. ///
  251. /// @throw isc::dhcp::DbOperationError An operation on the open database
  252. /// has failed.
  253. virtual std::pair<uint32_t, uint32_t> getVersion() const;
  254. /// @brief Commit Transactions
  255. ///
  256. /// Commits all pending database operations.
  257. virtual void commit();
  258. /// @brief Rollback Transactions
  259. ///
  260. /// Rolls back all pending database operations.
  261. virtual void rollback();
  262. private:
  263. /// @brief Pointer to the implementation of the @ref PgSqlHostDataSource.
  264. PgSqlHostDataSourceImpl* impl_;
  265. };
  266. }
  267. }
  268. #endif // PGSQL_HOST_DATA_SOURCE_H