Kea  2.3.9
d2_client_mgr.h
Go to the documentation of this file.
1 // Copyright (C) 2014-2022 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 
7 #ifndef D2_CLIENT_MGR_H
8 #define D2_CLIENT_MGR_H
9 
14 #include <asiolink/io_address.h>
15 #include <dhcp_ddns/ncr_io.h>
16 #include <dhcpsrv/d2_client_cfg.h>
17 #include <dhcpsrv/srv_config.h>
18 #include <exceptions/exceptions.h>
19 
20 #include <boost/algorithm/string.hpp>
21 #include <boost/shared_ptr.hpp>
22 #include <boost/noncopyable.hpp>
23 
24 #include <stdint.h>
25 #include <string>
26 #include <vector>
27 #include <sstream>
28 
29 namespace isc {
30 namespace dhcp {
31 
42 typedef
43 std::function<void(const dhcp_ddns::NameChangeSender::Result result,
45 
80  boost::noncopyable {
81 public:
86  D2ClientMgr();
87 
89  ~D2ClientMgr();
90 
95  void setD2ClientConfig(D2ClientConfigPtr& new_config);
96 
100  bool ddnsEnabled();
101 
105  const D2ClientConfigPtr& getD2ClientConfig() const;
106 
155  void analyzeFqdn(const bool client_s, const bool client_n, bool& server_s,
156  bool& server_n, const DdnsParams& ddns_params) const;
157 
176  std::string generateFqdn(const asiolink::IOAddress& address,
177  const DdnsParams& ddns_params,
178  const bool trailing_dot = true) const;
179 
198  std::string qualifyName(const std::string& partial_name,
199  const DdnsParams& ddns_params,
200  const bool trailing_dot) const;
201 
214  template <class T>
215  void adjustFqdnFlags(const T& fqdn, T& fqdn_resp,
216  const DdnsParams& ddns_params);
217 
235  template <class T>
236  void getUpdateDirections(const T& fqdn_resp, bool& forward, bool& reverse);
237 
265  template <class T>
266  void adjustDomainName(const T& fqdn, T& fqdn_resp,
267  const DdnsParams& ddns_params);
268 
289  void startSender(D2ClientErrorHandler error_handler,
290  isc::asiolink::IOService& io_service);
291 
307  void startSender(D2ClientErrorHandler error_handler);
308 
313  bool amSending() const;
314 
323  void stopSender();
324 
337 
349  Result result,
351 
353  size_t getQueueSize() const;
354 
356  size_t getQueueMaxSize() const;
357 
369  const dhcp_ddns::NameChangeRequestPtr& peekAt(const size_t index) const;
370 
375  void clearQueue();
376 
383  void runReadyIO();
384 
394  void suspendUpdates();
395 
396 protected:
407  virtual void operator ()(const dhcp_ddns::NameChangeSender::Result result,
409 
420  int getSelectFd();
421 
429 
430 private:
432  D2ClientConfigPtr d2_client_config_;
433 
435  dhcp_ddns::NameChangeSenderPtr name_change_sender_;
436 
439  boost::shared_ptr<asiolink::IOService> private_io_service_;
440 
443  D2ClientErrorHandler client_error_handler_;
444 
446  int registered_select_fd_;
447 };
448 
449 template <class T>
450 void
451 D2ClientMgr::adjustFqdnFlags(const T& fqdn, T& fqdn_resp, const DdnsParams& ddns_params) {
452  bool server_s = false;
453  bool server_n = false;
454  analyzeFqdn(fqdn.getFlag(T::FLAG_S), fqdn.getFlag(T::FLAG_N),
455  server_s, server_n, ddns_params);
456 
457  // Reset the flags to zero to avoid triggering N and S both 1 check.
458  fqdn_resp.resetFlags();
459 
460  // Set S and N flags.
461  fqdn_resp.setFlag(T::FLAG_S, server_s);
462  fqdn_resp.setFlag(T::FLAG_N, server_n);
463 
464  // Set O flag true if server S overrides client S.
465  fqdn_resp.setFlag(T::FLAG_O, (fqdn.getFlag(T::FLAG_S) != server_s));
466 }
467 
468 template <class T>
469 void
471  bool& forward, bool& reverse) {
472  forward = fqdn_resp.getFlag(T::FLAG_S);
473  reverse = !(fqdn_resp.getFlag(T::FLAG_N));
474 }
475 
476 template <class T>
477 void
478 D2ClientMgr::adjustDomainName(const T& fqdn, T& fqdn_resp, const DdnsParams& ddns_params) {
479  // If we're configured to replace it or the supplied name is blank
480  // set the response name to blank.
483  fqdn.getDomainName().empty()) {
484  fqdn_resp.setDomainName("", T::PARTIAL);
485  } else {
486  // Sanitize the name the client sent us, if we're configured to do so.
487  std::string client_name = fqdn.getDomainName();
488 
490  if (sanitizer) {
491  // We need the raw text form, so we can replace escaped chars
492  dns::Name tmp(client_name);
493  std::string raw_name = tmp.toRawText();
494 
495  // We do not know if the sanitizer's regexp preserves dots, so
496  // we'll scrub it label by label. Yeah, lucky us.
497  // Using boost::split is simpler than using dns::Name::split() as
498  // that returns Names which have trailing dots etc.
499  std::vector<std::string> labels;
500  boost::algorithm::split(labels, raw_name, boost::is_any_of("."));
501  std::stringstream ss;
502  for (auto label = labels.begin(); label != labels.end(); ++label ) {
503  if (label != labels.begin()) {
504  ss << ".";
505  }
506 
507  ss << sanitizer->scrub(*label);
508  }
509 
510  client_name = ss.str();
511  }
512 
513  // If the supplied name is partial, qualify it by adding the suffix.
514  if (fqdn.getDomainNameType() == T::PARTIAL) {
515  fqdn_resp.setDomainName(qualifyName(client_name, ddns_params, true), T::FULL);
516  } else {
517  fqdn_resp.setDomainName(client_name, T::FULL);
518  }
519  }
520 }
521 
522 
524 typedef boost::shared_ptr<D2ClientMgr> D2ClientMgrPtr;
525 
526 
527 } // namespace isc
528 } // namespace dhcp
529 
530 #endif
ReplaceClientNameMode
Defines the client name replacement modes.
Definition: d2_client_cfg.h:76
D2ClientMgr isolates Kea from the details of being a D2 client.
Definition: d2_client_mgr.h:80
void invokeClientErrorHandler(const dhcp_ddns::NameChangeSender::Result result, dhcp_ddns::NameChangeRequestPtr &ncr)
Calls the client's error handler.
std::string generateFqdn(const asiolink::IOAddress &address, const DdnsParams &ddns_params, const bool trailing_dot=true) const
Builds a FQDN based on the configuration and given IP address.
void analyzeFqdn(const bool client_s, const bool client_n, bool &server_s, bool &server_n, const DdnsParams &ddns_params) const
Determines server flags based on configuration and client flags.
bool ddnsEnabled()
Convenience method for checking if DHCP-DDNS is enabled.
const D2ClientConfigPtr & getD2ClientConfig() const
Fetches the DHCP-DDNS configuration pointer.
void startSender(D2ClientErrorHandler error_handler, isc::asiolink::IOService &io_service)
Enables sending NameChangeRequests to kea-dhcp-ddns.
void getUpdateDirections(const T &fqdn_resp, bool &forward, bool &reverse)
Get directional update flags based on server FQDN flags.
void suspendUpdates()
Suspends sending requests.
int getRegisteredSelectFd()
Fetches the select-fd that is currently registered.
void adjustDomainName(const T &fqdn, T &fqdn_resp, const DdnsParams &ddns_params)
Set server FQDN name based on configuration and a given FQDN.
void sendRequest(dhcp_ddns::NameChangeRequestPtr &ncr)
Send the given NameChangeRequests to kea-dhcp-ddns.
size_t getQueueSize() const
Returns the number of NCRs queued for transmission.
void clearQueue()
Removes all NCRs queued for transmission.
void stopSender()
Disables sending NameChangeRequests to kea-dhcp-ddns.
void setD2ClientConfig(D2ClientConfigPtr &new_config)
Updates the DHCP-DDNS client configuration to the given value.
bool amSending() const
Returns true if the sender is in send mode, false otherwise.
int getSelectFd()
Fetches the sender's select-fd.
void runReadyIO()
Processes sender IO events.
void adjustFqdnFlags(const T &fqdn, T &fqdn_resp, const DdnsParams &ddns_params)
Set server FQDN flags based on configuration and a given FQDN.
~D2ClientMgr()
Destructor.
D2ClientMgr()
Constructor.
size_t getQueueMaxSize() const
Returns the maximum number of NCRs allowed in the queue.
virtual void operator()(const dhcp_ddns::NameChangeSender::Result result, dhcp_ddns::NameChangeRequestPtr &ncr)
Function operator implementing the NCR sender callback.
const dhcp_ddns::NameChangeRequestPtr & peekAt(const size_t index) const
Returns the nth NCR queued for transmission.
std::string qualifyName(const std::string &partial_name, const DdnsParams &ddns_params, const bool trailing_dot) const
Adds a qualifying suffix to a given domain name.
Convenience container for conveying DDNS behavioral parameters It is intended to be created per Packe...
Definition: srv_config.h:48
D2ClientConfig::ReplaceClientNameMode getReplaceClientNameMode() const
Returns how Kea should handle the domain-name supplied by the client.
Definition: srv_config.cc:953
isc::util::str::StringSanitizerPtr getHostnameSanitizer() const
Returns a regular expression string sanitizer.
Definition: srv_config.cc:998
Abstract class for defining application layer send callbacks.
Definition: ncr_io.h:488
Abstract interface for sending NameChangeRequests.
Definition: ncr_io.h:466
Result
Defines the outcome of an asynchronous NCR send.
Definition: ncr_io.h:476
The Name class encapsulates DNS names.
Definition: name.h:223
std::string toRawText(bool omit_final_dot=false) const
Convert the LabelSequence to a string without escape sequences.
Definition: name.cc:513
Defines the D2ClientConfig class.
boost::shared_ptr< NameChangeSender > NameChangeSenderPtr
Defines a smart pointer to an instance of a sender.
Definition: ncr_io.h:848
boost::shared_ptr< NameChangeRequest > NameChangeRequestPtr
Defines a pointer to a NameChangeRequest.
Definition: ncr_msg.h:212
boost::shared_ptr< D2ClientConfig > D2ClientConfigPtr
Defines a pointer for D2ClientConfig instances.
boost::shared_ptr< D2ClientMgr > D2ClientMgrPtr
Defines a pointer for D2ClientMgr instances.
std::function< void(const dhcp_ddns::NameChangeSender::Result result, dhcp_ddns::NameChangeRequestPtr &ncr)> D2ClientErrorHandler
Defines the type for D2 IO error handler.
Definition: d2_client_mgr.h:44
boost::shared_ptr< StringSanitizer > StringSanitizerPtr
Type representing the pointer to the StringSanitizer.
Definition: strutil.h:359
Defines the logger used by the top-level component of kea-lfc.
This file defines abstract classes for exchanging NameChangeRequests.