Kea 3.0.2-git
d2_client_mgr.h
Go to the documentation of this file.
1// Copyright (C) 2014-2025 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>
17#include <dhcpsrv/srv_config.h>
19#include <util/str.h>
20
21#include <boost/algorithm/string.hpp>
22#include <boost/shared_ptr.hpp>
23#include <boost/noncopyable.hpp>
24
25#include <stdint.h>
26#include <string>
27#include <vector>
28#include <sstream>
29
30namespace isc {
31namespace dhcp {
32
36public:
37 FQDNScrubbedEmpty(const char* file, size_t line, const char* what) :
38 isc::Exception(file, line, what) { }
39};
40
51typedef
52std::function<void(const dhcp_ddns::NameChangeSender::Result result,
54
89 boost::noncopyable {
90public:
96
99
104 void setD2ClientConfig(D2ClientConfigPtr& new_config);
105
109 bool ddnsEnabled();
110
115
164 void analyzeFqdn(const bool client_s, const bool client_n, bool& server_s,
165 bool& server_n, const DdnsParams& ddns_params) const;
166
186 std::string generateFqdn(const asiolink::IOAddress& address,
187 const DdnsParams& ddns_params,
188 const bool trailing_dot = true) const;
189
209 std::string qualifyName(const std::string& partial_name,
210 const DdnsParams& ddns_params,
211 const bool trailing_dot) const;
212
225 template <class T>
226 void adjustFqdnFlags(const T& fqdn, T& fqdn_resp,
227 const DdnsParams& ddns_params);
228
246 template <class T>
247 void getUpdateDirections(const T& fqdn_resp, bool& forward, bool& reverse);
248
279 template <class T>
280 void adjustDomainName(const T& fqdn, T& fqdn_resp,
281 const DdnsParams& ddns_params);
282
303 void startSender(D2ClientErrorHandler error_handler,
304 const isc::asiolink::IOServicePtr& io_service);
305
321 void startSender(D2ClientErrorHandler error_handler);
322
327 bool amSending() const;
328
337 void stopSender();
338
351
363 Result result,
365
367 size_t getQueueSize() const;
368
370 size_t getQueueMaxSize() const;
371
383 const dhcp_ddns::NameChangeRequestPtr& peekAt(const size_t index) const;
384
389 void clearQueue();
390
397 void runReadyIO();
398
408 void suspendUpdates();
409
411 void stop();
412
413protected:
424 virtual void operator ()(const dhcp_ddns::NameChangeSender::Result result,
426
437 int getSelectFd();
438
446
447private:
448
450 D2ClientConfigPtr d2_client_config_;
451
453 dhcp_ddns::NameChangeSenderPtr name_change_sender_;
454
457 boost::shared_ptr<asiolink::IOService> private_io_service_;
458
461 D2ClientErrorHandler client_error_handler_;
462
464 int registered_select_fd_;
465};
466
467template <class T>
468void
469D2ClientMgr::adjustFqdnFlags(const T& fqdn, T& fqdn_resp, const DdnsParams& ddns_params) {
470 bool server_s = false;
471 bool server_n = false;
472 analyzeFqdn(fqdn.getFlag(T::FLAG_S), fqdn.getFlag(T::FLAG_N),
473 server_s, server_n, ddns_params);
474
475 // Reset the flags to zero to avoid triggering N and S both 1 check.
476 fqdn_resp.resetFlags();
477
478 // Set S and N flags.
479 fqdn_resp.setFlag(T::FLAG_S, server_s);
480 fqdn_resp.setFlag(T::FLAG_N, server_n);
481
482 // Set O flag true if server S overrides client S.
483 fqdn_resp.setFlag(T::FLAG_O, (fqdn.getFlag(T::FLAG_S) != server_s));
484}
485
486template <class T>
487void
489 bool& forward, bool& reverse) {
490 forward = fqdn_resp.getFlag(T::FLAG_S);
491 reverse = !(fqdn_resp.getFlag(T::FLAG_N));
492}
493
494template <class T>
495void
496D2ClientMgr::adjustDomainName(const T& fqdn, T& fqdn_resp, const DdnsParams& ddns_params) {
497 // If we're configured to replace it or the supplied name is blank
498 // set the response name to blank.
501 fqdn.getDomainName().empty()) {
502 fqdn_resp.setDomainName("", T::PARTIAL);
503 } else {
504 // Sanitize the name the client sent us, if we're configured to do so.
505 std::string client_name = fqdn.getDomainName();
507 if (sanitizer) {
508 // We need the raw text form, so we can replace escaped chars
509 dns::Name tmp(client_name);
510 std::string raw_name = tmp.toRawText();
511
512 // We do not know if the sanitizer's regexp preserves dots, so
513 // we'll scrub it label by label. Yeah, lucky us.
514 // Using boost::split is simpler than using dns::Name::split() as
515 // that returns Names which have trailing dots etc.
516 std::vector<std::string> labels;
517 boost::algorithm::split(labels, raw_name, boost::is_any_of("."));
518 std::stringstream ss;
519 bool first = true;
520 for (auto const& label : labels) {
521 if (!first) {
522 ss << ".";
523 } else {
524 first = false;
525 }
526
527 ss << sanitizer->scrub(label);
528 }
529
530 std::string clean_name = ss.str();
531 if (clean_name.empty() || clean_name == ".") {
532 isc_throw(FQDNScrubbedEmpty, client_name);
533 }
534
535 client_name = clean_name;
536 }
537
538 // If the supplied name is partial, qualify it by adding the suffix.
539 if (fqdn.getDomainNameType() == T::PARTIAL) {
540 if (client_name.back() == '.') {
541 // By definition a partial cannot end in a dot, sanitizing above
542 // may have added one. Strip it, so we'll add the suffix (if one).
543 client_name.pop_back();
544 }
545
546 fqdn_resp.setDomainName(qualifyName(client_name, ddns_params, true), T::FULL);
547 } else {
548 fqdn_resp.setDomainName(client_name, T::FULL);
549 }
550 }
551}
552
553
555typedef boost::shared_ptr<D2ClientMgr> D2ClientMgrPtr;
556
557
558} // namespace isc
559} // namespace dhcp
560
561#endif
Exception(const char *file, size_t line, const char *what)
Constructor for a given type for exceptions with file name and file line number.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
ReplaceClientNameMode
Defines the client name replacement modes.
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 getUpdateDirections(const T &fqdn_resp, bool &forward, bool &reverse)
Get directional update flags based on server FQDN flags.
void stop()
Stop the sender.
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()
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.
void startSender(D2ClientErrorHandler error_handler, const isc::asiolink::IOServicePtr &io_service)
Enables sending NameChangeRequests to kea-dhcp-ddns.
Convenience container for conveying DDNS behavioral parameters It is intended to be created per Packe...
Definition ddns_params.h:23
D2ClientConfig::ReplaceClientNameMode getReplaceClientNameMode() const
Returns how Kea should handle the domain-name supplied by the client.
isc::util::str::StringSanitizerPtr getHostnameSanitizer() const
Returns a regular expression string sanitizer.
Exception thrown when host name sanitizing reduces the domain name to an empty string.
FQDNScrubbedEmpty(const char *file, size_t line, const char *what)
Abstract class for defining application layer send callbacks.
Definition ncr_io.h:490
Abstract interface for sending NameChangeRequests.
Definition ncr_io.h:468
Result
Defines the outcome of an asynchronous NCR send.
Definition ncr_io.h:478
The Name class encapsulates DNS names.
Definition name.h:219
std::string toRawText(bool omit_final_dot=false) const
Convert the LabelSequence to a string without escape sequences.
Definition name.cc:509
Defines the D2ClientConfig class.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< NameChangeSender > NameChangeSenderPtr
Defines a smart pointer to an instance of a sender.
Definition ncr_io.h:857
boost::shared_ptr< NameChangeRequest > NameChangeRequestPtr
Defines a pointer to a NameChangeRequest.
Definition ncr_msg.h:241
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.
std::unique_ptr< StringSanitizer > StringSanitizerPtr
Type representing the pointer to the StringSanitizer.
Definition str.h:263
Defines the logger used by the top-level component of kea-lfc.
This file defines abstract classes for exchanging NameChangeRequests.