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