Kea  1.9.9-git
d2_client_mgr.h
Go to the documentation of this file.
1 // Copyright (C) 2014-2021 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 
195  std::string qualifyName(const std::string& partial_name,
196  const DdnsParams& ddns_params,
197  const bool trailing_dot) const;
198 
211  template <class T>
212  void adjustFqdnFlags(const T& fqdn, T& fqdn_resp,
213  const DdnsParams& ddns_params);
214 
232  template <class T>
233  void getUpdateDirections(const T& fqdn_resp, bool& forward, bool& reverse);
234 
262  template <class T>
263  void adjustDomainName(const T& fqdn, T& fqdn_resp,
264  const DdnsParams& ddns_params);
265 
286  void startSender(D2ClientErrorHandler error_handler,
287  isc::asiolink::IOService& io_service);
288 
304  void startSender(D2ClientErrorHandler error_handler);
305 
310  bool amSending() const;
311 
320  void stopSender();
321 
334 
346  Result result,
348 
350  size_t getQueueSize() const;
351 
353  size_t getQueueMaxSize() const;
354 
366  const dhcp_ddns::NameChangeRequestPtr& peekAt(const size_t index) const;
367 
372  void clearQueue();
373 
380  void runReadyIO();
381 
391  void suspendUpdates();
392 
393 protected:
404  virtual void operator ()(const dhcp_ddns::NameChangeSender::Result result,
406 
417  int getSelectFd();
418 
425  int getRegisteredSelectFd();
426 
427 private:
429  D2ClientConfigPtr d2_client_config_;
430 
432  dhcp_ddns::NameChangeSenderPtr name_change_sender_;
433 
436  boost::shared_ptr<asiolink::IOService> private_io_service_;
437 
440  D2ClientErrorHandler client_error_handler_;
441 
443  int registered_select_fd_;
444 };
445 
446 template <class T>
447 void
448 D2ClientMgr::adjustFqdnFlags(const T& fqdn, T& fqdn_resp, const DdnsParams& ddns_params) {
449  bool server_s = false;
450  bool server_n = false;
451  analyzeFqdn(fqdn.getFlag(T::FLAG_S), fqdn.getFlag(T::FLAG_N),
452  server_s, server_n, ddns_params);
453 
454  // Reset the flags to zero to avoid triggering N and S both 1 check.
455  fqdn_resp.resetFlags();
456 
457  // Set S and N flags.
458  fqdn_resp.setFlag(T::FLAG_S, server_s);
459  fqdn_resp.setFlag(T::FLAG_N, server_n);
460 
461  // Set O flag true if server S overrides client S.
462  fqdn_resp.setFlag(T::FLAG_O, (fqdn.getFlag(T::FLAG_S) != server_s));
463 }
464 
465 template <class T>
466 void
468  bool& forward, bool& reverse) {
469  forward = fqdn_resp.getFlag(T::FLAG_S);
470  reverse = !(fqdn_resp.getFlag(T::FLAG_N));
471 }
472 
473 template <class T>
474 void
475 D2ClientMgr::adjustDomainName(const T& fqdn, T& fqdn_resp, const DdnsParams& ddns_params) {
476  // If we're configured to replace it or the supplied name is blank
477  // set the response name to blank.
480  fqdn.getDomainName().empty()) {
481  fqdn_resp.setDomainName("", T::PARTIAL);
482  } else {
483  // Sanitize the name the client sent us, if we're configured to do so.
484  std::string client_name = fqdn.getDomainName();
485 
487  if (sanitizer) {
488  // We need the raw text form, so we can replace escaped chars
489  dns::Name tmp(client_name);
490  std::string raw_name = tmp.toRawText();
491 
492  // We do not know if the sanitizer's regexp preserves dots, so
493  // we'll scrub it label by label. Yeah, lucky us.
494  // Using boost::split is simpler than using dns::Name::split() as
495  // that returns Names which have trailing dots etc.
496  std::vector<std::string> labels;
497  boost::algorithm::split(labels, raw_name, boost::is_any_of("."));
498  std::stringstream ss;
499  for (auto label = labels.begin(); label != labels.end(); ++label ) {
500  if (label != labels.begin()) {
501  ss << ".";
502  }
503 
504  ss << sanitizer->scrub(*label);
505  }
506 
507  client_name = ss.str();
508  }
509 
510  // If the supplied name is partial, qualify it by adding the suffix.
511  if (fqdn.getDomainNameType() == T::PARTIAL) {
512  fqdn_resp.setDomainName(qualifyName(client_name, ddns_params, true), T::FULL);
513  }
514  else {
515  fqdn_resp.setDomainName(client_name, T::FULL);
516  }
517  }
518 }
519 
520 
522 typedef boost::shared_ptr<D2ClientMgr> D2ClientMgrPtr;
523 
524 
525 } // namespace isc
526 } // namespace dhcp
527 
528 #endif
The Name class encapsulates DNS names.
Definition: name.h:223
Defines the D2ClientConfig class.
D2ClientConfig::ReplaceClientNameMode getReplaceClientNameMode() const
Returns how Kea should handle the domain-name supplied by the client.
Definition: srv_config.cc:927
This file defines abstract classes for exchanging NameChangeRequests.
void adjustDomainName(const T &fqdn, T &fqdn_resp, const DdnsParams &ddns_params)
Set server FQDN name based on configuration and a given FQDN.
~D2ClientMgr()
Destructor.
void startSender(D2ClientErrorHandler error_handler, isc::asiolink::IOService &io_service)
Enables sending NameChangeRequests to kea-dhcp-ddns.
Result
Defines the outcome of an asynchronous NCR send.
Definition: ncr_io.h:476
virtual void operator()(const dhcp_ddns::NameChangeSender::Result result, dhcp_ddns::NameChangeRequestPtr &ncr)
Function operator implementing the NCR sender callback.
boost::shared_ptr< NameChangeRequest > NameChangeRequestPtr
Defines a pointer to a NameChangeRequest.
Definition: ncr_msg.h:212
void sendRequest(dhcp_ddns::NameChangeRequestPtr &ncr)
Send the given NameChangeRequests to kea-dhcp-ddns.
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.
std::string toRawText(bool omit_final_dot=false) const
Convert the LabelSequence to a string without escape sequences.
Definition: name.cc:513
const D2ClientConfigPtr & getD2ClientConfig() const
Fetches the DHCP-DDNS configuration pointer.
size_t getQueueMaxSize() const
Returns the maximum number of NCRs allowed in the queue.
const dhcp_ddns::NameChangeRequestPtr & peekAt(const size_t index) const
Returns the nth NCR queued for transmission.
boost::shared_ptr< D2ClientMgr > D2ClientMgrPtr
Defines a pointer for D2ClientMgr instances.
bool ddnsEnabled()
Convenience method for checking if DHCP-DDNS is enabled.
void clearQueue()
Removes all NCRs queued for transmission.
void invokeClientErrorHandler(const dhcp_ddns::NameChangeSender::Result result, dhcp_ddns::NameChangeRequestPtr &ncr)
Calls the client's error handler.
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.
isc::util::str::StringSanitizerPtr getHostnameSanitizer() const
Returns a regular expression string sanitizer.
Definition: srv_config.cc:972
boost::shared_ptr< NameChangeSender > NameChangeSenderPtr
Defines a smart pointer to an instance of a sender.
Definition: ncr_io.h:848
Convenience container for conveying DDNS behavioral parameters It is intended to be created per Packe...
Definition: srv_config.h:46
Abstract class for defining application layer send callbacks.
Definition: ncr_io.h:488
Defines the logger used by the top-level component of kea-dhcp-ddns.
D2ClientMgr isolates Kea from the details of being a D2 client.
Definition: d2_client_mgr.h:79
void getUpdateDirections(const T &fqdn_resp, bool &forward, bool &reverse)
Get directional update flags based on server FQDN flags.
ReplaceClientNameMode
Defines the client name replacement modes.
Definition: d2_client_cfg.h:75
size_t getQueueSize() const
Returns the number of NCRs 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.
void suspendUpdates()
Suspends sending requests.
Abstract interface for sending NameChangeRequests.
Definition: ncr_io.h:466
boost::shared_ptr< StringSanitizer > StringSanitizerPtr
Definition: strutil.h:348
D2ClientMgr()
Constructor.
int getSelectFd()
Fetches the sender's select-fd.
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
bool amSending() const
Returns true if the sender is in send mode, false otherwise.
int getRegisteredSelectFd()
Fetches the select-fd that is currently registered.
boost::shared_ptr< D2ClientConfig > D2ClientConfigPtr
Defines a pointer for D2ClientConfig instances.
void adjustFqdnFlags(const T &fqdn, T &fqdn_resp, const DdnsParams &ddns_params)
Set server FQDN flags based on configuration and a given FQDN.
void runReadyIO()
Processes sender IO events.
void setD2ClientConfig(D2ClientConfigPtr &new_config)
Updates the DHCP-DDNS client configuration to the given value.
void stopSender()
Disables sending NameChangeRequests to kea-dhcp-ddns.