| Kea 3.0.2-git

ncr_generator.cc
Go to the documentation of this file.
1// Copyright (C) 2015-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#include <config.h>
8
9#include <dhcp/option_data_types.h>
10#include <dhcpsrv/cfgmgr.h>
11#include <dhcpsrv/dhcpsrv_log.h>
12#include <dhcpsrv/d2_client_mgr.h>
13#include <dhcpsrv/ncr_generator.h>
14#include <stdint.h>
15#include <vector>
16#include <util/str.h>
17
18 using namespace isc;
19 using namespace isc::dhcp;
20 using namespace isc::dhcp_ddns;
21
22 namespace {
23
39 template<typename LeasePtrType, typename IdentifierType>
40 void queueNCRCommon(const NameChangeType& chg_type, const LeasePtrType& lease,
41 const IdentifierType& identifier, const std::string& label,
42 const ConstSubnetPtr subnet) {
43 // Check if there is a need for update.
44 if (lease->hostname_.empty() || (!lease->fqdn_fwd_ && !lease->fqdn_rev_)
45 || !CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
46 LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
47 DHCPSRV_QUEUE_NCR_SKIP)
48 .arg(label)
49 .arg(lease->addr_.toText());
50
51 return;
52 }
53
54 ConflictResolutionMode conflict_resolution_mode = CHECK_WITH_DHCID;
55 util::Optional<double> ddns_ttl_percent;
56 util::Optional<uint32_t> ddns_ttl;
57 util::Optional<uint32_t> ddns_ttl_min;
58 util::Optional<uint32_t> ddns_ttl_max;
59 if (subnet) {
60 // Create a DdnsParams so we have access to pool scope values.
61 DdnsParams ddns_params(subnet, true);
62 static_cast<void>(ddns_params.setPoolFromAddress(lease->addr_));
63
64 auto mode = ddns_params.getConflictResolutionMode();
65 if (!mode.empty()) {
66 conflict_resolution_mode = StringToConflictResolutionMode(mode);
67 }
68
69 ddns_ttl_percent = ddns_params.getTtlPercent();
70 ddns_ttl = ddns_params.getTtl();
71 ddns_ttl_min = ddns_params.getTtlMin();
72 ddns_ttl_max = ddns_params.getTtlMax();
73 }
74
75 try {
76 // Create DHCID
77 std::vector<uint8_t> hostname_wire;
78 OptionDataTypeUtil::writeFqdn(lease->hostname_, hostname_wire, true);
79 D2Dhcid dhcid = D2Dhcid(identifier, hostname_wire);
80
81 // Calculate the TTL based on lease life time.
82 uint32_t ttl = calculateDdnsTtl(lease->valid_lft_,
83 ddns_ttl_percent, ddns_ttl,
84 ddns_ttl_min, ddns_ttl_max);
85
86 // Create name change request.
87 NameChangeRequestPtr ncr
88 (new NameChangeRequest(chg_type, lease->fqdn_fwd_, lease->fqdn_rev_,
89 lease->hostname_, lease->addr_.toText(),
90 dhcid, lease->cltt_ + ttl,
91 ttl, conflict_resolution_mode));
92
93 LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL_DATA, DHCPSRV_QUEUE_NCR)
94 .arg(label)
95 .arg(chg_type == CHG_ADD ? "add" : "remove")
96 .arg(ncr->toText());
97
98 // Send name change request.
99 CfgMgr::instance().getD2ClientMgr().sendRequest(ncr);
100
101 } catch (const std::exception& ex) {
102 LOG_ERROR(dhcpsrv_logger, DHCPSRV_QUEUE_NCR_FAILED)
103 .arg(label)
104 .arg(chg_type == CHG_ADD ? "add" : "remove")
105 .arg(lease->addr_.toText())
106 .arg(ex.what());
107 }
108}
109
110} // end of anonymous namespace
111
112 namespace isc {
113 namespace dhcp {
114
115 void queueNCR(const NameChangeType& chg_type, const Lease4Ptr& lease) {
116 if (lease) {
117 // Figure out from the lease's subnet if we should use conflict resolution.
118 // If there's no subnet, something hinky is going on so we'll set it true.
119 ConstSubnet4Ptr subnet = CfgMgr::instance().getCurrentCfg()
120 ->getCfgSubnets4()->getSubnet(lease->subnet_id_);
121
122 // Client id takes precedence over HW address.
123 if (lease->client_id_) {
124 queueNCRCommon(chg_type, lease, lease->client_id_->getClientId(),
125 Pkt4::makeLabel(lease->hwaddr_, lease->client_id_), subnet);
126 } else {
127 // Client id is not specified for the lease. Use HW address
128 // instead.
129 queueNCRCommon(chg_type, lease, lease->hwaddr_,
130 Pkt4::makeLabel(lease->hwaddr_, lease->client_id_), subnet);
131 }
132 }
133}
134
135 void queueNCR(const NameChangeType& chg_type, const Lease6Ptr& lease) {
136 // DUID is required to generate NCR.
137 if (lease && (lease->type_ != Lease::TYPE_PD) && lease->duid_) {
138 // Figure out from the lease's subnet if we should use conflict resolution.
139 // If there's no subnet, something hinky is going on so we'll set it true.
140 ConstSubnet6Ptr subnet = CfgMgr::instance().getCurrentCfg()
141 ->getCfgSubnets6()->getSubnet(lease->subnet_id_);
142 queueNCRCommon(chg_type, lease, *(lease->duid_),
143 Pkt6::makeLabel(lease->duid_, lease->hwaddr_), subnet);
144 }
145}
146
147uint32_t calculateDdnsTtl(uint32_t lease_lft,
148 const util::Optional<double>& ddns_ttl_percent,
149 const util::Optional<uint32_t>& ddns_ttl,
150 const util::Optional<uint32_t>& ddns_ttl_min,
151 const util::Optional<uint32_t>& ddns_ttl_max) {
152 // If we have an explicit value use it.
153 if (!ddns_ttl.unspecified() && ddns_ttl.get() > 0) {
154 return (ddns_ttl.get());
155 }
156
157 // Use specified percentage (if one) or 1/3 as called for in RFC 4702.
158 double ttl_percent = (ddns_ttl_percent.get() > 0.0 ?
159 ddns_ttl_percent.get() : 0.33333);
160
161 // Calculate the ttl.
162 uint32_t ttl = static_cast<uint32_t>(round(ttl_percent * lease_lft));
163
164 // Adjust for minimum and maximum.
165 // If we have a custom minimum enforce it, otherwise per RFC 4702 it
166 // should not less than 600.
167 uint32_t ttl_min = (ddns_ttl_min.get() > 0) ? ddns_ttl_min.get() : 600;
168 if (ttl < ttl_min) {
169 LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL_DATA,
170 DHCPSRV_DDNS_TTL_TOO_SMALL)
171 .arg(util::str::dumpDouble(ttl_percent))
172 .arg(lease_lft)
173 .arg(ttl)
174 .arg(ttl_min);
175 return (ttl_min);
176 }
177
178 // If we have a maximum enforce it.
179 uint32_t ttl_max = ddns_ttl_max.get();
180 if (ttl_max && ttl > ttl_max) {
181 LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL_DATA,
182 DHCPSRV_DDNS_TTL_TOO_LARGE)
183 .arg(util::str::dumpDouble(ttl_percent))
184 .arg(lease_lft)
185 .arg(ttl)
186 .arg(ttl_max);
187 return (ttl_max);
188 }
189
190 return (ttl);
191}
192
193}
194}
cfgmgr.h
isc::dhcp::CfgMgr::getD2ClientMgr
D2ClientMgr & getD2ClientMgr()
Fetches the DHCP-DDNS manager.
Definition cfgmgr.cc:69
isc::dhcp::CfgMgr::instance
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:29
isc::dhcp::CfgMgr::getCurrentCfg
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition cfgmgr.cc:116
isc::dhcp::D2ClientMgr::sendRequest
void sendRequest(dhcp_ddns::NameChangeRequestPtr &ncr)
Send the given NameChangeRequests to kea-dhcp-ddns.
Definition d2_client_mgr.cc:326
isc::dhcp::DdnsParams
Convenience container for conveying DDNS behavioral parameters It is intended to be created per Packe...
Definition ddns_params.h:23
isc::dhcp::IdentifierType
Definition duid.h:37
isc::dhcp::OptionDataTypeUtil::writeFqdn
static void writeFqdn(const std::string &fqdn, std::vector< uint8_t > &buf, const bool downcase=false)
Append FQDN into a buffer.
Definition option_data_types.cc:359
isc::dhcp::Pkt4::makeLabel
static std::string makeLabel(const HWAddrPtr &hwaddr, const ClientIdPtr &client_id, const uint32_t transid)
Returns text representation of the given packet identifiers.
Definition pkt4.cc:397
isc::dhcp::Pkt6::makeLabel
static std::string makeLabel(const DuidPtr duid, const uint32_t transid, const HWAddrPtr &hwaddr)
Returns text representation of the given packet identifiers.
Definition pkt6.cc:693
isc::dhcp_ddns::D2Dhcid
Container class for handling the DHCID value within a NameChangeRequest.
Definition ncr_msg.h:113
isc::dhcp_ddns::NameChangeRequest
Represents a DHCP-DDNS client request.
Definition ncr_msg.h:254
isc::util::Optional
A template representing an optional value.
Definition optional.h:36
isc::util::Optional::get
T get() const
Retrieves the encapsulated value.
Definition optional.h:114
isc::util::Optional::unspecified
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
Definition optional.h:136
d2_client_mgr.h
Defines the D2ClientMgr class.
dhcpsrv_log.h
LOG_ERROR
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition macros.h:32
LOG_DEBUG
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition macros.h:14
isc::dhcp_ddns
Definition dhcp_ddns_log.cc:14
isc::dhcp_ddns::ConflictResolutionMode
ConflictResolutionMode
Definition ncr_msg.h:64
isc::dhcp_ddns::CHECK_WITH_DHCID
@ CHECK_WITH_DHCID
Definition ncr_msg.h:65
isc::dhcp_ddns::StringToConflictResolutionMode
ConflictResolutionMode StringToConflictResolutionMode(const std::string &mode_str)
Function which converts string to ConflictResolutionMode enum values.
Definition ncr_msg.cc:45
isc::dhcp_ddns::NameChangeRequestPtr
boost::shared_ptr< NameChangeRequest > NameChangeRequestPtr
Defines a pointer to a NameChangeRequest.
Definition ncr_msg.h:241
isc::dhcp_ddns::NameChangeType
NameChangeType
Defines the types of DNS updates that can be requested.
Definition ncr_msg.h:45
isc::dhcp_ddns::CHG_ADD
@ CHG_ADD
Definition ncr_msg.h:46
isc::dhcp
Definition dhcp4/client_handler.cc:20
isc::dhcp::DHCPSRV_DBG_TRACE_DETAIL_DATA
const int DHCPSRV_DBG_TRACE_DETAIL_DATA
Additional information.
Definition dhcpsrv_log.h:43
isc::dhcp::dhcpsrv_logger
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition dhcpsrv_log.h:56
isc::dhcp::calculateDdnsTtl
uint32_t calculateDdnsTtl(uint32_t lease_lft, const util::Optional< double > &ddns_ttl_percent, const util::Optional< uint32_t > &ddns_ttl, const util::Optional< uint32_t > &ddns_ttl_min, const util::Optional< uint32_t > &ddns_ttl_max)
Calculates TTL for a DNS resource record based on lease life time.
Definition ncr_generator.cc:147
isc::dhcp::DHCPSRV_QUEUE_NCR
const isc::log::MessageID DHCPSRV_QUEUE_NCR
Definition dhcpsrv_messages.h:156
isc::dhcp::queueNCR
void queueNCR(const NameChangeType &chg_type, const Lease4Ptr &lease)
Creates name change request from the DHCPv4 lease.
Definition ncr_generator.cc:115
isc::dhcp::ConstSubnet6Ptr
boost::shared_ptr< const Subnet6 > ConstSubnet6Ptr
A const pointer to a Subnet6 object.
Definition subnet.h:623
isc::dhcp::ConstSubnet4Ptr
boost::shared_ptr< const Subnet4 > ConstSubnet4Ptr
A const pointer to a Subnet4 object.
Definition subnet.h:458
isc::dhcp::Lease6Ptr
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition lease.h:528
isc::dhcp::DHCPSRV_DDNS_TTL_TOO_LARGE
const isc::log::MessageID DHCPSRV_DDNS_TTL_TOO_LARGE
Definition dhcpsrv_messages.h:53
isc::dhcp::DHCPSRV_QUEUE_NCR_FAILED
const isc::log::MessageID DHCPSRV_QUEUE_NCR_FAILED
Definition dhcpsrv_messages.h:157
isc::dhcp::DHCPSRV_DBG_TRACE_DETAIL
const int DHCPSRV_DBG_TRACE_DETAIL
Additional information.
Definition dhcpsrv_log.h:38
isc::dhcp::DHCPSRV_QUEUE_NCR_SKIP
const isc::log::MessageID DHCPSRV_QUEUE_NCR_SKIP
Definition dhcpsrv_messages.h:158
isc::dhcp::DHCPSRV_DDNS_TTL_TOO_SMALL
const isc::log::MessageID DHCPSRV_DDNS_TTL_TOO_SMALL
Definition dhcpsrv_messages.h:54
isc::dhcp::ConstSubnetPtr
boost::shared_ptr< const Subnet > ConstSubnetPtr
A generic pointer to either const Subnet4 or const Subnet6 object.
Definition subnet.h:452
isc::dhcp::Lease4Ptr
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition lease.h:315
isc::util::str::dumpDouble
string dumpDouble(double val, size_t precision)
Converts a double to a string with given precision.
Definition str.cc:344
isc
Defines the logger used by the top-level component of kea-lfc.
Definition agent_parser.cc:148
ncr_generator.h
option_data_types.h
str.h
isc::dhcp::Lease::TYPE_PD
@ TYPE_PD
the lease contains IPv6 prefix (for prefix delegation)
Definition lease.h:49