Kea 2.7.6
d2_simple_parser.cc
Go to the documentation of this file.
1// Copyright (C) 2017-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
10#include <d2srv/d2_config.h>
12#include <cc/data.h>
15#include <hooks/hooks_manager.h>
16#include <hooks/hooks_parser.h>
17
18using namespace isc::asiolink;
19using namespace isc::config;
20using namespace isc::data;
21using namespace isc::d2;
22using namespace isc;
23
24namespace {
25
27getProtocol(ConstElementPtr map, const std::string& name) {
28 ConstElementPtr value = map->get(name);
29 if (!value) {
30 isc_throw(D2CfgError, "Mandatory parameter " << name
31 << " not found (" << map->getPosition() << ")");
32 }
33 std::string str = value->stringValue();
34 try {
36 } catch (const std::exception& ex) {
38 "invalid NameChangeRequest protocol (" << str
39 << ") specified for parameter '" << name
40 << "' (" << value->getPosition() << ")");
41 }
42}
43
45getFormat(ConstElementPtr map, const std::string& name) {
46 ConstElementPtr value = map->get(name);
47 if (!value) {
48 isc_throw(D2CfgError, "Mandatory parameter " << name
49 << " not found (" << map->getPosition() << ")");
50 }
51 std::string str = value->stringValue();
52 try {
53 return (dhcp_ddns::stringToNcrFormat(str));
54 } catch (const std::exception& ex) {
56 "invalid NameChangeRequest format (" << str
57 << ") specified for parameter '" << name
58 << "' (" << value->getPosition() << ")");
59 }
60}
61
62} // anon
63
64namespace isc {
65namespace d2 {
80
87 { "ip-address", Element::string, "127.0.0.1" },
88 { "port", Element::integer, "53001" },
89 { "dns-server-timeout", Element::integer, "500" }, // in milliseconds
90 { "ncr-protocol", Element::string, "UDP" },
91 { "ncr-format", Element::string, "JSON" }
92};
93
96 { "digest-bits", Element::integer, "0" }
97};
98
106};
107
110 { "key-name", Element::string, "" }
111};
112
115 { "hostname", Element::string, "" },
116 { "port", Element::integer, "53" },
117 { "key-name", Element::string, "" }
118};
119
121
125
126size_t
128 size_t cnt = 0;
129 // Set global defaults first.
130 cnt = setDefaults(global, D2_GLOBAL_DEFAULTS);
131
132 // If the key list is present, set its members' defaults
133 if (global->find("tsig-keys")) {
134 ConstElementPtr keys = global->get("tsig-keys");
136 } else {
137 // Not present, so add an empty list.
138 ConstElementPtr list(new ListElement());
139 global->set("tsig-keys", list);
140 cnt++;
141 }
142
143 // Set the forward domain manager defaults.
144 cnt += setManagerDefaults(global, "forward-ddns", DDNS_DOMAIN_MGR_DEFAULTS);
145
146 // Set the reverse domain manager defaults.
147 cnt += setManagerDefaults(global, "reverse-ddns", DDNS_DOMAIN_MGR_DEFAULTS);
148 return (cnt);
149}
150
151size_t
153 const SimpleDefaults& domain_defaults) {
154 size_t cnt = 0;
155
156 // Set the domain's scalar defaults
157 cnt += setDefaults(domain, domain_defaults);
158 if (domain->find("dns-servers")) {
159 // Now add the defaults to its server list.
160 ConstElementPtr servers = domain->get("dns-servers");
161 cnt += setListDefaults(servers, DNS_SERVER_DEFAULTS);
162 }
163
164 return (cnt);
165}
166
167
168size_t
170 const std::string& mgr_name,
171 const SimpleDefaults& mgr_defaults) {
172 size_t cnt = 0;
173
174 if (!global->find(mgr_name)) {
175 // If it's not present, then default is an empty map
176 ConstElementPtr map(new MapElement());
177 global->set(mgr_name, map);
178 ++cnt;
179 } else {
180 // Get a writable copy of the manager element map
181 ElementPtr mgr =
182 boost::const_pointer_cast<Element>(global->get(mgr_name));
183
184 // Set the manager's scalar defaults first
185 cnt += setDefaults(mgr, mgr_defaults);
186
187 // Get the domain list and set defaults for them.
188 // The domain list may not be present ddns for this
189 // manager is disabled.
190 if (mgr->find("ddns-domains")) {
191 ConstElementPtr domains = mgr->get("ddns-domains");
192 for (auto const& domain : domains->listValue()) {
193 // Set the domain's defaults. We can't use setListDefaults()
194 // as this does not handle sub-lists or maps, like server list.
196 }
197 }
198
199 }
200
201 return (cnt);
202}
203
205 const isc::data::ConstElementPtr& config,
206 bool check_only) {
207 // TSIG keys need to parse before the Domains, so we can catch Domains
208 // that specify undefined keys. Create the necessary parsing order now.
209 // addToParseOrder("tsig-keys");
210 // addToParseOrder("forward-ddns");
211 // addToParseOrder("reverse-ddns");
212
213 ConstElementPtr keys = config->get("tsig-keys");
214 if (keys) {
216 ctx->setKeys(parser.parse(keys));
217 }
218
219 ConstElementPtr fwd = config->get("forward-ddns");
220 if (fwd) {
222 DdnsDomainListMgrPtr mgr = parser.parse(fwd, "forward-ddns",
223 ctx->getKeys());
224 ctx->setForwardMgr(mgr);
225 }
226
227 ConstElementPtr rev = config->get("reverse-ddns");
228 if (rev) {
230 DdnsDomainListMgrPtr mgr = parser.parse(rev, "reverse-ddns",
231 ctx->getKeys());
232 ctx->setReverseMgr(mgr);
233 }
234
235 // Fetch the parameters in the config, performing any logical
236 // validation required.
237 asiolink::IOAddress ip_address(0);
238 uint32_t port = 0;
239 uint32_t dns_server_timeout = 0;
242
243 ip_address = SimpleParser::getAddress(config, "ip-address");
244 port = SimpleParser::getUint32(config, "port");
245 dns_server_timeout = SimpleParser::getUint32(config, "dns-server-timeout");
246
247 ncr_protocol = getProtocol(config, "ncr-protocol");
248 if (ncr_protocol != dhcp_ddns::NCR_UDP) {
249 isc_throw(D2CfgError, "ncr-protocol : "
250 << dhcp_ddns::ncrProtocolToString(ncr_protocol)
251 << " is not yet supported ("
252 << config->get("ncr-protocol")->getPosition() << ")");
253 }
254
255 ncr_format = getFormat(config, "ncr-format");
256 if (ncr_format != dhcp_ddns::FMT_JSON) {
257 isc_throw(D2CfgError, "NCR Format:"
258 << dhcp_ddns::ncrFormatToString(ncr_format)
259 << " is not yet supported"
260 << " (" << config->get("ncr-format")->getPosition() << ")");
261 }
262
263 ConstElementPtr user = config->get("user-context");
264 if (user) {
265 ctx->setContext(user);
266 }
267
268 // Get control sockets.
269 ConstElementPtr control_sockets = config->get("control-sockets");
270 ConstElementPtr control_socket = config->get("control-socket");
271 if (control_socket) {
273 l->add(UserContext::toElement(control_socket));
274 control_sockets = l;
275 }
276 if (control_sockets) {
277 if (control_sockets->getType() != Element::list) {
278 // Sanity check: not supposed to fail.
280 "Specified control-sockets is expected to be a list");
281 }
282 bool seen_unix(false);
283 ElementPtr unix_config = Element::createList();
284 ElementPtr http_config = Element::createList();
285 for (ElementPtr socket : control_sockets->listValue()) {
286 if (socket->getType() != Element::map) {
287 // Sanity check: not supposed to fail.
289 "Specified control-sockets is expected to be a list of maps");
290 }
291 ConstElementPtr socket_type = socket->get("socket-type");
292 if (!socket_type) {
294 "'socket-type' parameter is mandatory in control-sockets items");
295 }
296 if (socket_type->getType() != Element::string) {
297 // Sanity check: not supposed to fail.
299 "'socket-type' parameter is expected to be a string");
300 }
301 std::string type = socket_type->stringValue();
302 if (type == "unix") {
303 if (seen_unix) {
305 "control socket of type 'unix' already configured");
306 }
307 UnixCommandConfig cmd_config(socket);
308 seen_unix = true;
309 unix_config->add(socket);
310 } else if ((type == "http") || (type == "https")) {
311 HttpCommandConfig cmd_config(socket);
312 http_config->add(socket);
313 } else {
314 // Sanity check: not supposed to fail.
316 "unsupported 'socket-type': '" << type
317 << "' not 'unix', 'http' or 'https'");
318 }
319 }
320 if (unix_config->size()) {
321 ctx->setUnixControlSocketInfo(unix_config);
322 }
323 if (http_config->size()) {
324 ctx->setHttpControlSocketInfo(http_config);
325 }
326 }
327
328 // Finally, let's get the hook libs!
329 using namespace isc::hooks;
330 HooksConfig& libraries = ctx->getHooksConfig();
331 ConstElementPtr hooks = config->get("hooks-libraries");
332 if (hooks) {
333 HooksLibrariesParser hooks_parser;
334 hooks_parser.parse(libraries, hooks);
335 libraries.verifyLibraries(hooks->getPosition(), false);
336 }
337
338 // Attempt to create the new client config. This ought to fly as
339 // we already validated everything.
340 D2ParamsPtr params(new D2Params(ip_address, port, dns_server_timeout,
341 ncr_protocol, ncr_format));
342
343 ctx->getD2Params() = params;
344
345 if (!check_only) {
346 // This occurs last as if it succeeds, there is no easy way
347 // revert it. As a result, the failure to commit a subsequent
348 // change causes problems when trying to roll back.
349 HooksManager::prepareUnloadLibraries();
350 static_cast<void>(HooksManager::unloadLibraries());
352 libraries.loadLibraries(false);
353 }
354}
355
356}
357}
HTTP command config aka HTTP control socket info class.
UNIX command config aka UNIX control socket info class.
Exception thrown when the error during configuration handling occurs.
Definition d2_config.h:136
Acts as a storage vault for D2 global scalar parameters.
Definition d2_config.h:143
static const data::SimpleDefaults D2_GLOBAL_DEFAULTS
This table defines default global values for D2.
static size_t setManagerDefaults(data::ElementPtr global, const std::string &mgr_name, const data::SimpleDefaults &mgr_defaults)
Adds default values to a DDNS Domain List Manager.
static const data::SimpleDefaults TSIG_KEY_DEFAULTS
Supplies defaults for ddns-domains list elements (i.e. DdnsDomains)
static size_t setDdnsDomainDefaults(data::ElementPtr domain, const data::SimpleDefaults &domain_defaults)
Adds default values to a DDNS Domain element.
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.
static const data::SimpleDefaults DNS_SERVER_DEFAULTS
Supplies defaults for optional values DdnsDomain entries.
static const data::SimpleDefaults DDNS_DOMAIN_MGR_DEFAULTS
Supplies defaults for optional values in DDNS domain managers (e.g.
static const data::SimpleDefaults DDNS_DOMAIN_DEFAULTS
Supplies defaults for ddns-domains list elements (i.e. DdnsDomains)
Parser for DdnsDomainListMgr.
Definition d2_config.h:917
DdnsDomainListMgrPtr parse(data::ConstElementPtr mgr_config, const std::string &mgr_name, const TSIGKeyInfoMapPtr keys)
Performs the actual parsing of the given manager element.
Definition d2_config.cc:667
Parser for a list of TSIGKeyInfos.
Definition d2_config.h:802
TSIGKeyInfoMapPtr parse(data::ConstElementPtr key_list_config)
Performs the parsing of the given list "tsig-key" elements.
Definition d2_config.cc:478
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:299
static size_t setListDefaults(isc::data::ConstElementPtr list, const SimpleDefaults &default_values)
Sets the default values for all entries in a list.
static isc::asiolink::IOAddress getAddress(const ConstElementPtr &scope, const std::string &name)
Returns a IOAddress parameter from a scope.
uint32_t getUint32(isc::data::ConstElementPtr scope, const std::string &name)
Returns a value converted to uint32_t.
static size_t setDefaults(isc::data::ElementPtr scope, const SimpleDefaults &default_values)
Sets the default values.
Wrapper class that holds hooks libraries configuration.
const isc::hooks::HookLibsCollection & get() const
Provides access to the configured hooks libraries.
void verifyLibraries(const isc::data::Element::Position &position, bool multi_threading_enabled) const
Verifies that libraries stored in libraries_ are valid.
void loadLibraries(bool multi_threading_enabled) const
Commits hooks libraries configuration.
Parser for hooks library list.
void parse(HooksConfig &libraries, isc::data::ConstElementPtr value)
Parses parameters value.
A collection of classes for housing and parsing the application configuration necessary for the DHCP-...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< DdnsDomainListMgr > DdnsDomainListMgrPtr
Defines a pointer for DdnsDomain instances.
Definition d2_cfg_mgr.h:175
boost::shared_ptr< D2CfgContext > D2CfgContextPtr
Pointer to a configuration context.
Definition d2_cfg_mgr.h:26
boost::shared_ptr< D2Params > D2ParamsPtr
Defines a pointer for D2Params instances.
Definition d2_config.h:257
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:29
std::vector< SimpleDefault > SimpleDefaults
This specifies all default values in a given scope (e.g. a subnet).
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
NameChangeProtocol stringToNcrProtocol(const std::string &protocol_str)
Function which converts text labels to NameChangeProtocol enums.
Definition ncr_io.cc:23
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
NameChangeFormat stringToNcrFormat(const std::string &fmt_str)
Function which converts labels to NameChangeFormat enum values.
Definition ncr_msg.cc:26
std::string ncrFormatToString(NameChangeFormat format)
Function which converts NameChangeFormat enums to text labels.
Definition ncr_msg.cc:35
Defines the logger used by the top-level component of kea-lfc.
static data::ElementPtr toElement(data::ConstElementPtr map)
Copy an Element map.