Kea 2.7.5
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>
13#include <hooks/hooks_manager.h>
14#include <hooks/hooks_parser.h>
15
16using namespace isc::asiolink;
17using namespace isc::data;
18using namespace isc::d2;
19using namespace isc;
20
21namespace {
22
24getProtocol(ConstElementPtr map, const std::string& name) {
25 ConstElementPtr value = map->get(name);
26 if (!value) {
27 isc_throw(D2CfgError, "Mandatory parameter " << name
28 << " not found (" << map->getPosition() << ")");
29 }
30 std::string str = value->stringValue();
31 try {
33 } catch (const std::exception& ex) {
35 "invalid NameChangeRequest protocol (" << str
36 << ") specified for parameter '" << name
37 << "' (" << value->getPosition() << ")");
38 }
39}
40
42getFormat(ConstElementPtr map, const std::string& name) {
43 ConstElementPtr value = map->get(name);
44 if (!value) {
45 isc_throw(D2CfgError, "Mandatory parameter " << name
46 << " not found (" << map->getPosition() << ")");
47 }
48 std::string str = value->stringValue();
49 try {
50 return (dhcp_ddns::stringToNcrFormat(str));
51 } catch (const std::exception& ex) {
53 "invalid NameChangeRequest format (" << str
54 << ") specified for parameter '" << name
55 << "' (" << value->getPosition() << ")");
56 }
57}
58
59} // anon
60
61namespace isc {
62namespace d2 {
77
84 { "ip-address", Element::string, "127.0.0.1" },
85 { "port", Element::integer, "53001" },
86 { "dns-server-timeout", Element::integer, "500" }, // in milliseconds
87 { "ncr-protocol", Element::string, "UDP" },
88 { "ncr-format", Element::string, "JSON" }
89};
90
93 { "digest-bits", Element::integer, "0" }
94};
95
103};
104
107 { "key-name", Element::string, "" }
108};
109
112 { "hostname", Element::string, "" },
113 { "port", Element::integer, "53" },
114 { "key-name", Element::string, "" }
115};
116
118
122
123size_t
125 size_t cnt = 0;
126 // Set global defaults first.
127 cnt = setDefaults(global, D2_GLOBAL_DEFAULTS);
128
129 // If the key list is present, set its members' defaults
130 if (global->find("tsig-keys")) {
131 ConstElementPtr keys = global->get("tsig-keys");
133 } else {
134 // Not present, so add an empty list.
135 ConstElementPtr list(new ListElement());
136 global->set("tsig-keys", list);
137 cnt++;
138 }
139
140 // Set the forward domain manager defaults.
141 cnt += setManagerDefaults(global, "forward-ddns", DDNS_DOMAIN_MGR_DEFAULTS);
142
143 // Set the reverse domain manager defaults.
144 cnt += setManagerDefaults(global, "reverse-ddns", DDNS_DOMAIN_MGR_DEFAULTS);
145 return (cnt);
146}
147
148size_t
150 const SimpleDefaults& domain_defaults) {
151 size_t cnt = 0;
152
153 // Set the domain's scalar defaults
154 cnt += setDefaults(domain, domain_defaults);
155 if (domain->find("dns-servers")) {
156 // Now add the defaults to its server list.
157 ConstElementPtr servers = domain->get("dns-servers");
158 cnt += setListDefaults(servers, DNS_SERVER_DEFAULTS);
159 }
160
161 return (cnt);
162}
163
164
165size_t
167 const std::string& mgr_name,
168 const SimpleDefaults& mgr_defaults) {
169 size_t cnt = 0;
170
171 if (!global->find(mgr_name)) {
172 // If it's not present, then default is an empty map
173 ConstElementPtr map(new MapElement());
174 global->set(mgr_name, map);
175 ++cnt;
176 } else {
177 // Get a writable copy of the manager element map
178 ElementPtr mgr =
179 boost::const_pointer_cast<Element>(global->get(mgr_name));
180
181 // Set the manager's scalar defaults first
182 cnt += setDefaults(mgr, mgr_defaults);
183
184 // Get the domain list and set defaults for them.
185 // The domain list may not be present ddns for this
186 // manager is disabled.
187 if (mgr->find("ddns-domains")) {
188 ConstElementPtr domains = mgr->get("ddns-domains");
189 for (auto const& domain : domains->listValue()) {
190 // Set the domain's defaults. We can't use setListDefaults()
191 // as this does not handle sub-lists or maps, like server list.
193 }
194 }
195
196 }
197
198 return (cnt);
199}
200
202 const isc::data::ConstElementPtr& config,
203 bool check_only) {
204 // TSIG keys need to parse before the Domains, so we can catch Domains
205 // that specify undefined keys. Create the necessary parsing order now.
206 // addToParseOrder("tsig-keys");
207 // addToParseOrder("forward-ddns");
208 // addToParseOrder("reverse-ddns");
209
210 ConstElementPtr keys = config->get("tsig-keys");
211 if (keys) {
213 ctx->setKeys(parser.parse(keys));
214 }
215
216 ConstElementPtr fwd = config->get("forward-ddns");
217 if (fwd) {
219 DdnsDomainListMgrPtr mgr = parser.parse(fwd, "forward-ddns",
220 ctx->getKeys());
221 ctx->setForwardMgr(mgr);
222 }
223
224 ConstElementPtr rev = config->get("reverse-ddns");
225 if (rev) {
227 DdnsDomainListMgrPtr mgr = parser.parse(rev, "reverse-ddns",
228 ctx->getKeys());
229 ctx->setReverseMgr(mgr);
230 }
231
232 // Fetch the parameters in the config, performing any logical
233 // validation required.
234 asiolink::IOAddress ip_address(0);
235 uint32_t port = 0;
236 uint32_t dns_server_timeout = 0;
239
240 ip_address = SimpleParser::getAddress(config, "ip-address");
241 port = SimpleParser::getUint32(config, "port");
242 dns_server_timeout = SimpleParser::getUint32(config, "dns-server-timeout");
243
244 ncr_protocol = getProtocol(config, "ncr-protocol");
245 if (ncr_protocol != dhcp_ddns::NCR_UDP) {
246 isc_throw(D2CfgError, "ncr-protocol : "
247 << dhcp_ddns::ncrProtocolToString(ncr_protocol)
248 << " is not yet supported ("
249 << config->get("ncr-protocol")->getPosition() << ")");
250 }
251
252 ncr_format = getFormat(config, "ncr-format");
253 if (ncr_format != dhcp_ddns::FMT_JSON) {
254 isc_throw(D2CfgError, "NCR Format:"
255 << dhcp_ddns::ncrFormatToString(ncr_format)
256 << " is not yet supported"
257 << " (" << config->get("ncr-format")->getPosition() << ")");
258 }
259
260 ConstElementPtr user = config->get("user-context");
261 if (user) {
262 ctx->setContext(user);
263 }
264
265 // Get control sockets.
266 ConstElementPtr control_sockets = config->get("control-sockets");
267 ConstElementPtr control_socket = config->get("control-socket");
268 if (control_socket) {
270 l->add(UserContext::toElement(control_socket));
271 control_sockets = l;
272 }
273 if (control_sockets) {
274 if (control_sockets->getType() != Element::list) {
275 // Sanity check: not supposed to fail.
277 "Specified control-sockets is expected to be a list");
278 }
279 bool seen_unix(false);
280 bool seen_http(false);
281 for (ConstElementPtr socket : control_sockets->listValue()) {
282 if (socket->getType() != Element::map) {
283 // Sanity check: not supposed to fail.
285 "Specified control-sockets is expected to be a list of maps");
286 }
287 ConstElementPtr socket_type = socket->get("socket-type");
288 if (!socket_type) {
290 "'socket-type' parameter is mandatory in control-sockets items");
291 }
292 if (socket_type->getType() != Element::string) {
293 // Sanity check: not supposed to fail.
295 "'socket-type' parameter is expected to be a string");
296 }
297 std::string type = socket_type->stringValue();
298 if (type == "unix") {
299 if (seen_unix) {
301 "control socket of type 'unix' already configured");
302 }
303 seen_unix = true;
304 ctx->setUnixControlSocketInfo(socket);
305 } else if ((type == "http") || (type == "https")) {
306 if (seen_http) {
308 "control socket of type 'http' or 'https'"
309 " already configured");
310 }
311 seen_http = true;
312 using namespace isc::config;
313 HttpCommandConfigPtr http_config(new HttpCommandConfig(socket));
314 ctx->setHttpControlSocketInfo(http_config);
315 } else {
316 // Sanity check: not supposed to fail.
318 "unsupported 'socket-type': '" << type
319 << "' not 'unix', 'http' or 'https'");
320 }
321 }
322 }
323
324 // Finally, let's get the hook libs!
325 using namespace isc::hooks;
326 HooksConfig& libraries = ctx->getHooksConfig();
327 ConstElementPtr hooks = config->get("hooks-libraries");
328 if (hooks) {
329 HooksLibrariesParser hooks_parser;
330 hooks_parser.parse(libraries, hooks);
331 libraries.verifyLibraries(hooks->getPosition(), false);
332 }
333
334 // Attempt to create the new client config. This ought to fly as
335 // we already validated everything.
336 D2ParamsPtr params(new D2Params(ip_address, port, dns_server_timeout,
337 ncr_protocol, ncr_format));
338
339 ctx->getD2Params() = params;
340
341 if (!check_only) {
342 // This occurs last as if it succeeds, there is no easy way
343 // revert it. As a result, the failure to commit a subsequent
344 // change causes problems when trying to roll back.
345 HooksManager::prepareUnloadLibraries();
346 static_cast<void>(HooksManager::unloadLibraries());
347 IOServiceMgr::instance().clearIOServices();
348 libraries.loadLibraries(false);
349 }
350}
351
352}
353}
HTTP command config aka HTTP 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.
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< HttpCommandConfig > HttpCommandConfigPtr
Pointer to a HttpCommandConfig object.
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.