Kea 3.3.3
ncr_generator.cc
Go to the documentation of this file.
1// Copyright (C) 2015-2026 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
10#include <dhcpsrv/cfgmgr.h>
11#include <dhcpsrv/dhcpsrv_log.h>
14#include <stdint.h>
15#include <vector>
16#include <util/str.h>
17
18using namespace isc;
19using namespace isc::dhcp;
20using namespace isc::dhcp_ddns;
21
22namespace {
23
35template<typename LeasePtrType, typename IdentifierType>
37generateNCRCommon(const NameChangeType& chg_type, const LeasePtrType& lease,
38 const IdentifierType& identifier,
39 const ConstSubnetPtr subnet) {
40 // Check if there is a need for update.
41 if (lease->hostname_.empty() || (!lease->fqdn_fwd_ && !lease->fqdn_rev_)
42 || !CfgMgr::instance().getD2ClientMgr().ddnsEnabled()) {
43 return (NameChangeRequestPtr());
44 }
45
46 ConflictResolutionMode conflict_resolution_mode = CHECK_WITH_DHCID;
47 util::Optional<double> ddns_ttl_percent;
49 util::Optional<uint32_t> ddns_ttl_min;
50 util::Optional<uint32_t> ddns_ttl_max;
51 if (subnet) {
52 // Create a DdnsParams so we have access to pool scope values.
53 DdnsParams ddns_params(subnet, true);
54 static_cast<void>(ddns_params.setPoolFromAddress(lease->addr_));
55
56 auto mode = ddns_params.getConflictResolutionMode();
57 if (!mode.empty()) {
58 conflict_resolution_mode = StringToConflictResolutionMode(mode);
59 }
60
61 ddns_ttl_percent = ddns_params.getTtlPercent();
62 ddns_ttl = ddns_params.getTtl();
63 ddns_ttl_min = ddns_params.getTtlMin();
64 ddns_ttl_max = ddns_params.getTtlMax();
65 }
66
67 // Create DHCID
68 std::vector<uint8_t> hostname_wire;
69 OptionDataTypeUtil::writeFqdn(lease->hostname_, hostname_wire, true);
70 D2Dhcid dhcid = D2Dhcid(identifier, hostname_wire);
71
72 // Calculate the TTL based on lease life time.
73 uint32_t ttl = calculateDdnsTtl(lease->valid_lft_,
74 ddns_ttl_percent, ddns_ttl,
75 ddns_ttl_min, ddns_ttl_max);
76 // Create name change request.
78 (new NameChangeRequest(chg_type, lease->fqdn_fwd_, lease->fqdn_rev_,
79 lease->hostname_, lease->addr_.toText(),
80 dhcid, ttl, conflict_resolution_mode));
81
82 return (ncr);
83}
84
100template<typename LeasePtrType, typename IdentifierType>
101void queueNCRCommon(const NameChangeType& chg_type, const LeasePtrType& lease,
102 const IdentifierType& identifier, const std::string& label,
103 const ConstSubnetPtr subnet) {
104
105 try {
106 NameChangeRequestPtr ncr = generateNCRCommon(chg_type, lease, identifier, subnet);
107 if (!ncr) {
109 .arg(label)
110 .arg(lease->addr_.toText());
111 return;
112 }
113
114 // Send name change request.
117 .arg(label)
118 .arg(chg_type == CHG_ADD ? "add" : "remove")
119 .arg(ncr->toText());
120 } catch (const std::exception& ex) {
122 .arg(label)
123 .arg(chg_type == CHG_ADD ? "add" : "remove")
124 .arg(lease->addr_.toText())
125 .arg(ex.what());
126 }
127}
128
129} // end of anonymous namespace
130
131namespace isc {
132namespace dhcp {
133
134void queueNCR(const NameChangeType& chg_type, const Lease4Ptr& lease) {
135 if (lease) {
136 // Figure out from the lease's subnet if we should use conflict resolution.
137 // If there's no subnet, something hinky is going on so we'll set it true.
139 ->getCfgSubnets4()->getSubnet(lease->subnet_id_);
140
141 // Client id takes precedence over HW address.
142 if (lease->client_id_) {
143 queueNCRCommon(chg_type, lease, lease->client_id_->getClientId(),
144 Pkt4::makeLabel(lease->hwaddr_, lease->client_id_), subnet);
145 } else {
146 // Client id is not specified for the lease. Use HW address
147 // instead.
148 queueNCRCommon(chg_type, lease, lease->hwaddr_,
149 Pkt4::makeLabel(lease->hwaddr_, lease->client_id_), subnet);
150 }
151 }
152}
153
155generateNCR(const NameChangeType& chg_type, const Lease4Ptr& lease) {
157 if (lease) {
158 // Figure out from the lease's subnet if we should use conflict resolution.
159 // If there's no subnet, something hinky is going on so we'll set it true.
161 ->getCfgSubnets4()->getSubnet(lease->subnet_id_);
162
163 try {
164 // Client id takes precedence over HW address.
165 if (lease->client_id_) {
166 ncr = generateNCRCommon(chg_type, lease,
167 lease->client_id_->getClientId(), subnet);
168 } else {
169 // Client id is not specified for the lease. Use HW address
170 // instead.
171 ncr = generateNCRCommon(chg_type, lease, lease->hwaddr_, subnet);
172 }
173 } catch (const std::exception& ex) {
175 .arg(Pkt4::makeLabel(lease->hwaddr_, lease->client_id_))
176 .arg(chg_type == CHG_ADD ? "add" : "remove")
177 .arg(lease->addr_.toText())
178 .arg(ex.what());
179 }
180 }
181
182 return (ncr);
183}
184
185void queueNCR(const NameChangeType& chg_type, const Lease6Ptr& lease) {
186 // DUID is required to generate NCR.
187 if (lease && (lease->type_ != Lease::TYPE_PD) && lease->duid_) {
188 // Figure out from the lease's subnet if we should use conflict resolution.
189 // If there's no subnet, something hinky is going on so we'll set it true.
191 ->getCfgSubnets6()->getSubnet(lease->subnet_id_);
192
193 queueNCRCommon(chg_type, lease, *(lease->duid_),
194 Pkt6::makeLabel(lease->duid_, lease->hwaddr_), subnet);
195 }
196}
197
199generateNCR(const NameChangeType& chg_type, const Lease6Ptr& lease) {
201 // DUID is required to generate NCR.
202 if (lease && (lease->type_ != Lease::TYPE_PD) && lease->duid_) {
203 // Figure out from the lease's subnet if we should use conflict resolution.
204 // If there's no subnet, something hinky is going on so we'll set it true.
206 ->getCfgSubnets6()->getSubnet(lease->subnet_id_);
207 try {
208 ncr = generateNCRCommon(chg_type, lease, *(lease->duid_), subnet);
209 } catch (const std::exception& ex) {
211 .arg(Pkt6::makeLabel(lease->duid_, lease->hwaddr_))
212 .arg(chg_type == CHG_ADD ? "add" : "remove")
213 .arg(lease->addr_.toText())
214 .arg(ex.what());
215 }
216 }
217
218 return (ncr);
219}
220
221uint32_t calculateDdnsTtl(uint32_t lease_lft,
222 const util::Optional<double>& ddns_ttl_percent,
223 const util::Optional<uint32_t>& ddns_ttl,
224 const util::Optional<uint32_t>& ddns_ttl_min,
225 const util::Optional<uint32_t>& ddns_ttl_max) {
226 // If we have an explicit value use it.
227 if (!ddns_ttl.unspecified() && ddns_ttl.get() > 0) {
228 return (ddns_ttl.get());
229 }
230
231 // Use specified percentage (if one) or 1/3 as called for in RFC 4702.
232 double ttl_percent = (ddns_ttl_percent.get() > 0.0 ?
233 ddns_ttl_percent.get() : 0.33333);
234
235 // Calculate the ttl.
236 uint32_t ttl = static_cast<uint32_t>(round(ttl_percent * lease_lft));
237
238 // Adjust for minimum and maximum.
239 // If we have a custom minimum enforce it, otherwise per RFC 4702 it
240 // should not less than 600.
241 uint32_t ttl_min = (ddns_ttl_min.get() > 0) ? ddns_ttl_min.get() : 600;
242 if (ttl < ttl_min) {
245 .arg(util::str::dumpDouble(ttl_percent))
246 .arg(lease_lft)
247 .arg(ttl)
248 .arg(ttl_min);
249 return (ttl_min);
250 }
251
252 // If we have a maximum enforce it.
253 uint32_t ttl_max = ddns_ttl_max.get();
254 if (ttl_max && ttl > ttl_max) {
257 .arg(util::str::dumpDouble(ttl_percent))
258 .arg(lease_lft)
259 .arg(ttl)
260 .arg(ttl_max);
261 return (ttl_max);
262 }
263
264 return (ttl);
265}
266
267}
268}
D2ClientMgr & getD2ClientMgr()
Fetches the DHCP-DDNS manager.
Definition cfgmgr.cc:69
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:29
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition cfgmgr.cc:116
void sendRequest(dhcp_ddns::NameChangeRequestPtr &ncr)
Send the given 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
static void writeFqdn(const std::string &fqdn, std::vector< uint8_t > &buf, const bool downcase=false)
Append FQDN into a buffer.
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:399
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:703
Container class for handling the DHCID value within a NameChangeRequest.
Definition ncr_msg.h:117
Represents a DHCP-DDNS client request.
Definition ncr_msg.h:258
A template representing an optional value.
Definition optional.h:37
T get() const
Retrieves the encapsulated value.
Definition optional.h:123
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
Definition optional.h:145
Defines the D2ClientMgr class.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition macros.h:32
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition macros.h:14
NameChangeType
Defines the types of DNS updates that can be requested.
Definition ncr_msg.h:49
ConflictResolutionMode StringToConflictResolutionMode(const std::string &mode_str)
Function which converts string to ConflictResolutionMode enum values.
Definition ncr_msg.cc:42
boost::shared_ptr< NameChangeRequest > NameChangeRequestPtr
Defines a pointer to a NameChangeRequest.
Definition ncr_msg.h:245
const int DHCPSRV_DBG_TRACE_DETAIL_DATA
Additional information.
Definition dhcpsrv_log.h:43
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition dhcpsrv_log.h:56
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.
const isc::log::MessageID DHCPSRV_QUEUE_NCR
void queueNCR(const NameChangeType &chg_type, const Lease4Ptr &lease)
Creates NameChangeRequest from the DHCPv4 lease and queues it to be sent to D2.
boost::shared_ptr< const Subnet6 > ConstSubnet6Ptr
A const pointer to a Subnet6 object.
Definition subnet.h:620
const isc::log::MessageID DHCPSRV_GENERATE_NCR4_FAILED
boost::shared_ptr< const Subnet4 > ConstSubnet4Ptr
A const pointer to a Subnet4 object.
Definition subnet.h:455
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition lease.h:530
const isc::log::MessageID DHCPSRV_DDNS_TTL_TOO_LARGE
const isc::log::MessageID DHCPSRV_QUEUE_NCR_FAILED
const int DHCPSRV_DBG_TRACE_DETAIL
Additional information.
Definition dhcpsrv_log.h:38
const isc::log::MessageID DHCPSRV_GENERATE_NCR6_FAILED
const isc::log::MessageID DHCPSRV_QUEUE_NCR_SKIP
const isc::log::MessageID DHCPSRV_DDNS_TTL_TOO_SMALL
NameChangeRequestPtr generateNCR(const NameChangeType &chg_type, const Lease4Ptr &lease)
Creates NameChangeRequest from the DHCPv4 lease.
boost::shared_ptr< const Subnet > ConstSubnetPtr
A generic pointer to either const Subnet4 or const Subnet6 object.
Definition subnet.h:449
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition lease.h:317
string dumpDouble(double val, size_t precision)
Converts a double to a string with given precision.
Definition str.cc:359
Defines the logger used by the top-level component of kea-lfc.
@ TYPE_PD
the lease contains IPv6 prefix (for prefix delegation)
Definition lease.h:51