d2_client.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. // Copyright (C) 2013-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 D2_CLIENT_H
  15. #define D2_CLIENT_H
  16. /// @file d2_client.h Defines the D2ClientConfig and D2ClientMgr classes.
  17. /// This file defines the classes Kea uses to act as a client of the b10-
  18. /// dhcp-ddns module (aka D2).
  19. ///
  20. #include <asiolink/io_address.h>
  21. #include <dhcp_ddns/ncr_io.h>
  22. #include <exceptions/exceptions.h>
  23. #include <boost/shared_ptr.hpp>
  24. #include <stdint.h>
  25. #include <string>
  26. #include <vector>
  27. namespace isc {
  28. namespace dhcp {
  29. /// An exception that is thrown if an error occurs while configuring
  30. /// the D2 DHCP DDNS client.
  31. class D2ClientError : public isc::Exception {
  32. public:
  33. /// @brief constructor
  34. ///
  35. /// @param file name of the file, where exception occurred
  36. /// @param line line of the file, where exception occurred
  37. /// @param what text description of the issue that caused exception
  38. D2ClientError(const char* file, size_t line, const char* what)
  39. : isc::Exception(file, line, what) {}
  40. };
  41. /// @brief Acts as a storage vault for D2 client configuration
  42. ///
  43. /// A simple container class for storing and retrieving the configuration
  44. /// parameters associated with DHCP-DDNS and acting as a client of D2.
  45. /// Instances of this class may be constructed through configuration parsing.
  46. ///
  47. class D2ClientConfig {
  48. public:
  49. /// @brief Constructor
  50. ///
  51. /// @param enable_updates Enables DHCP-DDNS updates
  52. /// @param server_ip IP address of the b10-dhcp-ddns server (IPv4 or IPv6)
  53. /// @param server_port IP port of the b10-dhcp-ddns server
  54. /// @param ncr_protocol Socket protocol to use with b10-dhcp-ddns
  55. /// Currently only UDP is supported.
  56. /// @param ncr_format Format of the b10-dhcp-ddns requests.
  57. /// Currently only JSON format is supported.
  58. /// @param always_include_fqdn Enables always including the FQDN option in
  59. /// DHCP responses.
  60. /// @param override_no_update Enables updates, even if clients request no
  61. /// updates.
  62. /// @param override_client_update Perform updates, even if client requested
  63. /// delegation.
  64. /// @param replace_client_name enables replacement of the domain-name
  65. /// supplied by the client with a generated name.
  66. /// @param generated_prefix Prefix to use when generating domain-names.
  67. /// @param qualifying_suffix Suffix to use to qualify partial domain-names.
  68. ///
  69. /// @throw D2ClientError if given an invalid protocol or format.
  70. D2ClientConfig(const bool enable_updates,
  71. const isc::asiolink::IOAddress& server_ip,
  72. const size_t server_port,
  73. const dhcp_ddns::NameChangeProtocol& ncr_protocol,
  74. const dhcp_ddns::NameChangeFormat& ncr_format,
  75. const bool always_include_fqdn,
  76. const bool override_no_update,
  77. const bool override_client_update,
  78. const bool replace_client_name,
  79. const std::string& generated_prefix,
  80. const std::string& qualifying_suffix);
  81. /// @brief Default constructor
  82. /// The default constructor creates an instance that has updates disabled.
  83. D2ClientConfig();
  84. /// @brief Destructor
  85. virtual ~D2ClientConfig();
  86. /// @brief Return whether or not DHCP-DDNS updating is enabled.
  87. bool getEnableUpdates() const {
  88. return(enable_updates_);
  89. }
  90. /// @brief Return the IP address of b10-dhcp-ddns (IPv4 or IPv6).
  91. const isc::asiolink::IOAddress& getServerIp() const {
  92. return(server_ip_);
  93. }
  94. /// @brief Return the IP port of b10-dhcp-ddns.
  95. size_t getServerPort() const {
  96. return(server_port_);
  97. }
  98. /// @brief Return the socket protocol to use with b10-dhcp-ddns.
  99. const dhcp_ddns::NameChangeProtocol& getNcrProtocol() const {
  100. return(ncr_protocol_);
  101. }
  102. /// @brief Return the b10-dhcp-ddns request format.
  103. const dhcp_ddns::NameChangeFormat& getNcrFormat() const {
  104. return(ncr_format_);
  105. }
  106. /// @brief Return whether or not FQDN is always included in DHCP responses.
  107. bool getAlwaysIncludeFqdn() const {
  108. return(always_include_fqdn_);
  109. }
  110. /// @brief Return if updates are done even if clients request no updates.
  111. bool getOverrideNoUpdate() const {
  112. return(override_no_update_);
  113. }
  114. /// @brief Return if updates are done even when clients request delegation.
  115. bool getOverrideClientUpdate() const {
  116. return(override_client_update_);
  117. }
  118. /// @brief Return whether or not client's domain-name is always replaced.
  119. bool getReplaceClientName() const {
  120. return(replace_client_name_);
  121. }
  122. /// @brief Return the prefix to use when generating domain-names.
  123. const std::string& getGeneratedPrefix() const {
  124. return(generated_prefix_);
  125. }
  126. /// @brief Return the suffix to use to qualify partial domain-names.
  127. const std::string& getQualifyingSuffix() const {
  128. return(qualifying_suffix_);
  129. }
  130. /// @brief Compares two D2ClientConfigs for equality
  131. bool operator == (const D2ClientConfig& other) const;
  132. /// @brief Compares two D2ClientConfigs for inequality
  133. bool operator != (const D2ClientConfig& other) const;
  134. /// @brief Generates a string representation of the class contents.
  135. std::string toText() const;
  136. protected:
  137. /// @brief Validates member values.
  138. ///
  139. /// Method is used by the constructor to validate member contents.
  140. ///
  141. /// @throw D2ClientError if given an invalid protocol or format.
  142. virtual void validateContents();
  143. private:
  144. /// @brief Indicates whether or not DHCP DDNS updating is enabled.
  145. bool enable_updates_;
  146. /// @brief IP address of the b10-dhcp-ddns server (IPv4 or IPv6).
  147. isc::asiolink::IOAddress server_ip_;
  148. /// @brief IP port of the b10-dhcp-ddns server.
  149. size_t server_port_;
  150. /// @brief The socket protocol to use with b10-dhcp-ddns.
  151. /// Currently only UDP is supported.
  152. dhcp_ddns::NameChangeProtocol ncr_protocol_;
  153. /// @brief Format of the b10-dhcp-ddns requests.
  154. /// Currently only JSON format is supported.
  155. dhcp_ddns::NameChangeFormat ncr_format_;
  156. /// @brief Should Kea always include the FQDN option in its response.
  157. bool always_include_fqdn_;
  158. /// @brief Should Kea perform updates, even if client requested no updates.
  159. /// Overrides the client request for no updates via the N flag.
  160. bool override_no_update_;
  161. /// @brief Should Kea perform updates, even if client requested delegation.
  162. bool override_client_update_;
  163. /// @brief Should Kea replace the domain-name supplied by the client.
  164. bool replace_client_name_;
  165. /// @brief Prefix Kea should use when generating domain-names.
  166. std::string generated_prefix_;
  167. /// @brief Suffix Kea should use when to qualify partial domain-names.
  168. std::string qualifying_suffix_;
  169. };
  170. std::ostream&
  171. operator<<(std::ostream& os, const D2ClientConfig& config);
  172. /// @brief Defines a pointer for D2ClientConfig instances.
  173. typedef boost::shared_ptr<D2ClientConfig> D2ClientConfigPtr;
  174. /// @brief Defines the type for D2 IO error handler.
  175. /// This callback is invoked when a send to b10-dhcp-ddns completes with a
  176. /// failed status. This provides the application layer (Kea) with a means to
  177. /// handle the error appropriately.
  178. ///
  179. /// @param result Result code of the send operation.
  180. /// @param ncr NameChangeRequest which failed to send.
  181. ///
  182. /// @note Handlers are expected not to throw. In the event a hanlder does
  183. /// throw invoking code logs the exception and then swallows it.
  184. typedef
  185. boost::function<void(const dhcp_ddns::NameChangeSender::Result result,
  186. dhcp_ddns::NameChangeRequestPtr& ncr)> D2ClientErrorHandler;
  187. /// @brief D2ClientMgr isolates Kea from the details of being a D2 client.
  188. ///
  189. /// Provides services for managing the current dhcp-ddns configuration and
  190. /// as well as communications with b10-dhcp-ddns. Regarding configuration it
  191. /// provides services to store, update, and access the current dhcp-ddns
  192. /// configuration. As for b10-dhcp-ddns communications, D2ClientMgr creates
  193. /// maintains a NameChangeSender appropriate to the current configuration and
  194. /// provides services to start, stop, and post NCRs to the sender. Additionally
  195. /// there are methods to examine the queue of requests currently waiting for
  196. /// transmission.
  197. ///
  198. /// The manager also provides the mechanics to integrate the ASIO-based IO
  199. /// used by the NCR IPC with the select-driven IO used by Kea. Senders expose
  200. /// a file descriptor, the "select-fd" that can monitored for read-readiness
  201. /// with the select() function (or variants). D2ClientMgr provides a method,
  202. /// runReadyIO(), that will process all ready events on a sender's
  203. /// IOservice. Track# 3315 is extending Kea's IfaceMgr to support the
  204. /// registration of multiple external sockets with callbacks that are then
  205. /// monitored with IO readiness via select().
  206. /// @todo D2ClientMgr will be modified to register the sender's select-fd and
  207. /// runReadyIO() with IfaceMgr when entering the send mode and will
  208. /// unregister when exiting send mode.
  209. ///
  210. /// To place the manager in send mode, the calling layer must supply an error
  211. /// handler and optionally an IOService instance. The error handler is invoked
  212. /// if a send completes with a failed status. This provides the calling layer
  213. /// an opportunity act upon the error.
  214. ///
  215. /// If the caller supplies an IOService, that service will be used to process
  216. /// the sender's IO. If not supplied, D2ClientMgr pass a private IOService
  217. /// into the sender. Using a private service isolates the sender's IO from
  218. /// any other services.
  219. ///
  220. class D2ClientMgr : public dhcp_ddns::NameChangeSender::RequestSendHandler {
  221. public:
  222. /// @brief Constructor
  223. ///
  224. /// Default constructor which constructs an instance which has DHCP-DDNS
  225. /// updates disabled.
  226. D2ClientMgr();
  227. /// @brief Destructor.
  228. ~D2ClientMgr();
  229. /// @brief Updates the DHCP-DDNS client configuration to the given value.
  230. ///
  231. /// @param new_config pointer to the new client configuration.
  232. /// @throw D2ClientError if passed an empty pointer.
  233. void setD2ClientConfig(D2ClientConfigPtr& new_config);
  234. /// @brief Convenience method for checking if DHCP-DDNS is enabled.
  235. ///
  236. /// @return True if the D2 configuration is enabled.
  237. bool ddnsEnabled();
  238. /// @brief Fetches the DHCP-DDNS configuration pointer.
  239. ///
  240. /// @return a reference to the current configuration pointer.
  241. const D2ClientConfigPtr& getD2ClientConfig() const;
  242. /// @brief Determines server flags based on configuration and client flags.
  243. ///
  244. /// This method uses input values for the client's FQDN S and N flags, in
  245. /// conjunction with the configuration parameters updates-enabled, override-
  246. /// no-updates, and override-client-updates to determine the values that
  247. /// should be used for the server's FQDN S and N flags.
  248. /// The logic in this method is based upon RFCs 4702 and 4704.
  249. ///
  250. /// @param client_s S Flag from the client's FQDN
  251. /// @param client_n N Flag from the client's FQDN
  252. /// @param server_s [out] S Flag for the server's FQDN
  253. /// @param server_n [out] N Flag for the server's FQDN
  254. ///
  255. /// @throw isc::BadValue if client_s and client_n are both 1 as this is
  256. /// an invalid combination per RFCs.
  257. void analyzeFqdn(const bool client_s, const bool client_n, bool& server_s,
  258. bool& server_n) const;
  259. /// @brief Builds a FQDN based on the configuration and given IP address.
  260. ///
  261. /// Using the current values for generated-prefix, qualifying-suffix and
  262. /// an IP address, this method constructs a fully qualified domain name.
  263. /// It supports both IPv4 and IPv6 addresses. The format of the name
  264. /// is as follows:
  265. ///
  266. /// <generated-prefix>-<ip address>.<qualifying-suffix>.
  267. ///
  268. /// <ip-address> is the result of IOAddress.toText() with the delimiters
  269. /// ('.' for IPv4 or ':' for IPv6) replaced with a hyphen, '-'.
  270. ///
  271. /// @param address IP address from which to derive the name (IPv4 or IPv6)
  272. ///
  273. /// @return std::string containing the generated name.
  274. std::string generateFqdn(const asiolink::IOAddress& address) const;
  275. /// @brief Adds a qualifying suffix to a given domain name
  276. ///
  277. /// Constructs a FQDN based on the configured qualifying-suffix and
  278. /// a partial domain name as follows:
  279. ///
  280. /// <partial_name>.<qualifying-suffix>.
  281. /// Note it will add a trailing '.' should qualifying-suffix not end with
  282. /// one.
  283. ///
  284. /// @param partial_name domain name to qualify
  285. ///
  286. /// @return std::string containing the qualified name.
  287. std::string qualifyName(const std::string& partial_name) const;
  288. /// @brief Set server FQDN flags based on configuration and a given FQDN
  289. ///
  290. /// Templated wrapper around the analyzeFqdn() allowing that method to
  291. /// be used for either IPv4 or IPv6 processing. This methods resets all
  292. /// of the flags in the response to zero and then sets the S,N, and O
  293. /// flags. Any other flags are the responsiblity of the invoking layer.
  294. ///
  295. /// @param fqdn FQDN option from which to read client (inbound) flags
  296. /// @param fqdn_resp FQDN option to update with the server (outbound) flags
  297. /// @tparam T FQDN Option class containing the FQDN data such as
  298. /// dhcp::Option4ClientFqdn or dhcp::Option6ClientFqdn
  299. template <class T>
  300. void adjustFqdnFlags(const T& fqdn, T& fqdn_resp);
  301. /// @brief Set server FQDN name based on configuration and a given FQDN
  302. ///
  303. /// Templated method which adjusts the domain name value and type in
  304. /// a server FQDN from a client (inbound) FQDN and the current
  305. /// configuration. The logic is as follows:
  306. ///
  307. /// If replace-client-name is true or the supplied name is empty, the
  308. /// server FQDN is set to ""/PARTIAL.
  309. ///
  310. /// If replace-client-name is false and the supplied name is a partial
  311. /// name the server FQDN is set to the supplied name qualified by
  312. /// appending the qualifying-suffix.
  313. ///
  314. /// If replace-client-name is false and the supplied name is a fully
  315. /// qualified name, set the server FQDN to the supplied name.
  316. ///
  317. /// @param fqdn FQDN option from which to get client (inbound) name
  318. /// @param fqdn_resp FQDN option to update with the adjusted name
  319. /// @tparam T FQDN Option class containing the FQDN data such as
  320. /// dhcp::Option4ClientFqdn or dhcp::Option6ClientFqdn
  321. template <class T>
  322. void adjustDomainName(const T& fqdn, T& fqdn_resp);
  323. /// @brief Enables sending NameChangeRequests to b10-dhcp-ddns
  324. ///
  325. /// Places the NameChangeSender into send mode. This instructs the
  326. /// sender to begin dequeuing and transmitting requests and to accept
  327. /// additional requests via the sendRequest() method.
  328. ///
  329. /// @param error_handler application level error handler to cope with
  330. /// sends that complete with a failed status. A valid function must be
  331. /// supplied as the manager cannot know how an application should deal
  332. /// with send failures.
  333. /// @param io_service IOService to be used for sender IO event processing
  334. /// @warning It is up to the invoking layer to ensure the io_service
  335. /// instance used outlives the D2ClientMgr send mode. When the send mode
  336. /// is exited, either expliclity by callind stopSender() or implicitly
  337. /// through D2CLientMgr destruction, any ASIO objects such as sockets or
  338. /// timers will be closed and released. If the io_service goes out of scope
  339. /// first this behavior could be unpredictable.
  340. ///
  341. /// @throw D2ClientError if sender instance is null. Underlying layer
  342. /// may throw NCRSenderExceptions exceptions.
  343. void startSender(D2ClientErrorHandler error_handler,
  344. isc::asiolink::IOService& io_service);
  345. /// @brief Enables sending NameChangeRequests to b10-dhcp-ddns
  346. ///
  347. /// Places the NameChangeSender into send mode. This instructs the
  348. /// sender to begin dequeuing and transmitting requests and to accept
  349. /// additional requests via the sendRequest() method. The manager
  350. /// will create a new, private instance of an IOService for the sender
  351. /// to use for IO event processing.
  352. ///
  353. /// @param error_handler application level error handler to cope with
  354. /// sends that complete with a failed status. A valid function must be
  355. /// supplied as the manager cannot know how an application should deal
  356. /// with send failures.
  357. ///
  358. /// @throw D2ClientError if sender instance is null. Underlying layer
  359. /// may throw NCRSenderExceptions exceptions.
  360. void startSender(D2ClientErrorHandler error_handler);
  361. /// @brief Returns true if the sender is in send mode, false otherwise.
  362. ///
  363. /// A true value indicates that the sender is present and in accepting
  364. /// messages for transmission, false otherwise.
  365. bool amSending() const;
  366. /// @brief Disables sending NameChangeRequests to b10-dhcp-ddns
  367. ///
  368. /// Takes the NameChangeSender out of send mode. The sender will stop
  369. /// transmitting requests, though any queued requests remain queued.
  370. /// Attempts to queue additional requests via sendRequest will fail.
  371. ///
  372. /// @throw D2ClientError if sender instance is null. Underlying layer
  373. /// may throw NCRSenderExceptions exceptions.
  374. void stopSender();
  375. /// @brief Send the given NameChangeRequests to b10-dhcp-ddns
  376. ///
  377. /// Passes NameChangeRequests to the NCR sender for transmission to
  378. /// b10-dhcp-ddns.
  379. ///
  380. /// @param ncr NameChangeRequest to send
  381. ///
  382. /// @throw D2ClientError if sender instance is null. Underlying layer
  383. /// may throw NCRSenderExceptions exceptions.
  384. void sendRequest(dhcp_ddns::NameChangeRequestPtr& ncr);
  385. /// @brief Returns the number of NCRs queued for transmission.
  386. size_t getQueueSize() const;
  387. /// @brief Returns the nth NCR queued for transmission.
  388. ///
  389. /// Note that the entry is not removed from the queue.
  390. /// @param index the index of the entry in the queue to fetch.
  391. /// Valid values are 0 (front of the queue) to (queue size - 1).
  392. /// @note This method is for test purposes only.
  393. ///
  394. /// @return Pointer reference to the queue entry.
  395. ///
  396. /// @throw D2ClientError if sender instance is null. Underlying layer
  397. /// may throw NCRSenderExceptions exceptions.
  398. const dhcp_ddns::NameChangeRequestPtr& peekAt(const size_t index) const;
  399. /// @brief Removes all NCRs queued for transmission.
  400. ///
  401. /// @throw D2ClientError if sender instance is null. Underlying layer
  402. /// may throw NCRSenderExceptions exceptions.
  403. void clearQueue();
  404. /// @brief Processes sender IO events
  405. ///
  406. /// Runs all handlers ready for execution on the sender's IO service.
  407. void runReadyIO();
  408. protected:
  409. /// @brief Function operator implementing the NCR sender callback.
  410. ///
  411. /// This method is invoked each time the NameChangeSender completes
  412. /// an asychronous send.
  413. ///
  414. /// @param result contains that send outcome status.
  415. /// @param ncr is a pointer to the NameChangeRequest that was
  416. /// delivered (or attempted).
  417. ///
  418. /// @throw This method MUST NOT throw.
  419. virtual void operator ()(const dhcp_ddns::NameChangeSender::Result result,
  420. dhcp_ddns::NameChangeRequestPtr& ncr);
  421. /// @brief Fetches the sender's select-fd.
  422. ///
  423. /// The select-fd may be used with select() or poll(). If the sender has
  424. /// IO waiting to process, the fd will evaluate as !EWOULDBLOCK.
  425. /// @note This is only exposed for testing purposes.
  426. ///
  427. /// @return The sender's select-fd
  428. ///
  429. /// @throw D2ClientError if the sender does not exist or is not in send
  430. /// mode.
  431. int getSelectFd();
  432. private:
  433. /// @brief Container class for DHCP-DDNS configuration parameters.
  434. D2ClientConfigPtr d2_client_config_;
  435. /// @brief Pointer to the current interface to DHCP-DDNS.
  436. dhcp_ddns::NameChangeSenderPtr name_change_sender_;
  437. /// @brief Private IOService to use if calling layer doesn't wish to
  438. /// supply one.
  439. boost::shared_ptr<asiolink::IOService> private_io_service_;
  440. /// @brief Application supplied error handler invoked when a send
  441. /// completes with a failed status.
  442. D2ClientErrorHandler client_error_handler_;
  443. /// @brief Pointer to the IOService currently being used by the sender.
  444. /// @note We need to remember the io_service given to the sender however
  445. /// we may have received only a referenece to it from the calling layer.
  446. /// Use a raw pointer to store it. This value should never be exposed
  447. /// and is only valid while in send mode.
  448. asiolink::IOService* sender_io_service_;
  449. };
  450. template <class T>
  451. void
  452. D2ClientMgr::adjustFqdnFlags(const T& fqdn, T& fqdn_resp) {
  453. bool server_s = false;
  454. bool server_n = false;
  455. analyzeFqdn(fqdn.getFlag(T::FLAG_S), fqdn.getFlag(T::FLAG_N),
  456. server_s, server_n);
  457. // Reset the flags to zero to avoid triggering N and S both 1 check.
  458. fqdn_resp.resetFlags();
  459. // Set S and N flags.
  460. fqdn_resp.setFlag(T::FLAG_S, server_s);
  461. fqdn_resp.setFlag(T::FLAG_N, server_n);
  462. // Set O flag true if server S overrides client S.
  463. fqdn_resp.setFlag(T::FLAG_O, (fqdn.getFlag(T::FLAG_S) != server_s));
  464. }
  465. template <class T>
  466. void
  467. D2ClientMgr::adjustDomainName(const T& fqdn, T& fqdn_resp) {
  468. // If we're configured to replace it or the supplied name is blank
  469. // set the response name to blank.
  470. if (d2_client_config_->getReplaceClientName() ||
  471. fqdn.getDomainName().empty()) {
  472. fqdn_resp.setDomainName("", T::PARTIAL);
  473. } else {
  474. // If the supplied name is partial, qualify it by adding the suffix.
  475. if (fqdn.getDomainNameType() == T::PARTIAL) {
  476. fqdn_resp.setDomainName(qualifyName(fqdn.getDomainName()), T::FULL);
  477. }
  478. }
  479. }
  480. /// @brief Defines a pointer for D2ClientMgr instances.
  481. typedef boost::shared_ptr<D2ClientMgr> D2ClientMgrPtr;
  482. } // namespace isc
  483. } // namespace dhcp
  484. #endif