Kea: d2_cfg_mgr.cc Source File

| Kea 3.2.0-git

d2_cfg_mgr.cc
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#include <config.h>
8
9#include <d2srv/d2_log.h>
10#include <d2srv/d2_cfg_mgr.h>
11#include <d2srv/d2_simple_parser.h>
12#include <cc/command_interpreter.h>
13#include <config/base_command_mgr.h>
14#include <util/encode/encode.h>
15#include <boost/range/adaptor/reversed.hpp>
16
17using namespace isc::asiolink;
18using namespace isc::config;
19using namespace isc::data;
20using namespace isc::process;
21
22namespace isc {
23namespace d2 {
24
25namespace {
26
27typedef std::vector<uint8_t> ByteAddress;
28
29} // end of unnamed namespace
30
31// *********************** D2CfgContext *************************
32
33D2CfgContext::D2CfgContext()
34 : d2_params_(new D2Params()),
35 forward_mgr_(new DdnsDomainListMgr("forward-ddns")),
36 reverse_mgr_(new DdnsDomainListMgr("reverse-ddns")),
37 keys_(new TSIGKeyInfoMap()),
38 unix_control_socket_(ConstElementPtr()),
39 http_control_socket_(ConstElementPtr()) {
40}
41
42 D2CfgContext::D2CfgContext(const D2CfgContext& rhs) : ConfigBase(rhs) {
43 d2_params_ = rhs.d2_params_;
44 if (rhs.forward_mgr_) {
45 forward_mgr_.reset(new DdnsDomainListMgr(rhs.forward_mgr_->getName()));
46 forward_mgr_->setDomains(rhs.forward_mgr_->getDomains());
47 }
48
49 if (rhs.reverse_mgr_) {
50 reverse_mgr_.reset(new DdnsDomainListMgr(rhs.reverse_mgr_->getName()));
51 reverse_mgr_->setDomains(rhs.reverse_mgr_->getDomains());
52 }
53
54 keys_ = rhs.keys_;
55
56 unix_control_socket_ = rhs.unix_control_socket_;
57
58 http_control_socket_ = rhs.http_control_socket_;
59
60 hooks_config_ = rhs.hooks_config_;
61}
62
63D2CfgContext::~D2CfgContext() {
64}
65
66 ElementPtr
67D2CfgContext::toElement() const {
68 ElementPtr d2 = ConfigBase::toElement();
69 // Set user-context
70 contextToElement(d2);
71 // Set ip-address
72 const IOAddress& ip_address = d2_params_->getIpAddress();
73 d2->set("ip-address", Element::create(ip_address.toText()));
74 // Set port
75 size_t port = d2_params_->getPort();
76 d2->set("port", Element::create(static_cast<int64_t>(port)));
77 // Set dns-server-timeout
78 size_t dns_server_timeout = d2_params_->getDnsServerTimeout();
79 d2->set("dns-server-timeout",
80 Element::create(static_cast<int64_t>(dns_server_timeout)));
81 // Set ncr-protocol
82 const dhcp_ddns::NameChangeProtocol& ncr_protocol =
83 d2_params_->getNcrProtocol();
84 d2->set("ncr-protocol",
85 Element::create(dhcp_ddns::ncrProtocolToString(ncr_protocol)));
86 // Set ncr-format
87 const dhcp_ddns::NameChangeFormat& ncr_format = d2_params_->getNcrFormat();
88 d2->set("ncr-format",
89 Element::create(dhcp_ddns::ncrFormatToString(ncr_format)));
90 // Set forward-ddns
91 ElementPtr forward_ddns = Element::createMap();
92 forward_ddns->set("ddns-domains", forward_mgr_->toElement());
93 d2->set("forward-ddns", forward_ddns);
94 // Set reverse-ddns
95 ElementPtr reverse_ddns = Element::createMap();
96 reverse_ddns->set("ddns-domains", reverse_mgr_->toElement());
97 d2->set("reverse-ddns", reverse_ddns);
98 // Set tsig-keys
99 ElementPtr tsig_keys = Element::createList();
100 for (auto const& key : *keys_) {
101 tsig_keys->add(key.second->toElement());
102 }
103 d2->set("tsig-keys", tsig_keys);
104 // Set control-sockets.
105 ElementPtr control_sockets = Element::createList();
106 if (!isNull(unix_control_socket_)) {
107 for (auto const& socket : unix_control_socket_->listValue()) {
108 control_sockets->add(UserContext::toElement(socket));
109 }
110 }
111 if (!isNull(http_control_socket_)) {
112 for (auto const& socket : http_control_socket_->listValue()) {
113 control_sockets->add(UserContext::toElement(socket));
114 }
115 }
116 if (!control_sockets->empty()) {
117 d2->set("control-sockets", control_sockets);
118 }
119 // Set hooks-libraries
120 d2->set("hooks-libraries", hooks_config_.toElement());
121 // Set DhcpDdns
122 ElementPtr result = Element::createMap();
123 result->set("DhcpDdns", d2);
124
125 return (result);
126}
127
128// *********************** D2CfgMgr *************************
129
130const char* D2CfgMgr::IPV4_REV_ZONE_SUFFIX = "in-addr.arpa.";
131
132const char* D2CfgMgr::IPV6_REV_ZONE_SUFFIX = "ip6.arpa.";
133
134D2CfgMgr::D2CfgMgr() : DCfgMgrBase(ConfigPtr(new D2CfgContext())) {
135}
136
137D2CfgMgr::~D2CfgMgr() {
138}
139
140 ConfigPtr
141D2CfgMgr::createNewContext() {
142 return (ConfigPtr(new D2CfgContext()));
143}
144
145bool
146D2CfgMgr::forwardUpdatesEnabled() {
147 // Forward updates are not enabled if no forward servers are defined.
148 return (getD2CfgContext()->getForwardMgr()->size() > 0);
149}
150
151bool
152D2CfgMgr::reverseUpdatesEnabled() {
153 // Reverse updates are not enabled if no reverse servers are defined.
154 return (getD2CfgContext()->getReverseMgr()->size() > 0);
155}
156
157bool
158D2CfgMgr::matchForward(const std::string& fqdn, DdnsDomainPtr& domain) {
159 if (fqdn.empty()) {
160 // This is a programmatic error and should not happen.
161 isc_throw(D2CfgError, "matchForward passed an empty fqdn");
162 }
163
164 // Fetch the forward manager from the D2 context.
165 DdnsDomainListMgrPtr mgr = getD2CfgContext()->getForwardMgr();
166
167 // Call the manager's match method and return the result.
168 return (mgr->matchDomain(fqdn, domain));
169}
170
171bool
172D2CfgMgr::matchReverse(const std::string& ip_address, DdnsDomainPtr& domain) {
173 // Note, reverseIpAddress will throw if the ip_address is invalid.
174 std::string reverse_address = reverseIpAddress(ip_address);
175
176 // Fetch the reverse manager from the D2 context.
177 DdnsDomainListMgrPtr mgr = getD2CfgContext()->getReverseMgr();
178
179 return (mgr->matchDomain(reverse_address, domain));
180}
181
182std::string
183D2CfgMgr::reverseIpAddress(const std::string& address) {
184 try {
185 // Convert string address into an IOAddress and invoke the
186 // appropriate reverse method.
187 isc::asiolink::IOAddress ioaddr(address);
188 if (ioaddr.isV4()) {
189 return (reverseV4Address(ioaddr));
190 }
191
192 return (reverseV6Address(ioaddr));
193
194 } catch (const isc::Exception& ex) {
195 isc_throw(D2CfgError, "D2CfgMgr cannot reverse address: "
196 << address << " : " << ex.what());
197 }
198}
199
200std::string
201D2CfgMgr::reverseV4Address(const isc::asiolink::IOAddress& ioaddr) {
202 if (!ioaddr.isV4()) {
203 isc_throw(D2CfgError, "D2CfgMgr address is not IPv4 address :"
204 << ioaddr);
205 }
206
207 // Get the address in byte vector form.
208 const ByteAddress bytes = ioaddr.toBytes();
209
210 // Walk backwards through vector outputting each octet and a dot.
211 std::ostringstream stream;
212
213 for (auto const& rit : boost::adaptors::reverse(bytes)) {
214 stream << static_cast<unsigned int>(rit) << ".";
215 }
216
217 // Tack on the suffix and we're done.
218 stream << IPV4_REV_ZONE_SUFFIX;
219 return(stream.str());
220}
221
222std::string
223D2CfgMgr::reverseV6Address(const isc::asiolink::IOAddress& ioaddr) {
224 if (!ioaddr.isV6()) {
225 isc_throw(D2CfgError, "D2Cfg address is not IPv6 address: " << ioaddr);
226 }
227
228 // Turn the address into a string of digits.
229 const ByteAddress bytes = ioaddr.toBytes();
230 const std::string digits = isc::util::encode::encodeHex(bytes);
231
232 // Walk backwards through string outputting each digits and a dot.
233 std::ostringstream stream;
234
235 for (auto const& rit : boost::adaptors::reverse(digits)) {
236 stream << static_cast<char>(rit) << ".";
237 }
238
239 // Tack on the suffix and we're done.
240 stream << IPV6_REV_ZONE_SUFFIX;
241 return(stream.str());
242}
243
244const D2ParamsPtr&
245D2CfgMgr::getD2Params() {
246 return (getD2CfgContext()->getD2Params());
247}
248
249const isc::data::ConstElementPtr
250D2CfgMgr::getUnixControlSocketInfo() {
251 return (getD2CfgContext()->getUnixControlSocketInfo());
252}
253
254const isc::data::ConstElementPtr
255D2CfgMgr::getHttpControlSocketInfo() {
256 return (getD2CfgContext()->getHttpControlSocketInfo());
257}
258
259std::string
260D2CfgMgr::getConfigSummary(const uint32_t) {
261 return (getD2Params()->getConfigSummary());
262}
263
264void
265D2CfgMgr::setCfgDefaults(ElementPtr mutable_config) {
266 D2SimpleParser::setAllDefaults(mutable_config);
267}
268
269 isc::data::ConstElementPtr
270D2CfgMgr::parse(isc::data::ConstElementPtr config_set, bool check_only) {
271 // Do a sanity check first.
272 if (!config_set) {
273 isc_throw(D2CfgError, "Mandatory config parameter not provided");
274 }
275
276 D2CfgContextPtr ctx = getD2CfgContext();
277
278 // Set the defaults
279 ElementPtr cfg = boost::const_pointer_cast<Element>(config_set);
280 D2SimpleParser::setAllDefaults(cfg);
281
282 // And parse the configuration.
283 ConstElementPtr answer;
284 std::string excuse;
285 try {
286 // Do the actual parsing
287 D2SimpleParser parser;
288 parser.parse(ctx, cfg, check_only);
289 } catch (const isc::Exception& ex) {
290 excuse = ex.what();
291 answer = createAnswer(CONTROL_RESULT_ERROR, excuse);
292 } catch (...) {
293 excuse = "undefined configuration parsing error";
294 answer = createAnswer(CONTROL_RESULT_ERROR, excuse);
295 }
296
297 // At this stage the answer was created only in case of exception.
298 if (answer) {
299 if (check_only) {
300 LOG_ERROR(d2_logger, DHCP_DDNS_CONFIG_CHECK_FAIL).arg(excuse);
301 } else {
302 LOG_ERROR(d2_logger, DHCP_DDNS_CONFIG_FAIL).arg(excuse);
303 }
304 return (answer);
305 }
306
307 if (check_only) {
308 answer = createAnswer(CONTROL_RESULT_SUCCESS,
309 "Configuration check successful");
310 } else {
311
312 // Calculate hash of the configuration that was just set.
313 ConstElementPtr config = getContext()->toElement();
314 std::string hash = BaseCommandMgr::getHash(config);
315 ElementPtr params = Element::createMap();
316 params->set("hash", Element::create(hash));
317
318 answer = createAnswer(CONTROL_RESULT_SUCCESS,
319 "Configuration applied successfully.", params);
320 }
321
322 return (answer);
323}
324
325std::list<std::list<std::string>>
326D2CfgMgr::jsonPathsToRedact() const {
327 static std::list<std::list<std::string>> const list({
328 {"tsig-keys", "[]"},
329 {"hooks-libraries", "[]", "parameters", "*"},
330 });
331 return list;
332}
333
334} // namespace d2
335} // namespace isc
base_command_mgr.h
Element::create
static ElementPtr create(const Position &pos=ZERO_POSITION())
Create a NullElement.
Definition data.cc:299
Element::createMap
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:354
Element::createList
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:349
isc::Exception
This is a base class for exceptions thrown from the DNS library module.
Definition exceptions/exceptions.h:23
isc::Exception::what
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
Definition exceptions/exceptions.cc:32
isc::asiolink::IOAddress
The IOAddress class represents an IP addresses (version agnostic).
Definition io_address.h:53
isc::asiolink::IOAddress::toText
std::string toText() const
Convert the address to a string.
Definition io_address.cc:60
isc::asiolink::IOAddress::isV6
bool isV6() const
Convenience function to check for an IPv6 address.
Definition io_address.h:144
isc::asiolink::IOAddress::isV4
bool isV4() const
Convenience function to check for an IPv4 address.
Definition io_address.h:122
isc::asiolink::IOAddress::toBytes
std::vector< uint8_t > toBytes() const
Return address as set of bytes.
Definition io_address.cc:81
isc::config::BaseCommandMgr::getHash
static std::string getHash(const isc::data::ConstElementPtr &config)
returns a hash of a given Element structure
Definition base_command_mgr.cc:193
isc::d2::D2CfgContext
DHCP-DDNS Configuration Context.
Definition d2_cfg_mgr.h:35
isc::d2::D2CfgContext::~D2CfgContext
virtual ~D2CfgContext()
Destructor.
Definition d2_cfg_mgr.cc:63
isc::d2::D2CfgContext::toElement
virtual isc::data::ElementPtr toElement() const
Unparse a configuration object.
Definition d2_cfg_mgr.cc:67
isc::d2::D2CfgContext::D2CfgContext
D2CfgContext()
Constructor.
Definition d2_cfg_mgr.cc:33
isc::d2::D2CfgError
Exception thrown when the error during configuration handling occurs.
Definition d2_config.h:136
isc::d2::D2CfgMgr::~D2CfgMgr
virtual ~D2CfgMgr()
Destructor.
Definition d2_cfg_mgr.cc:137
isc::d2::D2CfgMgr::matchForward
bool matchForward(const std::string &fqdn, DdnsDomainPtr &domain)
Matches a given FQDN to a forward domain.
Definition d2_cfg_mgr.cc:158
isc::d2::D2CfgMgr::getHttpControlSocketInfo
const isc::data::ConstElementPtr getHttpControlSocketInfo()
Convenience method fetches information about HTTP/HTTPS control socket from context.
Definition d2_cfg_mgr.cc:255
isc::d2::D2CfgMgr::createNewContext
virtual process::ConfigPtr createNewContext() override
Creates an new, blank D2CfgContext context.
Definition d2_cfg_mgr.cc:141
isc::d2::D2CfgMgr::reverseIpAddress
static std::string reverseIpAddress(const std::string &address)
Generate a reverse order string for the given IP address.
Definition d2_cfg_mgr.cc:183
isc::d2::D2CfgMgr::getUnixControlSocketInfo
const isc::data::ConstElementPtr getUnixControlSocketInfo()
Convenience method fetches information about UNIX control socket from context.
Definition d2_cfg_mgr.cc:250
isc::d2::D2CfgMgr::getD2CfgContext
D2CfgContextPtr getD2CfgContext()
Convenience method that returns the D2 configuration context.
Definition d2_cfg_mgr.h:204
isc::d2::D2CfgMgr::reverseUpdatesEnabled
bool reverseUpdatesEnabled()
Returns whether or not reverse updates are enabled.
Definition d2_cfg_mgr.cc:152
isc::d2::D2CfgMgr::setCfgDefaults
virtual void setCfgDefaults(isc::data::ElementPtr mutable_config) override
Adds default values to the given config.
Definition d2_cfg_mgr.cc:265
isc::d2::D2CfgMgr::jsonPathsToRedact
std::list< std::list< std::string > > jsonPathsToRedact() const final override
Return a list of all paths that contain passwords or secrets.
Definition d2_cfg_mgr.cc:326
isc::d2::D2CfgMgr::D2CfgMgr
D2CfgMgr()
Constructor.
Definition d2_cfg_mgr.cc:134
isc::d2::D2CfgMgr::IPV6_REV_ZONE_SUFFIX
static const char * IPV6_REV_ZONE_SUFFIX
Reverse zone suffix added to IPv6 addresses for reverse lookups.
Definition d2_cfg_mgr.h:193
isc::d2::D2CfgMgr::reverseV4Address
static std::string reverseV4Address(const isc::asiolink::IOAddress &ioaddr)
Generate a reverse order string for the given IP address.
Definition d2_cfg_mgr.cc:201
isc::d2::D2CfgMgr::forwardUpdatesEnabled
bool forwardUpdatesEnabled()
Returns whether or not forward updates are enabled.
Definition d2_cfg_mgr.cc:146
isc::d2::D2CfgMgr::matchReverse
bool matchReverse(const std::string &ip_address, DdnsDomainPtr &domain)
Matches a given IP address to a reverse domain.
Definition d2_cfg_mgr.cc:172
isc::d2::D2CfgMgr::getConfigSummary
virtual std::string getConfigSummary(const uint32_t selection) override
Returns configuration summary in the textual format.
Definition d2_cfg_mgr.cc:260
isc::d2::D2CfgMgr::reverseV6Address
static std::string reverseV6Address(const isc::asiolink::IOAddress &ioaddr)
Generate a reverse order string for the given IP address.
Definition d2_cfg_mgr.cc:223
isc::d2::D2CfgMgr::getD2Params
const D2ParamsPtr & getD2Params()
Convenience method fetches the D2Params from context.
Definition d2_cfg_mgr.cc:245
isc::d2::D2CfgMgr::parse
virtual isc::data::ConstElementPtr parse(isc::data::ConstElementPtr config, bool check_only) override
Parses configuration of the D2.
Definition d2_cfg_mgr.cc:270
isc::d2::D2CfgMgr::IPV4_REV_ZONE_SUFFIX
static const char * IPV4_REV_ZONE_SUFFIX
Reverse zone suffix added to IPv4 addresses for reverse lookups.
Definition d2_cfg_mgr.h:188
isc::d2::D2Params
Acts as a storage vault for D2 global scalar parameters.
Definition d2_config.h:143
isc::d2::D2SimpleParser
Definition d2_simple_parser.h:22
isc::d2::D2SimpleParser::parse
void parse(const D2CfgContextPtr &ctx, const isc::data::ConstElementPtr &config, bool check_only)
Parses the whole D2 configuration.
Definition d2_simple_parser.cc:204
isc::d2::D2SimpleParser::setAllDefaults
static size_t setAllDefaults(data::ElementPtr global)
Sets all defaults for D2 configuration.
Definition d2_simple_parser.cc:127
isc::d2::DdnsDomainListMgr
Provides storage for and management of a list of DNS domains.
Definition d2_config.h:646
isc::process::ConfigBase
Base class for all configurations.
Definition config_base.h:33
isc::process::ConfigBase::toElement
virtual isc::data::ElementPtr toElement() const
Converts to Element representation.
Definition config_base.cc:118
isc::process::DCfgMgrBase::DCfgMgrBase
DCfgMgrBase(ConfigPtr context)
Constructor.
Definition d_cfg_mgr.cc:37
isc::process::DCfgMgrBase::getContext
ConfigPtr & getContext()
Fetches the configuration context.
Definition d_cfg_mgr.h:148
command_interpreter.h
This file contains several functions and constants that are used for handling commands and responses ...
d2_cfg_mgr.h
if
if(!(yy_init))
Definition d2_lexer.cc:1515
d2_log.h
d2_simple_parser.h
encode.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition exceptions/exceptions.h:210
LOG_ERROR
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition macros.h:32
isc::asiolink
Definition addr_utilities.cc:170
isc::config
Definition command_interpreter.cc:23
isc::config::CONTROL_RESULT_ERROR
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
Definition command_interpreter.h:45
isc::config::createAnswer
ConstElementPtr createAnswer()
Creates a standard config/command level success answer message (i.e.
Definition command_interpreter.cc:54
isc::config::CONTROL_RESULT_SUCCESS
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
Definition command_interpreter.h:42
isc::d2
Definition check_exists_add.cc:19
isc::d2::DdnsDomainListMgrPtr
boost::shared_ptr< DdnsDomainListMgr > DdnsDomainListMgrPtr
Defines a pointer for DdnsDomain instances.
Definition d2_cfg_mgr.h:175
isc::d2::DdnsDomainPtr
boost::shared_ptr< DdnsDomain > DdnsDomainPtr
Defines a pointer for DdnsDomain instances.
Definition d2_config.h:624
isc::d2::DHCP_DDNS_CONFIG_CHECK_FAIL
const isc::log::MessageID DHCP_DDNS_CONFIG_CHECK_FAIL
Definition d2_messages.h:17
isc::d2::TSIGKeyInfoMap
std::map< std::string, TSIGKeyInfoPtr > TSIGKeyInfoMap
Defines a map of TSIGKeyInfos, keyed by the name.
Definition d2_config.h:419
isc::d2::D2CfgContextPtr
boost::shared_ptr< D2CfgContext > D2CfgContextPtr
Pointer to a configuration context.
Definition d2_cfg_mgr.h:26
isc::d2::d2_logger
isc::log::Logger d2_logger("dhcpddns")
Defines the logger used within D2.
Definition d2_log.h:18
isc::d2::D2ParamsPtr
boost::shared_ptr< D2Params > D2ParamsPtr
Defines a pointer for D2Params instances.
Definition d2_config.h:257
isc::d2::DHCP_DDNS_CONFIG_FAIL
const isc::log::MessageID DHCP_DDNS_CONFIG_FAIL
Definition d2_messages.h:18
isc::data
Definition base_stamped_element.cc:12
isc::data::ConstElementPtr
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:30
isc::data::isNull
bool isNull(ConstElementPtr p)
Checks whether the given ElementPtr is a null pointer.
Definition data.cc:1230
isc::data::ElementPtr
boost::shared_ptr< Element > ElementPtr
Definition data.h:29
isc::dhcp_ddns::NameChangeFormat
NameChangeFormat
Defines the list of data wire formats supported.
Definition ncr_msg.h:59
isc::dhcp_ddns::NameChangeProtocol
NameChangeProtocol
Defines the list of socket protocols supported.
Definition ncr_io.h:69
isc::dhcp_ddns::ncrProtocolToString
std::string ncrProtocolToString(NameChangeProtocol protocol)
Function which converts NameChangeProtocol enums to text labels.
Definition ncr_io.cc:36
isc::dhcp_ddns::ncrFormatToString
std::string ncrFormatToString(NameChangeFormat format)
Function which converts NameChangeFormat enums to text labels.
Definition ncr_msg.cc:32
isc::process
Definition cb_ctl_base.h:22
isc::process::ConfigPtr
boost::shared_ptr< ConfigBase > ConfigPtr
Non-const pointer to the ConfigBase.
Definition config_base.h:176
isc::util::encode::encodeHex
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 format.
Definition encode.cc:361
isc
Defines the logger used by the top-level component of kea-lfc.
Definition check_exists_add.cc:18
isc::data::UserContext::contextToElement
void contextToElement(data::ElementPtr map) const
Merge unparse a user_context object.
Definition user_context.cc:15
isc::data::UserContext::toElement
static data::ElementPtr toElement(data::ConstElementPtr map)
Copy an Element map.
Definition user_context.cc:24