Kea  1.5.0
d2_simple_parser.cc
Go to the documentation of this file.
1 // Copyright (C) 2017-2018 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 <d2/d2_config.h>
8 #include <d2/d2_simple_parser.h>
9 #include <cc/data.h>
10 #include <boost/foreach.hpp>
11 
12 using namespace isc::data;
13 using namespace isc::d2;
14 using namespace isc;
15 
16 namespace {
17 
19 getProtocol(ConstElementPtr map, const std::string& name) {
20  ConstElementPtr value = map->get(name);
21  if (!value) {
22  isc_throw(D2CfgError, "Mandatory parameter " << name
23  << " not found (" << map->getPosition() << ")");
24  }
25  std::string str = value->stringValue();
26  try {
27  return (dhcp_ddns::stringToNcrProtocol(str));
28  } catch (const std::exception& ex) {
30  "invalid NameChangeRequest protocol (" << str
31  << ") specified for parameter '" << name
32  << "' (" << value->getPosition() << ")");
33  }
34 }
35 
37 getFormat(ConstElementPtr map, const std::string& name) {
38  ConstElementPtr value = map->get(name);
39  if (!value) {
40  isc_throw(D2CfgError, "Mandatory parameter " << name
41  << " not found (" << map->getPosition() << ")");
42  }
43  std::string str = value->stringValue();
44  try {
45  return (dhcp_ddns::stringToNcrFormat(str));
46  } catch (const std::exception& ex) {
48  "invalid NameChangeRequest format (" << str
49  << ") specified for parameter '" << name
50  << "' (" << value->getPosition() << ")");
51  }
52 }
53 
54 } // anon
55 
56 namespace isc {
57 namespace d2 {
72 
78 const SimpleDefaults D2SimpleParser::D2_GLOBAL_DEFAULTS = {
79  { "ip-address", Element::string, "127.0.0.1" },
80  { "port", Element::integer, "53001" },
81  { "dns-server-timeout", Element::integer, "100" }, // in seconds
82  { "ncr-protocol", Element::string, "UDP" },
83  { "ncr-format", Element::string, "JSON" }
84 };
85 
87 const SimpleDefaults D2SimpleParser::TSIG_KEY_DEFAULTS = {
88  { "digest-bits", Element::integer, "0" }
89 };
90 
97 const SimpleDefaults D2SimpleParser::DDNS_DOMAIN_MGR_DEFAULTS = {
98 };
99 
101 const SimpleDefaults D2SimpleParser::DDNS_DOMAIN_DEFAULTS = {
102  { "key-name", Element::string, "" }
103 };
104 
106 const SimpleDefaults D2SimpleParser::DNS_SERVER_DEFAULTS = {
107  { "hostname", Element::string, "" },
108  { "port", Element::integer, "53" },
109 };
110 
112 
116 
117 size_t
118 D2SimpleParser::setAllDefaults(isc::data::ElementPtr global) {
119  size_t cnt = 0;
120  // Set global defaults first.
121  cnt = setDefaults(global, D2_GLOBAL_DEFAULTS);
122 
123  // If the key list is present, set its members' defaults
124  if (global->find("tsig-keys")) {
125  ConstElementPtr keys = global->get("tsig-keys");
126  cnt += setListDefaults(keys, TSIG_KEY_DEFAULTS);
127  } else {
128  // Not present, so add an empty list.
129  ConstElementPtr list(new ListElement());
130  global->set("tsig-keys", list);
131  cnt++;
132  }
133 
134  // Set the forward domain manager defaults.
135  cnt += setManagerDefaults(global, "forward-ddns", DDNS_DOMAIN_MGR_DEFAULTS);
136 
137  // Set the reverse domain manager defaults.
138  cnt += setManagerDefaults(global, "reverse-ddns", DDNS_DOMAIN_MGR_DEFAULTS);
139  return (cnt);
140 }
141 
142 size_t
143 D2SimpleParser::setDdnsDomainDefaults(ElementPtr domain,
144  const SimpleDefaults& domain_defaults) {
145  size_t cnt = 0;
146 
147  // Set the domain's scalar defaults
148  cnt += setDefaults(domain, domain_defaults);
149  if (domain->find("dns-servers")) {
150  // Now add the defaults to its server list.
151  ConstElementPtr servers = domain->get("dns-servers");
152  cnt += setListDefaults(servers, DNS_SERVER_DEFAULTS);
153  }
154 
155  return (cnt);
156 }
157 
158 
159 size_t
160 D2SimpleParser::setManagerDefaults(ElementPtr global,
161  const std::string& mgr_name,
162  const SimpleDefaults& mgr_defaults) {
163  size_t cnt = 0;
164 
165  if (!global->find(mgr_name)) {
166  // If it's not present, then default is an empty map
167  ConstElementPtr map(new MapElement());
168  global->set(mgr_name, map);
169  ++cnt;
170  } else {
171  // Get a writable copy of the manager element map
172  ElementPtr mgr =
173  boost::const_pointer_cast<Element>(global->get(mgr_name));
174 
175  // Set the manager's scalar defaults first
176  cnt += setDefaults(mgr, mgr_defaults);
177 
178  // Get the domain list and set defaults for them.
179  // The domain list may not be present ddns for this
180  // manager is disabled.
181  if (mgr->find("ddns-domains")) {
182  ConstElementPtr domains = mgr->get("ddns-domains");
183  BOOST_FOREACH(ElementPtr domain, domains->listValue()) {
184  // Set the domain's defaults. We can't use setListDefaults()
185  // as this does not handle sub-lists or maps, like server list.
186  cnt += setDdnsDomainDefaults(domain, DDNS_DOMAIN_DEFAULTS);
187  }
188  }
189 
190  }
191 
192  return (cnt);
193 }
194 
195 void D2SimpleParser::parse(const D2CfgContextPtr& ctx,
196  const isc::data::ConstElementPtr& config,
197  bool /*check_only*/) {
198  // TSIG keys need to parse before the Domains, so we can catch Domains
199  // that specify undefined keys. Create the necessary parsing order now.
200  // addToParseOrder("tsig-keys");
201  // addToParseOrder("forward-ddns");
202  // addToParseOrder("reverse-ddns");
203 
204  ConstElementPtr keys = config->get("tsig-keys");
205  if (keys) {
206  TSIGKeyInfoListParser parser;
207  ctx->setKeys(parser.parse(keys));
208  }
209 
210  ConstElementPtr fwd = config->get("forward-ddns");
211  if (fwd) {
213  DdnsDomainListMgrPtr mgr = parser.parse(fwd, "forward-ddns",
214  ctx->getKeys());
215  ctx->setForwardMgr(mgr);
216  }
217 
218  ConstElementPtr rev = config->get("reverse-ddns");
219  if (rev) {
221  DdnsDomainListMgrPtr mgr = parser.parse(rev, "reverse-ddns",
222  ctx->getKeys());
223  ctx->setReverseMgr(mgr);
224  }
225 
226  // Fetch the parameters in the config, performing any logical
227  // validation required.
228  asiolink::IOAddress ip_address(0);
229  uint32_t port = 0;
230  uint32_t dns_server_timeout = 0;
233 
234  ip_address = SimpleParser::getAddress(config, "ip-address");
235 
236  if ((ip_address.toText() == "0.0.0.0") ||
237  (ip_address.toText() == "::")) {
238  isc_throw(D2CfgError, "IP address cannot be \""
239  << ip_address << "\""
240  << " (" << config->get("ip-address")->getPosition() << ")");
241  }
242 
243  port = SimpleParser::getUint32(config, "port");
244 
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  // Attempt to create the new client config. This ought to fly as
269  // we already validated everything.
270  D2ParamsPtr params(new D2Params(ip_address, port, dns_server_timeout,
271  ncr_protocol, ncr_format));
272 
273  ctx->getD2Params() = params;
274 }
275 
276 
277 };
278 };
isc::d2
Definition: d2_cfg_mgr.cc:23
isc::data::ListElement
Definition: data.h:613
isc::d2::D2Params
Acts as a storage vault for D2 global scalar parameters.
Definition: d2_config.h:137
isc::d2::DdnsDomainListMgrPtr
boost::shared_ptr< DdnsDomainListMgr > DdnsDomainListMgrPtr
Defines a pointer for DdnsDomain instances.
Definition: d2_cfg_mgr.h:120
isc::data::SimpleParser::getAddress
static isc::asiolink::IOAddress getAddress(const ConstElementPtr &scope, const std::string &name)
Returns a IOAddress parameter from a scope.
Definition: lib/cc/simple_parser.cc:75
isc::data::MapElement
Definition: data.h:646
isc::d2::DdnsDomainListMgrParser::parse
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:624
isc::data::SimpleDefaults
std::vector< SimpleDefault > SimpleDefaults
This specifies all default values in a given scope (e.g. a subnet)
Definition: lib/cc/simple_parser.h:31
isc::d2::DdnsDomainListMgrParser
Parser for DdnsDomainListMgr.
Definition: d2_config.h:871
isc::data
Definition: cfg_to_element.h:25
isc::d2::D2CfgError
Exception thrown when the error during configuration handling occurs.
Definition: d2_config.h:130
isc
Defines the logger used by the top-level component of kea-dhcp-ddns.
Definition: agent_parser.cc:144
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition: exceptions/exceptions.h:192
isc::d2::TSIGKeyInfoListParser::parse
TSIGKeyInfoMapPtr parse(data::ConstElementPtr key_list_config)
Performs the parsing of the given list "tsig-key" elements.
Definition: d2_config.cc:456
isc::d2::D2ParamsPtr
boost::shared_ptr< D2Params > D2ParamsPtr
Defines a pointer for D2Params instances.
Definition: d2_config.h:251
isc::dhcp_ddns::FMT_JSON
@ FMT_JSON
Definition: ncr_msg.h:61
d2_config.h
A collection of classes for housing and parsing the application configuration necessary for the DHCP-...
isc::dhcp_ddns::NCR_UDP
@ NCR_UDP
Definition: ncr_io.h:67
isc::data::SimpleParser::getUint32
uint32_t getUint32(isc::data::ConstElementPtr scope, const std::string &name)
Returns a value converted to uint32_t.
Definition: lib/cc/simple_parser.h:231
isc::dhcp_ddns::stringToNcrFormat
NameChangeFormat stringToNcrFormat(const std::string &fmt_str)
Function which converts labels to NameChangeFormat enum values.
Definition: ncr_msg.cc:27
isc::dhcp_ddns::ncrProtocolToString
std::string ncrProtocolToString(NameChangeProtocol protocol)
Function which converts NameChangeProtocol enums to text labels.
Definition: ncr_io.cc:30
isc::data::Element::string
@ string
Definition: data.h:151
data.h
isc::d2::TSIGKeyInfoListParser
Parser for a list of TSIGKeyInfos.
Definition: d2_config.h:764
isc::data::Element::integer
@ integer
Definition: data.h:151
isc::data::ElementPtr
boost::shared_ptr< Element > ElementPtr
Definition: data.h:20
isc::data::ConstElementPtr
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
isc::d2::D2CfgContextPtr
boost::shared_ptr< D2CfgContext > D2CfgContextPtr
Pointer to a configuration context.
Definition: d2_cfg_mgr.h:22
d2_simple_parser.h
isc::dhcp_ddns::ncrFormatToString
std::string ncrFormatToString(NameChangeFormat format)
Function which converts NameChangeFormat enums to text labels.
Definition: ncr_msg.cc:36
isc::dhcp_ddns::stringToNcrProtocol
NameChangeProtocol stringToNcrProtocol(const std::string &protocol_str)
Function which converts labels to NameChangeProtocol enum values.
Definition: ncr_io.cc:17
isc::dhcp_ddns::NameChangeFormat
NameChangeFormat
Defines the list of data wire formats supported.
Definition: ncr_msg.h:60
isc::dhcp_ddns::NameChangeProtocol
NameChangeProtocol
Defines the list of socket protocols supported.
Definition: ncr_io.h:66