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