Kea  2.3.2-git
dhcp_parsers.cc
Go to the documentation of this file.
1 // Copyright (C) 2013-2022 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 #include <dhcp/iface_mgr.h>
9 #include <dhcp/dhcp4.h>
10 #include <dhcp/libdhcp++.h>
11 #include <dhcpsrv/cfgmgr.h>
12 #include <dhcpsrv/cfg_option.h>
13 #include <dhcpsrv/dhcpsrv_log.h>
20 #include <dhcpsrv/cfg_mac_source.h>
21 #include <util/encode/hex.h>
22 #include <util/strutil.h>
23 
24 #include <boost/algorithm/string.hpp>
25 #include <boost/foreach.hpp>
26 #include <boost/lexical_cast.hpp>
27 #include <boost/make_shared.hpp>
28 #include <boost/scoped_ptr.hpp>
29 
30 #include <map>
31 #include <string>
32 #include <vector>
33 #include <iomanip>
34 
35 using namespace std;
36 using namespace isc::asiolink;
37 using namespace isc::data;
38 using namespace isc::util;
39 
40 namespace isc {
41 namespace dhcp {
42 
43 // ******************** MACSourcesListConfigParser *************************
44 
45 void
46 MACSourcesListConfigParser::parse(CfgMACSource& mac_sources, ConstElementPtr value) {
47  uint32_t source = 0;
48  size_t cnt = 0;
49 
50  // By default, there's only one source defined: ANY.
51  // If user specified anything, we need to get rid of that default.
52  mac_sources.clear();
53 
54  BOOST_FOREACH(ConstElementPtr source_elem, value->listValue()) {
55  std::string source_str = source_elem->stringValue();
56  try {
57  source = CfgMACSource::MACSourceFromText(source_str);
58  mac_sources.add(source);
59  ++cnt;
60  } catch (const InvalidParameter& ex) {
61  isc_throw(DhcpConfigError, "The mac-sources value '" << source_str
62  << "' was specified twice (" << value->getPosition() << ")");
63  } catch (const std::exception& ex) {
64  isc_throw(DhcpConfigError, "Failed to convert '"
65  << source_str << "' to any recognized MAC source:"
66  << ex.what() << " (" << value->getPosition() << ")");
67  }
68  }
69 
70  if (!cnt) {
71  isc_throw(DhcpConfigError, "If specified, MAC Sources cannot be empty");
72  }
73 }
74 
75 // ******************** ControlSocketParser *************************
76 void ControlSocketParser::parse(SrvConfig& srv_cfg, isc::data::ConstElementPtr value) {
77  if (!value) {
78  // Sanity check: not supposed to fail.
79  isc_throw(DhcpConfigError, "Logic error: specified control-socket is null");
80  }
81 
82  if (value->getType() != Element::map) {
83  // Sanity check: not supposed to fail.
84  isc_throw(DhcpConfigError, "Specified control-socket is expected to be a map"
85  ", i.e. a structure defined within { }");
86  }
87  srv_cfg.setControlSocketInfo(value);
88 }
89 
90 // ******************************** OptionDefParser ****************************
91 
92 OptionDefParser::OptionDefParser(const uint16_t address_family)
93  : address_family_(address_family) {
94 }
95 
98 
99  // Check parameters.
100  if (address_family_ == AF_INET) {
102  } else {
104  }
105 
106  // Get mandatory parameters.
107  std::string name = getString(option_def, "name");
108  int64_t code64 = getInteger(option_def, "code");
109  std::string type = getString(option_def, "type");
110 
111  // Get optional parameters. Whoever called this parser, should have
112  // called SimpleParser::setDefaults first.
113  bool array_type = getBoolean(option_def, "array");
114  std::string record_types = getString(option_def, "record-types");
115  std::string space = getString(option_def, "space");
116  std::string encapsulates = getString(option_def, "encapsulate");
117  ConstElementPtr user_context = option_def->get("user-context");
118 
119  // Check code value.
120  if (code64 < 0) {
121  isc_throw(DhcpConfigError, "option code must not be negative "
122  "(" << getPosition("code", option_def) << ")");
123  } else if (address_family_ == AF_INET &&
124  code64 > std::numeric_limits<uint8_t>::max()) {
125  isc_throw(DhcpConfigError, "invalid option code '" << code64
126  << "', it must not be greater than '"
127  << static_cast<int>(std::numeric_limits<uint8_t>::max())
128  << "' (" << getPosition("code", option_def) << ")");
129  } else if (address_family_ == AF_INET6 &&
130  code64 > std::numeric_limits<uint16_t>::max()) {
131  isc_throw(DhcpConfigError, "invalid option code '" << code64
132  << "', it must not be greater than '"
133  << std::numeric_limits<uint16_t>::max()
134  << "' (" << getPosition("code", option_def) << ")");
135  }
136  uint32_t code = static_cast<uint32_t>(code64);
137 
138  // Validate space name.
139  if (!OptionSpace::validateName(space)) {
140  isc_throw(DhcpConfigError, "invalid option space name '"
141  << space << "' ("
142  << getPosition("space", option_def) << ")");
143  }
144 
145  // Protect against definition of options 0 (PAD) or 255 (END)
146  // in (and only in) the dhcp4 space.
147  if (space == DHCP4_OPTION_SPACE) {
148  if (code == DHO_PAD) {
149  isc_throw(DhcpConfigError, "invalid option code '0': "
150  << "reserved for PAD ("
151  << getPosition("code", option_def) << ")");
152  } else if (code == DHO_END) {
153  isc_throw(DhcpConfigError, "invalid option code '255': "
154  << "reserved for END ("
155  << getPosition("code", option_def) << ")");
156  }
157  }
158 
159  // For dhcp6 space the value 0 is reserved.
160  if (space == DHCP6_OPTION_SPACE) {
161  if (code == 0) {
162  isc_throw(DhcpConfigError, "invalid option code '0': "
163  << "reserved value ("
164  << getPosition("code", option_def) << ")");
165  }
166  }
167 
168  // Create option definition.
170  // We need to check if user has set encapsulated option space
171  // name. If so, different constructor will be used.
172  if (!encapsulates.empty()) {
173  // Arrays can't be used together with sub-options.
174  if (array_type) {
175  isc_throw(DhcpConfigError, "option '" << space << "."
176  << name << "', comprising an array of data"
177  << " fields may not encapsulate any option space ("
178  << option_def->getPosition() << ")");
179 
180  } else if (encapsulates == space) {
181  isc_throw(DhcpConfigError, "option must not encapsulate"
182  << " an option space it belongs to: '"
183  << space << "." << name << "' is set to"
184  << " encapsulate '" << space << "' ("
185  << option_def->getPosition() << ")");
186 
187  } else {
188  def.reset(new OptionDefinition(name, code, space, type,
189  encapsulates.c_str()));
190  }
191 
192  } else {
193  def.reset(new OptionDefinition(name, code, space, type, array_type));
194 
195  }
196 
197  if (user_context) {
198  def->setContext(user_context);
199  }
200 
201  // Split the list of record types into tokens.
202  std::vector<std::string> record_tokens =
203  isc::util::str::tokens(record_types, ",");
204  // Iterate over each token and add a record type into
205  // option definition.
206  BOOST_FOREACH(std::string record_type, record_tokens) {
207  try {
208  boost::trim(record_type);
209  if (!record_type.empty()) {
210  def->addRecordField(record_type);
211  }
212  } catch (const Exception& ex) {
213  isc_throw(DhcpConfigError, "invalid record type values"
214  << " specified for the option definition: "
215  << ex.what() << " ("
216  << getPosition("record-types", option_def) << ")");
217  }
218  }
219 
220  // Validate the definition.
221  try {
222  def->validate();
223  } catch (const std::exception& ex) {
225  << " (" << option_def->getPosition() << ")");
226  }
227 
228  // Option definition has been created successfully.
229  return (def);
230 }
231 
232 // ******************************** OptionDefListParser ************************
233 
234 OptionDefListParser::OptionDefListParser(const uint16_t address_family)
235  : address_family_(address_family) {
236 }
237 
238 void
240  if (!option_def_list) {
241  // Sanity check: not supposed to fail.
242  isc_throw(DhcpConfigError, "parser error: a pointer to a list of"
243  << " option definitions is NULL ("
244  << option_def_list->getPosition() << ")");
245  }
246 
247  OptionDefParser parser(address_family_);
248  BOOST_FOREACH(ConstElementPtr option_def, option_def_list->listValue()) {
249  OptionDefinitionPtr def = parser.parse(option_def);
250  try {
251  storage->add(def);
252  } catch (const std::exception& ex) {
253  // Append position if there is a failure.
254  isc_throw(DhcpConfigError, ex.what() << " ("
255  << option_def->getPosition() << ")");
256  }
257  }
258 
259  // All definitions have been prepared. Put them as runtime options into
260  // the libdhcp++.
261  LibDHCP::setRuntimeOptionDefs(storage->getContainer());
262 }
263 
264 //****************************** RelayInfoParser ********************************
266  : family_(family) {
267 };
268 
269 void
271  ConstElementPtr relay_elem) {
272 
273  if (relay_elem->getType() != Element::map) {
274  isc_throw(DhcpConfigError, "relay must be a map");
275  }
276 
277  ConstElementPtr address = relay_elem->get("ip-address");
278  ConstElementPtr addresses = relay_elem->get("ip-addresses");
279 
280  if (address && addresses) {
282  "specify either ip-address or ip-addresses, not both");
283  }
284 
285  if (!address && !addresses) {
286  isc_throw(DhcpConfigError, "ip-addresses is required");
287  }
288 
289  // Create our resultant RelayInfo structure
290  *relay_info = isc::dhcp::Network::RelayInfo();
291 
292  if (address) {
293  addAddress("ip-address", getString(relay_elem, "ip-address"),
294  relay_elem, relay_info);
297  .arg(getPosition("ip-address", relay_elem));
298  return;
299  }
300 
301  if (addresses->getType() != Element::list) {
302  isc_throw(DhcpConfigError, "ip-addresses must be a list "
303  "(" << getPosition("ip-addresses", relay_elem) << ")");
304  }
305 
306  BOOST_FOREACH(ConstElementPtr address_element, addresses->listValue()) {
307  addAddress("ip-addresses", address_element->stringValue(),
308  relay_elem, relay_info);
309  }
310 }
311 
312 void
313 RelayInfoParser::addAddress(const std::string& name,
314  const std::string& address_str,
315  ConstElementPtr relay_elem,
316  const isc::dhcp::Network::RelayInfoPtr& relay_info) {
317  boost::scoped_ptr<isc::asiolink::IOAddress> ip;
318  try {
319  ip.reset(new isc::asiolink::IOAddress(address_str));
320  } catch (const std::exception& ex) {
321  isc_throw(DhcpConfigError, "address " << address_str
322  << " is not a valid: "
323  << (family_ == Option::V4 ? "IPv4" : "IPv6")
324  << "address"
325  << " (" << getPosition(name, relay_elem) << ")");
326  }
327 
328  // Check if the address family matches.
329  if ((ip->isV4() && family_ != Option::V4) ||
330  (ip->isV6() && family_ != Option::V6) ) {
331  isc_throw(DhcpConfigError, "address " << address_str
332  << " is not a: "
333  << (family_ == Option::V4 ? "IPv4" : "IPv6")
334  << "address"
335  << " (" << getPosition(name, relay_elem) << ")");
336  }
337 
338  try {
339  relay_info->addAddress(*ip);
340  } catch (const std::exception& ex) {
341  isc_throw(DhcpConfigError, "cannot add address: " << address_str
342  << " to relay info: " << ex.what()
343  << " (" << getPosition(name, relay_elem) << ")");
344  }
345 }
346 
347 //****************************** PoolParser ********************************
348 
349 void
351  ConstElementPtr pool_structure,
352  const uint16_t address_family) {
353 
354  if (address_family == AF_INET) {
356  } else {
358  }
359 
360  ConstElementPtr text_pool = pool_structure->get("pool");
361 
362  if (!text_pool) {
363  isc_throw(DhcpConfigError, "Mandatory 'pool' entry missing in "
364  "definition: (" << pool_structure->getPosition() << ")");
365  }
366 
367  // That should be a single pool representation. It should contain
368  // text is form prefix/len or first - last. Note that spaces
369  // are allowed
370  string txt = text_pool->stringValue();
371 
372  // first let's remove any whitespaces
373  boost::erase_all(txt, " "); // space
374  boost::erase_all(txt, "\t"); // tabulation
375 
376  PoolPtr pool;
377 
378  // Is this prefix/len notation?
379  size_t pos = txt.find("/");
380  if (pos != string::npos) {
381  isc::asiolink::IOAddress addr("::");
382  uint8_t len = 0;
383  try {
384  addr = isc::asiolink::IOAddress(txt.substr(0, pos));
385 
386  // start with the first character after /
387  string prefix_len = txt.substr(pos + 1);
388 
389  // It is lexical cast to int and then downcast to uint8_t.
390  // Direct cast to uint8_t (which is really an unsigned char)
391  // will result in interpreting the first digit as output
392  // value and throwing exception if length is written on two
393  // digits (because there are extra characters left over).
394 
395  // No checks for values over 128. Range correctness will
396  // be checked in Pool4 constructor, here we only check
397  // the representation fits in an uint8_t as this can't
398  // be done by a direct lexical cast as explained...
399  int val_len = boost::lexical_cast<int>(prefix_len);
400  if ((val_len < std::numeric_limits<uint8_t>::min()) ||
401  (val_len > std::numeric_limits<uint8_t>::max())) {
402  // This exception will be handled 4 line later!
403  isc_throw(OutOfRange, "");
404  }
405  len = static_cast<uint8_t>(val_len);
406  } catch (...) {
407  isc_throw(DhcpConfigError, "Failed to parse pool "
408  "definition: " << txt << " ("
409  << text_pool->getPosition() << ")");
410  }
411 
412  try {
413  pool = poolMaker(addr, len);
414  pools->push_back(pool);
415  } catch (const std::exception& ex) {
416  isc_throw(DhcpConfigError, "Failed to create pool defined by: "
417  << txt << " (" << text_pool->getPosition() << ")");
418  }
419 
420  } else {
421  isc::asiolink::IOAddress min("::");
422  isc::asiolink::IOAddress max("::");
423 
424  // Is this min-max notation?
425  pos = txt.find("-");
426  if (pos != string::npos) {
427  // using min-max notation
428  try {
429  min = isc::asiolink::IOAddress(txt.substr(0, pos));
430  max = isc::asiolink::IOAddress(txt.substr(pos + 1));
431  } catch (...) {
432  isc_throw(DhcpConfigError, "Failed to parse pool "
433  "definition: " << txt << " ("
434  << text_pool->getPosition() << ")");
435  }
436 
437  try {
438  pool = poolMaker(min, max);
439  pools->push_back(pool);
440  } catch (const std::exception& ex) {
441  isc_throw(DhcpConfigError, "Failed to create pool defined by: "
442  << txt << " (" << text_pool->getPosition() << ")");
443  }
444  }
445  }
446 
447  if (!pool) {
448  isc_throw(DhcpConfigError, "invalid pool definition: "
449  << text_pool->stringValue() <<
450  ". There are two acceptable formats <min address-max address>"
451  " or <prefix/len> ("
452  << text_pool->getPosition() << ")");
453  }
454 
455  // If there's user-context specified, store it.
456  ConstElementPtr user_context = pool_structure->get("user-context");
457  if (user_context) {
458  // The grammar accepts only maps but still check it.
459  if (user_context->getType() != Element::map) {
460  isc_throw(isc::dhcp::DhcpConfigError, "User context has to be a map ("
461  << user_context->getPosition() << ")");
462  }
463  pool->setContext(user_context);
464  }
465 
466  // Parser pool specific options.
467  ConstElementPtr option_data = pool_structure->get("option-data");
468  if (option_data) {
469  try {
470  CfgOptionPtr cfg = pool->getCfgOption();
471  auto option_parser = createOptionDataListParser(address_family);
472  option_parser->parse(cfg, option_data);
473  } catch (const std::exception& ex) {
475  << " (" << option_data->getPosition() << ")");
476  }
477  }
478 
479  // Client-class.
480  ConstElementPtr client_class = pool_structure->get("client-class");
481  if (client_class) {
482  string cclass = client_class->stringValue();
483  if (!cclass.empty()) {
484  pool->allowClientClass(cclass);
485  }
486  }
487 
488  // Try setting up required client classes.
489  ConstElementPtr class_list = pool_structure->get("require-client-classes");
490  if (class_list) {
491  const std::vector<data::ElementPtr>& classes = class_list->listValue();
492  for (auto cclass = classes.cbegin();
493  cclass != classes.cend(); ++cclass) {
494  if (((*cclass)->getType() != Element::string) ||
495  (*cclass)->stringValue().empty()) {
496  isc_throw(DhcpConfigError, "invalid class name ("
497  << (*cclass)->getPosition() << ")");
498  }
499  pool->requireClientClass((*cclass)->stringValue());
500  }
501  }
502 }
503 
504 boost::shared_ptr<OptionDataListParser>
505 PoolParser::createOptionDataListParser(const uint16_t address_family) const {
506  auto parser = boost::make_shared<OptionDataListParser>(address_family);
507  return (parser);
508 }
509 
510 //****************************** Pool4Parser *************************
511 
512 PoolPtr
513 Pool4Parser::poolMaker (IOAddress &addr, uint32_t len, int32_t) {
514  return (PoolPtr(new Pool4(addr, len)));
515 }
516 
517 PoolPtr
519  return (PoolPtr(new Pool4(min, max)));
520 }
521 
522 //****************************** Pools4ListParser *************************
523 
524 void
526  BOOST_FOREACH(ConstElementPtr pool, pools_list->listValue()) {
527  auto parser = createPoolConfigParser();
528  parser->parse(pools, pool, AF_INET);
529  }
530 }
531 
532 boost::shared_ptr<PoolParser>
534  auto parser = boost::make_shared<Pool4Parser>();
535  return (parser);
536 }
537 
538 //****************************** SubnetConfigParser *************************
539 
540 SubnetConfigParser::SubnetConfigParser(uint16_t family, bool check_iface)
541  : pools_(new PoolStorage()),
542  address_family_(family),
543  options_(new CfgOption()),
544  check_iface_(check_iface) {
546 }
547 
548 SubnetPtr
550 
551  ConstElementPtr options_params = subnet->get("option-data");
552  if (options_params) {
553  auto opt_parser = createOptionDataListParser();
554  opt_parser->parse(options_, options_params);
555  }
556 
557  ConstElementPtr relay_params = subnet->get("relay");
558  if (relay_params) {
560  RelayInfoParser parser(u);
561  parser.parse(relay_info_, relay_params);
562  }
563 
564  // Create a subnet.
565  try {
566  createSubnet(subnet);
567  } catch (const std::exception& ex) {
569  "subnet configuration failed: " << ex.what());
570  }
571 
572  return (subnet_);
573 }
574 
575 void
577  std::string subnet_txt;
578  try {
579  subnet_txt = getString(params, "subnet");
580  } catch (const DhcpConfigError &) {
581  // rethrow with precise error
583  "mandatory 'subnet' parameter is missing for a subnet being"
584  " configured (" << params->getPosition() << ")");
585  }
586 
587  // Remove any spaces or tabs.
588  boost::erase_all(subnet_txt, " ");
589  boost::erase_all(subnet_txt, "\t");
590 
591  // The subnet format is prefix/len. We are going to extract
592  // the prefix portion of a subnet string to create IOAddress
593  // object from it. IOAddress will be passed to the Subnet's
594  // constructor later on. In order to extract the prefix we
595  // need to get all characters preceding "/".
596  size_t pos = subnet_txt.find("/");
597  if (pos == string::npos) {
598  ConstElementPtr elem = params->get("subnet");
600  "Invalid subnet syntax (prefix/len expected):" << subnet_txt
601  << " (" << elem->getPosition() << ")");
602  }
603 
604  // Try to create the address object. It also validates that
605  // the address syntax is ok.
606  isc::asiolink::IOAddress addr(subnet_txt.substr(0, pos));
607 
608  // Now parse out the prefix length.
609  unsigned int len;
610  try {
611  len = boost::lexical_cast<unsigned int>(subnet_txt.substr(pos + 1));
612  } catch (const boost::bad_lexical_cast&) {
613  ConstElementPtr elem = params->get("subnet");
614  isc_throw(DhcpConfigError, "prefix length: '" <<
615  subnet_txt.substr(pos+1) << "' is not an integer ("
616  << elem->getPosition() << ")");
617  }
618 
619  // Sanity check the prefix length
620  if ((addr.isV6() && len > 128) ||
621  (addr.isV4() && len > 32)) {
622  ConstElementPtr elem = params->get("subnet");
624  "Invalid prefix length specified for subnet: " << len
625  << " (" << elem->getPosition() << ")");
626  }
627 
628  // Call the subclass's method to instantiate the subnet
629  initSubnet(params, addr, len);
630 
631  // Add pools to it.
632  for (PoolStorage::iterator it = pools_->begin(); it != pools_->end();
633  ++it) {
634  try {
635  subnet_->addPool(*it);
636  } catch (const BadValue& ex) {
637  // addPool() can throw BadValue if the pool is overlapping or
638  // is out of bounds for the subnet.
640  ex.what() << " (" << params->getPosition() << ")");
641  }
642  }
643  // If there's user-context specified, store it.
644  ConstElementPtr user_context = params->get("user-context");
645  if (user_context) {
646  // The grammar accepts only maps but still check it.
647  if (user_context->getType() != Element::map) {
648  isc_throw(isc::dhcp::DhcpConfigError, "User context has to be a map ("
649  << user_context->getPosition() << ")");
650  }
651  subnet_->setContext(user_context);
652  }
653 
654  // In order to take advantage of the dynamic inheritance of global
655  // parameters to a subnet we need to set a callback function for each
656  // subnet to allow for fetching global parameters.
657  subnet_->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr {
658  return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals());
659  });
660 }
661 
662 boost::shared_ptr<OptionDataListParser>
664  auto parser = boost::make_shared<OptionDataListParser>(address_family_);
665  return (parser);
666 }
667 
668 //****************************** Subnet4ConfigParser *************************
669 
671  : SubnetConfigParser(AF_INET, check_iface) {
672 }
673 
676  // Check parameters.
678 
680  ConstElementPtr pools = subnet->get("pools");
681  if (pools) {
682  auto parser = createPoolsListParser();
683  parser->parse(pools_, pools);
684  }
685 
686  SubnetPtr generic = SubnetConfigParser::parse(subnet);
687 
688  if (!generic) {
689  // Sanity check: not supposed to fail.
691  "Failed to create an IPv4 subnet (" <<
692  subnet->getPosition() << ")");
693  }
694 
695  Subnet4Ptr sn4ptr = boost::dynamic_pointer_cast<Subnet4>(subnet_);
696  if (!sn4ptr) {
697  // If we hit this, it is a programming error.
699  "Invalid Subnet4 cast in Subnet4ConfigParser::parse");
700  }
701 
702  // Set relay information if it was parsed
703  if (relay_info_) {
704  sn4ptr->setRelayInfo(*relay_info_);
705  }
706 
707  // Parse Host Reservations for this subnet if any.
708  ConstElementPtr reservations = subnet->get("reservations");
709  if (reservations) {
710  HostCollection hosts;
712  parser.parse(subnet_->getID(), reservations, hosts);
713  for (auto h = hosts.begin(); h != hosts.end(); ++h) {
714  validateResv(sn4ptr, *h);
715  CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(*h);
716  }
717  }
718 
719  return (sn4ptr);
720 }
721 
722 void
724  asiolink::IOAddress addr, uint8_t len) {
725  // Subnet ID is optional. If it is not supplied the value of 0 is used,
726  // which means autogenerate. The value was inserted earlier by calling
727  // SimpleParser4::setAllDefaults.
728  int64_t subnet_id_max = static_cast<int64_t>(SUBNET_ID_MAX);
729  SubnetID subnet_id = static_cast<SubnetID>(getInteger(params, "id", 0,
730  subnet_id_max));
731 
732  Subnet4Ptr subnet4(new Subnet4(addr, len, Triplet<uint32_t>(),
734  subnet_id));
735  subnet_ = subnet4;
736 
737  // Move from reservation mode to new reservations flags.
738  ElementPtr mutable_params;
739  mutable_params = boost::const_pointer_cast<Element>(params);
740  // @todo add warning
742 
743  // Parse parameters common to all Network derivations.
744  NetworkPtr network = boost::dynamic_pointer_cast<Network>(subnet4);
745  parseCommon(mutable_params, network);
746 
747  std::ostringstream output;
748  output << addr << "/" << static_cast<int>(len) << " with params: ";
749 
750  bool has_renew = !subnet4->getT1().unspecified();
751  bool has_rebind = !subnet4->getT2().unspecified();
752  int64_t renew = -1;
753  int64_t rebind = -1;
754 
755  // t1 and t2 are optional may be not specified.
756  if (has_renew) {
757  renew = subnet4->getT1().get();
758  output << "t1=" << renew << ", ";
759  }
760  if (has_rebind) {
761  rebind = subnet4->getT2().get();
762  output << "t2=" << rebind << ", ";
763  }
764 
765  if (has_renew && has_rebind && (renew > rebind)) {
766  isc_throw(DhcpConfigError, "the value of renew-timer (" << renew
767  << ") is greater than the value of rebind-timer ("
768  << rebind << ")");
769  }
770 
771  if (!subnet4->getValid().unspecified()) {
772  output << "valid-lifetime=" << subnet4->getValid().get();
773  }
774 
776 
777  // Set the match-client-id value for the subnet.
778  if (params->contains("match-client-id")) {
779  bool match_client_id = getBoolean(params, "match-client-id");
780  subnet4->setMatchClientId(match_client_id);
781  }
782 
783  // Set the authoritative value for the subnet.
784  if (params->contains("authoritative")) {
785  bool authoritative = getBoolean(params, "authoritative");
786  subnet4->setAuthoritative(authoritative);
787  }
788 
789  // Set next-server. The default value is 0.0.0.0. Nevertheless, the
790  // user could have messed that up by specifying incorrect value.
791  // To avoid using 0.0.0.0, user can specify "".
792  if (params->contains("next-server")) {
793  string next_server;
794  try {
795  next_server = getString(params, "next-server");
796  if (!next_server.empty()) {
797  subnet4->setSiaddr(IOAddress(next_server));
798  }
799  } catch (...) {
800  ConstElementPtr next = params->get("next-server");
801  string pos;
802  if (next) {
803  pos = next->getPosition().str();
804  } else {
805  pos = params->getPosition().str();
806  }
807  isc_throw(DhcpConfigError, "invalid parameter next-server : "
808  << next_server << "(" << pos << ")");
809  }
810  }
811 
812  // Set server-hostname.
813  if (params->contains("server-hostname")) {
814  std::string sname = getString(params, "server-hostname");
815  if (!sname.empty()) {
816  if (sname.length() >= Pkt4::MAX_SNAME_LEN) {
817  ConstElementPtr error = params->get("server-hostname");
818  isc_throw(DhcpConfigError, "server-hostname must be at most "
819  << Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is "
820  << sname.length() << " ("
821  << error->getPosition() << ")");
822  }
823  subnet4->setSname(sname);
824  }
825  }
826 
827  // Set boot-file-name.
828  if (params->contains("boot-file-name")) {
829  std::string filename =getString(params, "boot-file-name");
830  if (!filename.empty()) {
831  if (filename.length() > Pkt4::MAX_FILE_LEN) {
832  ConstElementPtr error = params->get("boot-file-name");
833  isc_throw(DhcpConfigError, "boot-file-name must be at most "
834  << Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is "
835  << filename.length() << " ("
836  << error->getPosition() << ")");
837  }
838  subnet4->setFilename(filename);
839  }
840  }
841 
842  // Get interface name. If it is defined, then the subnet is available
843  // directly over specified network interface.
844  if (params->contains("interface")) {
845  std::string iface = getString(params, "interface");
846  if (!iface.empty()) {
847  if (check_iface_ && !IfaceMgr::instance().getIface(iface)) {
848  ConstElementPtr error = params->get("interface");
849  isc_throw(DhcpConfigError, "Specified network interface name " << iface
850  << " for subnet " << subnet4->toText()
851  << " is not present in the system ("
852  << error->getPosition() << ")");
853  }
854 
855  subnet4->setIface(iface);
856  }
857  }
858 
859  // Try setting up client class.
860  if (params->contains("client-class")) {
861  string client_class = getString(params, "client-class");
862  if (!client_class.empty()) {
863  subnet4->allowClientClass(client_class);
864  }
865  }
866 
867  // Try setting up required client classes.
868  ConstElementPtr class_list = params->get("require-client-classes");
869  if (class_list) {
870  const std::vector<data::ElementPtr>& classes = class_list->listValue();
871  for (auto cclass = classes.cbegin();
872  cclass != classes.cend(); ++cclass) {
873  if (((*cclass)->getType() != Element::string) ||
874  (*cclass)->stringValue().empty()) {
875  isc_throw(DhcpConfigError, "invalid class name ("
876  << (*cclass)->getPosition() << ")");
877  }
878  subnet4->requireClientClass((*cclass)->stringValue());
879  }
880  }
881 
882  // 4o6 specific parameter: 4o6-interface.
883  if (params->contains("4o6-interface")) {
884  string iface4o6 = getString(params, "4o6-interface");
885  if (!iface4o6.empty()) {
886  subnet4->get4o6().setIface4o6(iface4o6);
887  subnet4->get4o6().enabled(true);
888  }
889  }
890 
891  // 4o6 specific parameter: 4o6-subnet.
892  if (params->contains("4o6-subnet")) {
893  string subnet4o6 = getString(params, "4o6-subnet");
894  if (!subnet4o6.empty()) {
895  size_t slash = subnet4o6.find("/");
896  if (slash == std::string::npos) {
897  isc_throw(DhcpConfigError, "Missing / in the 4o6-subnet parameter:"
898  << subnet4o6 << ", expected format: prefix6/length");
899  }
900  string prefix = subnet4o6.substr(0, slash);
901  string lenstr = subnet4o6.substr(slash + 1);
902 
903  uint8_t len = 128;
904  try {
905  len = boost::lexical_cast<unsigned int>(lenstr.c_str());
906  } catch (const boost::bad_lexical_cast &) {
907  isc_throw(DhcpConfigError, "Invalid prefix length specified in "
908  "4o6-subnet parameter: " << subnet4o6 << ", expected 0..128 value");
909  }
910  subnet4->get4o6().setSubnet4o6(IOAddress(prefix), len);
911  subnet4->get4o6().enabled(true);
912  }
913  }
914 
915  // Try 4o6 specific parameter: 4o6-interface-id
916  if (params->contains("4o6-interface-id")) {
917  std::string ifaceid = getString(params, "4o6-interface-id");
918  if (!ifaceid.empty()) {
919  OptionBuffer tmp(ifaceid.begin(), ifaceid.end());
921  subnet4->get4o6().setInterfaceId(opt);
922  subnet4->get4o6().enabled(true);
923  }
924  }
925 
928 
929  // Here globally defined options were merged to the subnet specific
930  // options but this is no longer the case (they have a different
931  // and not consecutive priority).
932 
933  // Copy options to the subnet configuration.
934  options_->copyTo(*subnet4->getCfgOption());
935 
936  // Parse t1-percent and t2-percent
937  parseTeePercents(params, network);
938 
939  // Parse DDNS parameters
940  parseDdnsParams(params, network);
941 
942  // Parse lease cache parameters
943  parseCacheParams(params, network);
944 }
945 
946 void
948  const IOAddress& address = host->getIPv4Reservation();
949  if (!address.isV4Zero() && !subnet->inRange(address)) {
950  isc_throw(DhcpConfigError, "specified reservation '" << address
951  << "' is not within the IPv4 subnet '"
952  << subnet->toText() << "'");
953  }
954 }
955 
956 boost::shared_ptr<PoolsListParser>
958  auto parser = boost::make_shared<Pools4ListParser>();
959  return (parser);
960 }
961 
962 //**************************** Subnets4ListConfigParser **********************
963 
965  : check_iface_(check_iface) {
966 }
967 
968 size_t
970  ConstElementPtr subnets_list) {
971  size_t cnt = 0;
972  BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
973 
974  auto parser = createSubnetConfigParser();
975  Subnet4Ptr subnet = parser->parse(subnet_json);
976  if (subnet) {
977 
978  // Adding a subnet to the Configuration Manager may fail if the
979  // subnet id is invalid (duplicate). Thus, we catch exceptions
980  // here to append a position in the configuration string.
981  try {
982  cfg->getCfgSubnets4()->add(subnet);
983  cnt++;
984  } catch (const std::exception& ex) {
985  isc_throw(DhcpConfigError, ex.what() << " ("
986  << subnet_json->getPosition() << ")");
987  }
988  }
989  }
990  return (cnt);
991 }
992 
993 size_t
995  data::ConstElementPtr subnets_list) {
996  size_t cnt = 0;
997  BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
998 
999  auto parser = createSubnetConfigParser();
1000  Subnet4Ptr subnet = parser->parse(subnet_json);
1001  if (subnet) {
1002  try {
1003  auto ret = subnets.insert(subnet);
1004  if (!ret.second) {
1006  "can't store subnet because of conflict");
1007  }
1008  ++cnt;
1009  } catch (const std::exception& ex) {
1010  isc_throw(DhcpConfigError, ex.what() << " ("
1011  << subnet_json->getPosition() << ")");
1012  }
1013  }
1014  }
1015  return (cnt);
1016 }
1017 
1018 boost::shared_ptr<Subnet4ConfigParser>
1020  auto parser = boost::make_shared<Subnet4ConfigParser>(check_iface_);
1021  return (parser);
1022 }
1023 
1024 //**************************** Pool6Parser *********************************
1025 
1026 PoolPtr
1027 Pool6Parser::poolMaker (IOAddress &addr, uint32_t len, int32_t ptype)
1028 {
1029  return (PoolPtr(new Pool6(static_cast<isc::dhcp::Lease::Type>
1030  (ptype), addr, len)));
1031 }
1032 
1033 PoolPtr
1034 Pool6Parser::poolMaker (IOAddress &min, IOAddress &max, int32_t ptype)
1035 {
1036  return (PoolPtr(new Pool6(static_cast<isc::dhcp::Lease::Type>
1037  (ptype), min, max)));
1038 }
1039 
1040 
1041 //**************************** Pool6ListParser ***************************
1042 
1043 void
1045  BOOST_FOREACH(ConstElementPtr pool, pools_list->listValue()) {
1046  auto parser = createPoolConfigParser();
1047  parser->parse(pools, pool, AF_INET6);
1048  }
1049 }
1050 
1051 boost::shared_ptr<PoolParser>
1053  auto parser = boost::make_shared<Pool6Parser>();
1054  return (parser);
1055 }
1056 
1057 //**************************** PdPoolParser ******************************
1058 
1060 }
1061 
1062 void
1065 
1066  std::string addr_str = getString(pd_pool_, "prefix");
1067 
1068  uint8_t prefix_len = getUint8(pd_pool_, "prefix-len");
1069 
1070  uint8_t delegated_len = getUint8(pd_pool_, "delegated-len");
1071 
1072  std::string excluded_prefix_str = "::";
1073  if (pd_pool_->contains("excluded-prefix")) {
1074  excluded_prefix_str = getString(pd_pool_, "excluded-prefix");
1075  }
1076 
1077  uint8_t excluded_prefix_len = 0;
1078  if (pd_pool_->contains("excluded-prefix-len")) {
1079  excluded_prefix_len = getUint8(pd_pool_, "excluded-prefix-len");
1080  }
1081 
1082  ConstElementPtr option_data = pd_pool_->get("option-data");
1083  if (option_data) {
1084  auto opts_parser = createOptionDataListParser();
1085  opts_parser->parse(options_, option_data);
1086  }
1087 
1088  ConstElementPtr user_context = pd_pool_->get("user-context");
1089  if (user_context) {
1090  user_context_ = user_context;
1091  }
1092 
1093  ConstElementPtr client_class = pd_pool_->get("client-class");
1094  if (client_class) {
1095  client_class_ = client_class;
1096  }
1097 
1098  ConstElementPtr class_list = pd_pool_->get("require-client-classes");
1099 
1100  // Check the pool parameters. It will throw an exception if any
1101  // of the required parameters are invalid.
1102  try {
1103  // Attempt to construct the local pool.
1104  pool_.reset(new Pool6(IOAddress(addr_str),
1105  prefix_len,
1106  delegated_len,
1107  IOAddress(excluded_prefix_str),
1108  excluded_prefix_len));
1109  // Merge options specified for a pool into pool configuration.
1110  options_->copyTo(*pool_->getCfgOption());
1111  } catch (const std::exception& ex) {
1112  // Some parameters don't exist or are invalid. Since we are not
1113  // aware whether they don't exist or are invalid, let's append
1114  // the position of the pool map element.
1116  << " (" << pd_pool_->getPosition() << ")");
1117  }
1118 
1119  if (user_context_) {
1120  pool_->setContext(user_context_);
1121  }
1122 
1123  if (client_class_) {
1124  string cclass = client_class_->stringValue();
1125  if (!cclass.empty()) {
1126  pool_->allowClientClass(cclass);
1127  }
1128  }
1129 
1130  if (class_list) {
1131  const std::vector<data::ElementPtr>& classes = class_list->listValue();
1132  for (auto cclass = classes.cbegin();
1133  cclass != classes.cend(); ++cclass) {
1134  if (((*cclass)->getType() != Element::string) ||
1135  (*cclass)->stringValue().empty()) {
1136  isc_throw(DhcpConfigError, "invalid class name ("
1137  << (*cclass)->getPosition() << ")");
1138  }
1139  pool_->requireClientClass((*cclass)->stringValue());
1140  }
1141  }
1142 
1143  // Add the local pool to the external storage ptr.
1144  pools->push_back(pool_);
1145 }
1146 
1147 boost::shared_ptr<OptionDataListParser>
1149  auto parser = boost::make_shared<OptionDataListParser>(AF_INET6);
1150  return (parser);
1151 }
1152 
1153 //**************************** PdPoolsListParser ************************
1154 
1155 void
1157  // Loop through the list of pd pools.
1158  BOOST_FOREACH(ConstElementPtr pd_pool, pd_pool_list->listValue()) {
1159  auto parser = createPdPoolConfigParser();
1160  parser->parse(pools, pd_pool);
1161  }
1162 }
1163 
1164 boost::shared_ptr<PdPoolParser>
1166  auto parser = boost::make_shared<PdPoolParser>();
1167  return (parser);
1168 }
1169 
1170 //**************************** Subnet6ConfigParser ***********************
1171 
1173  : SubnetConfigParser(AF_INET6, check_iface) {
1174 }
1175 
1176 Subnet6Ptr
1178  // Check parameters.
1180 
1182  ConstElementPtr pools = subnet->get("pools");
1183  if (pools) {
1184  auto parser = createPoolsListParser();
1185  parser->parse(pools_, pools);
1186  }
1187  ConstElementPtr pd_pools = subnet->get("pd-pools");
1188  if (pd_pools) {
1189  auto parser = createPdPoolsListParser();
1190  parser->parse(pools_, pd_pools);
1191  }
1192 
1193  SubnetPtr generic = SubnetConfigParser::parse(subnet);
1194 
1195  if (!generic) {
1196  // Sanity check: not supposed to fail.
1198  "Failed to create an IPv6 subnet (" <<
1199  subnet->getPosition() << ")");
1200  }
1201 
1202  Subnet6Ptr sn6ptr = boost::dynamic_pointer_cast<Subnet6>(subnet_);
1203  if (!sn6ptr) {
1204  // If we hit this, it is a programming error.
1206  "Invalid Subnet6 cast in Subnet6ConfigParser::parse");
1207  }
1208 
1209  // Set relay information if it was provided
1210  if (relay_info_) {
1211  sn6ptr->setRelayInfo(*relay_info_);
1212  }
1213 
1214  // Parse Host Reservations for this subnet if any.
1215  ConstElementPtr reservations = subnet->get("reservations");
1216  if (reservations) {
1217  HostCollection hosts;
1219  parser.parse(subnet_->getID(), reservations, hosts);
1220  for (auto h = hosts.begin(); h != hosts.end(); ++h) {
1221  validateResvs(sn6ptr, *h);
1222  CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(*h);
1223  }
1224  }
1225 
1226  return (sn6ptr);
1227 }
1228 
1229 // Unused?
1230 void
1232  asiolink::IOAddress& addr) {
1234  .arg(code).arg(addr.toText());
1235 }
1236 
1237 void
1239  asiolink::IOAddress addr, uint8_t len) {
1240  // Subnet ID is optional. If it is not supplied the value of 0 is used,
1241  // which means autogenerate. The value was inserted earlier by calling
1242  // SimpleParser6::setAllDefaults.
1243  int64_t subnet_id_max = static_cast<int64_t>(SUBNET_ID_MAX);
1244  SubnetID subnet_id = static_cast<SubnetID>(getInteger(params, "id", 0,
1245  subnet_id_max));
1246 
1247  // We want to log whether rapid-commit is enabled, so we get this
1248  // before the actual subnet creation.
1249  Optional<bool> rapid_commit;
1250  if (params->contains("rapid-commit")) {
1251  rapid_commit = getBoolean(params, "rapid-commit");
1252  }
1253 
1254  // Parse preferred lifetime as it is not parsed by the common function.
1255  Triplet<uint32_t> pref = parseIntTriplet(params, "preferred-lifetime");
1256 
1257  // Create a new subnet.
1258  Subnet6* subnet6 = new Subnet6(addr, len, Triplet<uint32_t>(),
1260  pref,
1262  subnet_id);
1263  subnet_.reset(subnet6);
1264 
1265  // Move from reservation mode to new reservations flags.
1266  ElementPtr mutable_params;
1267  mutable_params = boost::const_pointer_cast<Element>(params);
1268  // @todo add warning
1270 
1271  // Parse parameters common to all Network derivations.
1272  NetworkPtr network = boost::dynamic_pointer_cast<Network>(subnet_);
1273  parseCommon(mutable_params, network);
1274 
1275  // Enable or disable Rapid Commit option support for the subnet.
1276  if (!rapid_commit.unspecified()) {
1277  subnet6->setRapidCommit(rapid_commit);
1278  }
1279 
1280  std::ostringstream output;
1281  output << addr << "/" << static_cast<int>(len) << " with params: ";
1282  // t1 and t2 are optional may be not specified.
1283 
1284  bool has_renew = !subnet6->getT1().unspecified();
1285  bool has_rebind = !subnet6->getT2().unspecified();
1286  int64_t renew = -1;
1287  int64_t rebind = -1;
1288 
1289  if (has_renew) {
1290  renew = subnet6->getT1().get();
1291  output << "t1=" << renew << ", ";
1292  }
1293  if (has_rebind) {
1294  rebind = subnet6->getT2().get();
1295  output << "t2=" << rebind << ", ";
1296  }
1297 
1298  if (has_renew && has_rebind && (renew > rebind)) {
1299  isc_throw(DhcpConfigError, "the value of renew-timer (" << renew
1300  << ") is greater than the value of rebind-timer ("
1301  << rebind << ")");
1302  }
1303 
1304  if (!subnet6->getPreferred().unspecified()) {
1305  output << "preferred-lifetime=" << subnet6->getPreferred().get() << ", ";
1306  }
1307  if (!subnet6->getValid().unspecified()) {
1308  output << "valid-lifetime=" << subnet6->getValid().get();
1309  }
1310  if (!subnet6->getRapidCommit().unspecified()) {
1311  output << ", rapid-commit is "
1312  << boolalpha << subnet6->getRapidCommit().get();
1313  }
1314 
1316 
1317  // Get interface-id option content. For now we support string
1318  // representation only
1319  Optional<std::string> ifaceid;
1320  if (params->contains("interface-id")) {
1321  ifaceid = getString(params, "interface-id");
1322  }
1323 
1324  Optional<std::string> iface;
1325  if (params->contains("interface")) {
1326  iface = getString(params, "interface");
1327  }
1328 
1329  // Specifying both interface for locally reachable subnets and
1330  // interface id for relays is mutually exclusive. Need to test for
1331  // this condition.
1332  if (!ifaceid.unspecified() && !iface.unspecified() && !ifaceid.empty() &&
1333  !iface.empty()) {
1335  "parser error: interface (defined for locally reachable "
1336  "subnets) and interface-id (defined for subnets reachable"
1337  " via relays) cannot be defined at the same time for "
1338  "subnet " << addr << "/" << (int)len << "("
1339  << params->getPosition() << ")");
1340  }
1341 
1342  // Configure interface-id for remote interfaces, if defined
1343  if (!ifaceid.unspecified() && !ifaceid.empty()) {
1344  std::string ifaceid_value = ifaceid.get();
1345  OptionBuffer tmp(ifaceid_value.begin(), ifaceid_value.end());
1346  OptionPtr opt(new Option(Option::V6, D6O_INTERFACE_ID, tmp));
1347  subnet6->setInterfaceId(opt);
1348  }
1349 
1350  // Get interface name. If it is defined, then the subnet is available
1351  // directly over specified network interface.
1352  if (!iface.unspecified() && !iface.empty()) {
1353  if (check_iface_ && !IfaceMgr::instance().getIface(iface)) {
1354  ConstElementPtr error = params->get("interface");
1355  isc_throw(DhcpConfigError, "Specified network interface name " << iface
1356  << " for subnet " << subnet6->toText()
1357  << " is not present in the system ("
1358  << error->getPosition() << ")");
1359  }
1360 
1361  subnet6->setIface(iface);
1362  }
1363 
1364  // Try setting up client class.
1365  if (params->contains("client-class")) {
1366  string client_class = getString(params, "client-class");
1367  if (!client_class.empty()) {
1368  subnet6->allowClientClass(client_class);
1369  }
1370  }
1371 
1372  if (params->contains("require-client-classes")) {
1373  // Try setting up required client classes.
1374  ConstElementPtr class_list = params->get("require-client-classes");
1375  if (class_list) {
1376  const std::vector<data::ElementPtr>& classes = class_list->listValue();
1377  for (auto cclass = classes.cbegin();
1378  cclass != classes.cend(); ++cclass) {
1379  if (((*cclass)->getType() != Element::string) ||
1380  (*cclass)->stringValue().empty()) {
1381  isc_throw(DhcpConfigError, "invalid class name ("
1382  << (*cclass)->getPosition() << ")");
1383  }
1384  subnet6->requireClientClass((*cclass)->stringValue());
1385  }
1386  }
1387  }
1388 
1391 
1392  // Copy options to the subnet configuration.
1393  options_->copyTo(*subnet6->getCfgOption());
1394 
1395  // Parse t1-percent and t2-percent
1396  parseTeePercents(params, network);
1397 
1398  // Parse DDNS parameters
1399  parseDdnsParams(params, network);
1400 
1401  // Parse lease cache parameters
1402  parseCacheParams(params, network);
1403 }
1404 
1405 void
1407  IPv6ResrvRange range = host->getIPv6Reservations(IPv6Resrv::TYPE_NA);
1408  for (auto it = range.first; it != range.second; ++it) {
1409  const IOAddress& address = it->second.getPrefix();
1410  if (!subnet->inRange(address)) {
1411  isc_throw(DhcpConfigError, "specified reservation '" << address
1412  << "' is not within the IPv6 subnet '"
1413  << subnet->toText() << "'");
1414  }
1415  }
1416 }
1417 
1418 boost::shared_ptr<PoolsListParser>
1420  auto parser = boost::make_shared<Pools6ListParser>();
1421  return (parser);
1422 }
1423 
1424 boost::shared_ptr<PdPoolsListParser>
1426  auto parser = boost::make_shared<PdPoolsListParser>();
1427  return (parser);
1428 }
1429 
1430 //**************************** Subnet6ListConfigParser ********************
1431 
1433  : check_iface_(check_iface) {
1434 }
1435 
1436 size_t
1438  ConstElementPtr subnets_list) {
1439  size_t cnt = 0;
1440  BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
1441 
1442  auto parser = createSubnetConfigParser();
1443  Subnet6Ptr subnet = parser->parse(subnet_json);
1444 
1445  // Adding a subnet to the Configuration Manager may fail if the
1446  // subnet id is invalid (duplicate). Thus, we catch exceptions
1447  // here to append a position in the configuration string.
1448  try {
1449  cfg->getCfgSubnets6()->add(subnet);
1450  cnt++;
1451  } catch (const std::exception& ex) {
1452  isc_throw(DhcpConfigError, ex.what() << " ("
1453  << subnet_json->getPosition() << ")");
1454  }
1455  }
1456  return (cnt);
1457 }
1458 
1459 size_t
1461  ConstElementPtr subnets_list) {
1462  size_t cnt = 0;
1463  BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
1464 
1465  auto parser = createSubnetConfigParser();
1466  Subnet6Ptr subnet = parser->parse(subnet_json);
1467  if (subnet) {
1468  try {
1469  auto ret = subnets.insert(subnet);
1470  if (!ret.second) {
1472  "can't store subnet because of conflict");
1473  }
1474  ++cnt;
1475  } catch (const std::exception& ex) {
1476  isc_throw(DhcpConfigError, ex.what() << " ("
1477  << subnet_json->getPosition() << ")");
1478  }
1479  }
1480  }
1481  return (cnt);
1482 }
1483 
1484 boost::shared_ptr<Subnet6ConfigParser>
1486  auto parser = boost::make_shared<Subnet6ConfigParser>(check_iface_);
1487  return (parser);
1488 }
1489 
1490 //**************************** D2ClientConfigParser **********************
1491 
1493 D2ClientConfigParser::getProtocol(ConstElementPtr scope,
1494  const std::string& name) {
1497  (scope, name, "NameChangeRequest protocol"));
1498 }
1499 
1501 D2ClientConfigParser::getFormat(ConstElementPtr scope,
1502  const std::string& name) {
1505  (scope, name, "NameChangeRequest format"));
1506 }
1507 
1509 D2ClientConfigParser::getMode(ConstElementPtr scope,
1510  const std::string& name) {
1513  (scope, name, "ReplaceClientName mode"));
1514 }
1515 
1518  D2ClientConfigPtr new_config;
1519 
1520  // Get all parameters that are needed to create the D2ClientConfig.
1521  bool enable_updates = getBoolean(client_config, "enable-updates");
1522 
1523  IOAddress server_ip = getAddress(client_config, "server-ip");
1524 
1525  uint32_t server_port = getUint32(client_config, "server-port");
1526 
1527  std::string sender_ip_str = getString(client_config, "sender-ip");
1528 
1529  uint32_t sender_port = getUint32(client_config, "sender-port");
1530 
1531  uint32_t max_queue_size = getUint32(client_config, "max-queue-size");
1532 
1533  dhcp_ddns::NameChangeProtocol ncr_protocol =
1534  getProtocol(client_config, "ncr-protocol");
1535 
1536  dhcp_ddns::NameChangeFormat ncr_format =
1537  getFormat(client_config, "ncr-format");
1538 
1539  IOAddress sender_ip(0);
1540  if (sender_ip_str.empty()) {
1541  // The default sender IP depends on the server IP family
1542  sender_ip = (server_ip.isV4() ? IOAddress::IPV4_ZERO_ADDRESS() :
1544  } else {
1545  try {
1546  sender_ip = IOAddress(sender_ip_str);
1547  } catch (const std::exception& ex) {
1548  isc_throw(DhcpConfigError, "invalid address (" << sender_ip_str
1549  << ") specified for parameter 'sender-ip' ("
1550  << getPosition("sender-ip", client_config) << ")");
1551  }
1552  }
1553 
1554  // Now we check for logical errors. This repeats what is done in
1555  // D2ClientConfig::validate(), but doing it here permits us to
1556  // emit meaningful parameter position info in the error.
1557  if (ncr_format != dhcp_ddns::FMT_JSON) {
1558  isc_throw(D2ClientError, "D2ClientConfig error: NCR Format: "
1559  << dhcp_ddns::ncrFormatToString(ncr_format)
1560  << " is not supported. ("
1561  << getPosition("ncr-format", client_config) << ")");
1562  }
1563 
1564  if (ncr_protocol != dhcp_ddns::NCR_UDP) {
1565  isc_throw(D2ClientError, "D2ClientConfig error: NCR Protocol: "
1566  << dhcp_ddns::ncrProtocolToString(ncr_protocol)
1567  << " is not supported. ("
1568  << getPosition("ncr-protocol", client_config) << ")");
1569  }
1570 
1571  if (sender_ip.getFamily() != server_ip.getFamily()) {
1573  "D2ClientConfig error: address family mismatch: "
1574  << "server-ip: " << server_ip.toText()
1575  << " is: " << (server_ip.isV4() ? "IPv4" : "IPv6")
1576  << " while sender-ip: " << sender_ip.toText()
1577  << " is: " << (sender_ip.isV4() ? "IPv4" : "IPv6")
1578  << " (" << getPosition("sender-ip", client_config) << ")");
1579  }
1580 
1581  if (server_ip == sender_ip && server_port == sender_port) {
1583  "D2ClientConfig error: server and sender cannot"
1584  " share the exact same IP address/port: "
1585  << server_ip.toText() << "/" << server_port
1586  << " (" << getPosition("sender-ip", client_config) << ")");
1587  }
1588 
1589  try {
1590  // Attempt to create the new client config.
1591  new_config.reset(new D2ClientConfig(enable_updates,
1592  server_ip,
1593  server_port,
1594  sender_ip,
1595  sender_port,
1596  max_queue_size,
1597  ncr_protocol,
1598  ncr_format));
1599  } catch (const std::exception& ex) {
1600  isc_throw(DhcpConfigError, ex.what() << " ("
1601  << client_config->getPosition() << ")");
1602  }
1603 
1604  // Add user context
1605  ConstElementPtr user_context = client_config->get("user-context");
1606  if (user_context) {
1607  new_config->setContext(user_context);
1608  }
1609 
1610  return (new_config);
1611 }
1612 
1615  // enable-updates is unconditionally required
1616  { "server-ip", Element::string, "127.0.0.1" },
1617  { "server-port", Element::integer, "53001" },
1618  // default sender-ip depends on server-ip family, so we leave default blank
1619  // parser knows to use the appropriate ZERO address based on server-ip
1620  { "sender-ip", Element::string, "" },
1621  { "sender-port", Element::integer, "0" },
1622  { "max-queue-size", Element::integer, "1024" },
1623  { "ncr-protocol", Element::string, "UDP" },
1624  { "ncr-format", Element::string, "JSON" }
1625 };
1626 
1627 size_t
1629  ElementPtr mutable_d2 = boost::const_pointer_cast<Element>(d2_config);
1630  return (SimpleParser::setDefaults(mutable_d2, D2_CLIENT_CONFIG_DEFAULTS));
1631 }
1632 
1633 } // namespace dhcp
1634 } // namespace isc
void parseDdnsParams(const data::ConstElementPtr &network_data, NetworkPtr &network)
Parses parameters pertaining to DDNS behavior.
static const size_t MAX_SNAME_LEN
length of the SNAME field in DHCPv4 message
Definition: pkt4.h:44
IfacePtr getIface(int ifindex)
Returns interface specified interface index.
Definition: iface_mgr.cc:902
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
static bool getBoolean(isc::data::ConstElementPtr scope, const std::string &name)
Returns a boolean parameter from a scope.
virtual boost::shared_ptr< PoolsListParser > createPoolsListParser() const
Returns an instance of the Pools4ListParser to be used in parsing the address pools.
virtual boost::shared_ptr< PdPoolsListParser > createPdPoolsListParser() const
Returns an instance of the PdPools6ListParser to be used in parsing the prefix delegation pools...
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
Definition: optional.h:136
static int64_t getInteger(isc::data::ConstElementPtr scope, const std::string &name)
Returns an integer parameter from a scope.
D2ClientConfigPtr parse(isc::data::ConstElementPtr d2_client_cfg)
Parses a given dhcp-ddns element into D2ClientConfig.
void validateResvs(const Subnet6Ptr &subnet, ConstHostPtr host)
Verifies host reservation addresses are in the subnet range.
virtual void duplicate_option_warning(uint32_t code, asiolink::IOAddress &addr)
Issues a DHCP6 server specific warning regarding duplicate subnet options.
boost::shared_ptr< CfgOption > CfgOptionPtr
Non-const pointer.
Definition: cfg_option.h:745
isc::dhcp::Pool6Ptr pool_
Pointer to the created pool object.
Definition: dhcp_parsers.h:798
size_t parse(SrvConfigPtr cfg, data::ConstElementPtr subnets_list)
parses contents of the list
boost::shared_ptr< Network > NetworkPtr
Pointer to the Network object.
Definition: network.h:70
Base class representing a DHCP option definition.
NameChangeProtocol stringToNcrProtocol(const std::string &protocol_str)
Function which converts text labels to NameChangeProtocol enums.
Definition: ncr_io.cc:23
static const isc::data::SimpleKeywords OPTION4_DEF_PARAMETERS
This table defines all option definition parameters.
this class parses a single subnet
Definition: dhcp_parsers.h:503
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
isc::util::Triplet< uint32_t > getPreferred(const Inheritance &inheritance=Inheritance::ALL) const
Returns preferred lifetime (in seconds)
Definition: network.h:1325
static const isc::data::SimpleDefaults D2_CLIENT_CONFIG_DEFAULTS
Defaults for the D2 client configuration.
std::vector< SimpleDefault > SimpleDefaults
This specifies all default values in a given scope (e.g. a subnet).
boost::shared_ptr< Network::RelayInfo > RelayInfoPtr
Pointer to the RelayInfo structure.
Definition: network.h:210
void parseCommon(const data::ConstElementPtr &network_data, NetworkPtr &network)
Parses common parameters.
static const size_t MAX_FILE_LEN
length of the FILE field in DHCPv4 message
Definition: pkt4.h:47
virtual boost::shared_ptr< OptionDataListParser > createOptionDataListParser(const uint16_t address_family) const
Returns an instance of the OptionDataListParser to be used in parsing the option-data structure...
static bool validateName(const std::string &name)
Checks that the provided option space name is valid.
Definition: option_space.cc:26
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
Subnets6ListConfigParser(bool check_iface=true)
constructor
boost::shared_ptr< SrvConfig > SrvConfigPtr
Non-const pointer to the SrvConfig.
Definition: srv_config.h:1165
virtual boost::shared_ptr< OptionDataListParser > createOptionDataListParser() const
Returns an instance of the OptionDataListParser to be used in parsing the option-data structure...
boost::shared_ptr< Option > OptionPtr
Definition: option.h:36
boost::shared_ptr< Subnet4 > Subnet4Ptr
A pointer to a Subnet4 object.
Definition: subnet.h:524
virtual boost::shared_ptr< PoolsListParser > createPoolsListParser() const
Returns an instance of the Pools6ListParser to be used in parsing the address pools.
boost::shared_ptr< const CfgGlobals > ConstCfgGlobalsPtr
Const shared pointer to a CfgGlobals instance.
Definition: cfg_globals.h:159
void setControlSocketInfo(const isc::data::ConstElementPtr &control_socket)
Sets information about the control socket.
Definition: srv_config.h:529
const isc::log::MessageID DHCPSRV_CFGMGR_RELAY_IP_ADDRESS_DEPRECATED
void clear()
Removes any configured MAC/Hardware address sources.
Universe
defines option universe DHCPv4 or DHCPv6
Definition: option.h:83
T get() const
Retrieves the encapsulated value.
Definition: optional.h:114
void add(uint32_t source)
Adds additional MAC/hardware address acquisition.
void parseCacheParams(const data::ConstElementPtr &network_data, NetworkPtr &network)
Parses parameters related to lease cache settings.
boost::shared_ptr< Element > ElementPtr
Definition: data.h:24
virtual boost::shared_ptr< Subnet4ConfigParser > createSubnetConfigParser() const
Returns an instance of the Subnet4ConfigParser to be used in parsing the subnets. ...
STL namespace.
std::vector< HostPtr > HostCollection
Collection of the Host objects.
Definition: host.h:810
CfgOptionPtr options_
Pointer to the options configuration.
Definition: dhcp_parsers.h:578
static void setRuntimeOptionDefs(const OptionDefSpaceContainer &defs)
Copies option definitions created at runtime.
Definition: libdhcp++.cc:214
Subnet4Ptr parse(data::ConstElementPtr subnet)
Parses a single IPv4 subnet configuration and adds to the Configuration Manager.
NameChangeFormat
Defines the list of data wire formats supported.
Definition: ncr_msg.h:60
A configuration holder for IPv4 subnet.
Definition: subnet.h:531
void setInterfaceId(const OptionPtr &ifaceid)
sets interface-id option (if defined)
Definition: network.h:1352
boost::shared_ptr< CfgOptionDef > CfgOptionDefPtr
Non-const pointer.
CfgOptionPtr getCfgOption()
Returns pointer to the option data configuration for this network.
Definition: network.h:474
boost::shared_ptr< Pool > PoolPtr
a pointer to either IPv4 or IPv6 Pool
Definition: pool.h:505
OptionDefinitionPtr parse(isc::data::ConstElementPtr option_def)
Parses an entry that describes single option definition.
Definition: dhcp_parsers.cc:97
virtual boost::shared_ptr< OptionDataListParser > createOptionDataListParser() const
Returns an instance of the OptionDataListParser to be used in parsing the option-data structure...
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
PdPoolParser()
Constructor.
const isc::log::MessageID DHCPSRV_CFGMGR_NEW_SUBNET6
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:24
PoolStoragePtr pools_
Storage for pools belonging to this subnet.
Definition: dhcp_parsers.h:566
static const isc::data::SimpleKeywords SUBNET4_PARAMETERS
This table defines all subnet parameters for DHCPv4.
void parse(const SubnetID &subnet_id, isc::data::ConstElementPtr hr_list, HostCollection &hosts_list)
Parses a list of host reservation entries for a subnet.
Holds optional information about relay.
Definition: network.h:162
OptionDefListParser(const uint16_t address_family)
Constructor.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
std::string ncrProtocolToString(NameChangeProtocol protocol)
Function which converts NameChangeProtocol enums to text labels.
Definition: ncr_io.cc:36
static const isc::data::SimpleKeywords PD_POOL6_PARAMETERS
This table defines all prefix delegation pool parameters.
static const isc::data::SimpleKeywords SUBNET6_PARAMETERS
This table defines all subnet parameters for DHCPv6.
Subnets4ListConfigParser(bool check_iface=true)
constructor
void initSubnet(isc::data::ConstElementPtr params, isc::asiolink::IOAddress addr, uint8_t len)
Instantiates the IPv6 Subnet based on a given IPv6 address and prefix length.
void addAddress(const std::string &name, const std::string &address_str, isc::data::ConstElementPtr relay_elem, const isc::dhcp::Network::RelayInfoPtr &relay_info)
Attempts to add an IP address to list of relay addresses.
void createSubnet(isc::data::ConstElementPtr data)
Create a new subnet using a data from child parsers.
Definition: edns.h:19
std::pair< IPv6ResrvIterator, IPv6ResrvIterator > IPv6ResrvRange
Definition: host.h:243
Pool information for IPv6 addresses and prefixes.
Definition: pool.h:321
Represents option data configuration for the DHCP server.
Definition: cfg_option.h:318
boost::multi_index_container< Subnet4Ptr, boost::multi_index::indexed_by< boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetSubnetIdIndexTag >, boost::multi_index::const_mem_fun< Subnet, SubnetID, &Subnet::getID > >, boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetPrefixIndexTag >, boost::multi_index::const_mem_fun< Subnet, std::string, &Subnet::toText > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetServerIdIndexTag >, boost::multi_index::const_mem_fun< Network4, asiolink::IOAddress, &Network4::getServerId > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetModificationTimeIndexTag >, boost::multi_index::const_mem_fun< data::BaseStampedElement, boost::posix_time::ptime, &data::BaseStampedElement::getModificationTime > > >> Subnet4Collection
A collection of Subnet4 objects.
Definition: subnet.h:893
vector< string > tokens(const std::string &text, const std::string &delim, bool escape)
Split String into Tokens.
Definition: strutil.cc:77
An exception that is thrown if an error occurs while configuring the D2 DHCP DDNS client...
Definition: d2_client_cfg.h:34
Wrapper class that holds MAC/hardware address sources.
const int DHCPSRV_DBG_TRACE_DETAIL
Additional information.
Definition: dhcpsrv_log.h:38
parser for additional relay information
Definition: dhcp_parsers.h:440
To be removed. Please use ConfigError instead.
Acts as a storage vault for D2 client configuration.
Definition: d2_client_cfg.h:57
uint8_t getUint8(ConstElementPtr scope, const std::string &name)
Get an uint8_t value.
void allowClientClass(const isc::dhcp::ClientClass &class_name)
Sets the supported class to class class_name.
Definition: network.cc:80
void parseTeePercents(const data::ConstElementPtr &network_data, NetworkPtr &network)
Parses parameters related to "percent" timers settings.
void setRapidCommit(const util::Optional< bool > &rapid_commit)
Enables or disables Rapid Commit option support for the subnet.
Definition: network.h:1374
Parser for a single option definition.
Definition: dhcp_parsers.h:228
A generic exception that is thrown when an unexpected error condition occurs.
virtual void initSubnet(isc::data::ConstElementPtr params, isc::asiolink::IOAddress addr, uint8_t len)=0
Instantiates the subnet based on a given IP prefix and prefix length.
Common interface representing a network to which the DHCP clients are connected.
Definition: network.h:152
static size_t setDefaults(isc::data::ElementPtr scope, const SimpleDefaults &default_values)
Sets the default values.
T get(T hint) const
Returns value with a hint.
Definition: triplet.h:99
static void moveReservationMode(isc::data::ElementPtr config)
Moves deprecated reservation-mode parameter to new reservations flags.
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
Definition: host.h:804
static std::string getString(isc::data::ConstElementPtr scope, const std::string &name)
Returns a string parameter from a scope.
const isc::log::MessageID DHCPSRV_CFGMGR_NEW_SUBNET4
static const isc::data::SimpleKeywords POOL6_PARAMETERS
This table defines all pool parameters.
void initSubnet(data::ConstElementPtr params, asiolink::IOAddress addr, uint8_t len)
Instantiates the IPv4 Subnet based on a given IPv4 address and prefix length.
uint32_t getUint32(isc::data::ConstElementPtr scope, const std::string &name)
Returns a value converted to uint32_t.
size_t parse(SrvConfigPtr cfg, data::ConstElementPtr subnets_list)
parses contents of the list
isc::data::ConstElementPtr client_class_
Client class (a client has to belong to to use this pd-pool)
Definition: dhcp_parsers.h:811
boost::multi_index_container< Subnet6Ptr, boost::multi_index::indexed_by< boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetSubnetIdIndexTag >, boost::multi_index::const_mem_fun< Subnet, SubnetID, &Subnet::getID > >, boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetPrefixIndexTag >, boost::multi_index::const_mem_fun< Subnet, std::string, &Subnet::toText > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetModificationTimeIndexTag >, boost::multi_index::const_mem_fun< data::BaseStampedElement, boost::posix_time::ptime, &data::BaseStampedElement::getModificationTime > > >> Subnet6Collection
A collection of Subnet6 objects.
Definition: subnet.h:964
Specifies current DHCP configuration.
Definition: srv_config.h:177
SubnetConfigParser(uint16_t family, bool check_iface=true)
constructor
isc::util::Triplet< uint32_t > getT1(const Inheritance &inheritance=Inheritance::ALL) const
Returns T1 (renew timer), expressed in seconds.
Definition: network.h:392
static const data::Element::Position & getPosition(const std::string &name, const data::ConstElementPtr parent)
Utility method that returns position of an element.
CfgOptionPtr options_
A storage for pool specific option values.
Definition: dhcp_parsers.h:801
This is a base class for exceptions thrown from the DNS library module.
static isc::asiolink::IOAddress getAddress(const ConstElementPtr &scope, const std::string &name)
Returns a IOAddress parameter from a scope.
Defines the logger used by the top-level component of kea-lfc.
virtual boost::shared_ptr< PoolParser > createPoolConfigParser() const
Returns an instance of the Pool6Parser to be used in parsing the address pools.
virtual boost::shared_ptr< PoolParser > createPoolConfigParser() const
Returns an instance of the Pool4Parser to be used in parsing the address pools.
bool check_iface_
Check if the specified interface exists in the system.
Definition: dhcp_parsers.h:973
static const isc::data::SimpleKeywords POOL4_PARAMETERS
This table defines all pool parameters.
ReplaceClientNameMode
Defines the client name replacement modes.
Definition: d2_client_cfg.h:76
A configuration holder for IPv6 subnet.
Definition: subnet.h:679
uint16_t address_family_
Address family: AF_INET or AF_INET6.
Definition: dhcp_parsers.h:572
PoolPtr poolMaker(asiolink::IOAddress &addr, uint32_t len, int32_t ignored)
Creates a Pool4 object given a IPv4 prefix and the prefix length.
target_type getAndConvert(isc::data::ConstElementPtr scope, const std::string &name, const std::string &type_name)
Returns a converted value from a scope.
SubnetPtr parse(isc::data::ConstElementPtr subnet)
parses a subnet description and returns Subnet{4,6} structure
void requireClientClass(const isc::dhcp::ClientClass &class_name)
Adds class class_name to classes required to be evaluated.
Definition: network.cc:85
bool check_iface_
Check if the specified interface exists in the system.
Definition: dhcp_parsers.h:685
isc::util::Triplet< uint32_t > getValid(const Inheritance &inheritance=Inheritance::ALL) const
Return valid-lifetime for addresses in that prefix.
Definition: network.h:375
#define DHCP6_OPTION_SPACE
std::string ncrFormatToString(NameChangeFormat format)
Function which converts NameChangeFormat enums to text labels.
Definition: ncr_msg.cc:35
Subnet6Ptr parse(data::ConstElementPtr subnet)
Parses a single IPv6 subnet configuration and adds to the Configuration Manager.
void parse(const isc::dhcp::Network::RelayInfoPtr &relay_info, isc::data::ConstElementPtr relay_elem)
parses the actual relay parameters
static IfaceMgr & instance()
IfaceMgr is a singleton class.
Definition: iface_mgr.cc:53
isc::dhcp::SubnetPtr subnet_
Pointer to the created subnet object.
Definition: dhcp_parsers.h:569
#define DHCP4_OPTION_SPACE
global std option spaces
PoolPtr poolMaker(asiolink::IOAddress &addr, uint32_t len, int32_t ptype)
Creates a Pool6 object given a IPv6 prefix and the prefix length.
static void checkKeywords(const SimpleKeywords &keywords, isc::data::ConstElementPtr scope)
Checks acceptable keywords with their expected type.
The Element class represents a piece of data, used by the command channel and configuration parts...
Definition: data.h:70
static const isc::data::SimpleKeywords OPTION6_DEF_PARAMETERS
This table defines all option definition parameters.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
isc::dhcp::Network::RelayInfoPtr relay_info_
Pointer to relay information.
Definition: dhcp_parsers.h:575
void parse(PoolStoragePtr pools, data::ConstElementPtr pools_list)
parses the actual structure
const isc::util::Triplet< uint32_t > parseIntTriplet(const data::ConstElementPtr &scope, const std::string &name)
Parses an integer triplet.
NameChangeProtocol
Defines the list of socket protocols supported.
Definition: ncr_io.h:68
boost::shared_ptr< PoolStorage > PoolStoragePtr
Definition: dhcp_parsers.h:281
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
void setIface(const util::Optional< std::string > &iface_name)
Sets local name of the interface for which this network is selected.
Definition: network.h:255
static size_t setAllDefaults(isc::data::ConstElementPtr d2_config)
Sets all defaults for D2 client configuration.
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
NameChangeFormat stringToNcrFormat(const std::string &fmt_str)
Function which converts labels to NameChangeFormat enum values.
Definition: ncr_msg.cc:26
isc::data::ConstElementPtr user_context_
User context (optional, may be null)
Definition: dhcp_parsers.h:806
string trim(const string &instring)
Trim Leading and Trailing Spaces.
Definition: strutil.cc:53
isc::util::Triplet< uint32_t > getT2(const Inheritance &inheritance=Inheritance::ALL) const
Returns T2 (rebind timer), expressed in seconds.
Definition: network.h:407
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
virtual boost::shared_ptr< Subnet6ConfigParser > createSubnetConfigParser() const
Returns an instance of the Subnet6ConfigParser to be used in parsing the subnets. ...
Subnet4ConfigParser(bool check_iface=true)
Constructor.
Parser for a list of host reservations for a subnet.
boost::shared_ptr< Subnet6 > Subnet6Ptr
A pointer to a Subnet6 object.
Definition: subnet.h:672
util::Optional< bool > getRapidCommit(const Inheritance &inheritance=Inheritance::ALL) const
Returns boolean value indicating that the Rapid Commit option is supported or unsupported for the sub...
Definition: network.h:1364
void parse(CfgOptionDefPtr cfg, isc::data::ConstElementPtr def_list)
Parses a list of option definitions, create them and store in cfg.
const isc::log::MessageID DHCPSRV_CFGMGR_OPTION_DUPLICATE
virtual void parse(PoolStoragePtr pools, isc::data::ConstElementPtr pool_structure, const uint16_t address_family)
parses the actual structure
Subnet6ConfigParser(bool check_iface=true)
Constructor.
bool empty() const
Checks if the encapsulated value is empty.
Definition: optional.h:153
boost::shared_ptr< D2ClientConfig > D2ClientConfigPtr
Defines a pointer for D2ClientConfig instances.
virtual boost::shared_ptr< PdPoolParser > createPdPoolConfigParser() const
Returns an instance of the PdPoolParser to be used in parsing the prefix delegation pools...
bool check_iface_
Check if the specified interface exists in the system.
Definition: dhcp_parsers.h:581
void parse(PoolStoragePtr pools, data::ConstElementPtr pd_pool_list)
Parse configuration entries.
void validateResv(const Subnet4Ptr &subnet, ConstHostPtr host)
Verifies the host reservation address is in the subnet range.
void parse(PoolStoragePtr pools, data::ConstElementPtr pd_pool_)
Builds a prefix delegation pool from the given configuration.
std::vector< PoolPtr > PoolStorage
a collection of pools
Definition: dhcp_parsers.h:280
virtual std::string toText() const
Returns textual representation of the subnet (e.g.
Definition: subnet.cc:174
boost::shared_ptr< Subnet > SubnetPtr
A generic pointer to either Subnet4 or Subnet6 object.
Definition: subnet.h:515
RelayInfoParser(const isc::dhcp::Option::Universe &family)
constructor
static ReplaceClientNameMode stringToReplaceClientNameMode(const std::string &mode_str)
Converts labels to ReplaceClientNameMode enum values.
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition: subnet_id.h:24
Pool information for IPv4 addresses.
Definition: pool.h:262
void parse(PoolStoragePtr pools, data::ConstElementPtr pools_list)
parses the actual structure
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition: cfgmgr.cc:167