Kea  2.1.6-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  SubnetID subnet_id = static_cast<SubnetID>(getInteger(params, "id"));
729 
730  Subnet4Ptr subnet4(new Subnet4(addr, len, Triplet<uint32_t>(),
732  subnet_id));
733  subnet_ = subnet4;
734 
735  // Move from reservation mode to new reservations flags.
736  ElementPtr mutable_params;
737  mutable_params = boost::const_pointer_cast<Element>(params);
738  // @todo add warning
740 
741  // Parse parameters common to all Network derivations.
742  NetworkPtr network = boost::dynamic_pointer_cast<Network>(subnet4);
743  parseCommon(mutable_params, network);
744 
745  std::ostringstream output;
746  output << addr << "/" << static_cast<int>(len) << " with params: ";
747 
748  bool has_renew = !subnet4->getT1().unspecified();
749  bool has_rebind = !subnet4->getT2().unspecified();
750  int64_t renew = -1;
751  int64_t rebind = -1;
752 
753  // t1 and t2 are optional may be not specified.
754  if (has_renew) {
755  renew = subnet4->getT1().get();
756  output << "t1=" << renew << ", ";
757  }
758  if (has_rebind) {
759  rebind = subnet4->getT2().get();
760  output << "t2=" << rebind << ", ";
761  }
762 
763  if (has_renew && has_rebind && (renew > rebind)) {
764  isc_throw(DhcpConfigError, "the value of renew-timer (" << renew
765  << ") is greater than the value of rebind-timer ("
766  << rebind << ")");
767  }
768 
769  if (!subnet4->getValid().unspecified()) {
770  output << "valid-lifetime=" << subnet4->getValid().get();
771  }
772 
774 
775  // Set the match-client-id value for the subnet.
776  if (params->contains("match-client-id")) {
777  bool match_client_id = getBoolean(params, "match-client-id");
778  subnet4->setMatchClientId(match_client_id);
779  }
780 
781  // Set the authoritative value for the subnet.
782  if (params->contains("authoritative")) {
783  bool authoritative = getBoolean(params, "authoritative");
784  subnet4->setAuthoritative(authoritative);
785  }
786 
787  // Set next-server. The default value is 0.0.0.0. Nevertheless, the
788  // user could have messed that up by specifying incorrect value.
789  // To avoid using 0.0.0.0, user can specify "".
790  if (params->contains("next-server")) {
791  string next_server;
792  try {
793  next_server = getString(params, "next-server");
794  if (!next_server.empty()) {
795  subnet4->setSiaddr(IOAddress(next_server));
796  }
797  } catch (...) {
798  ConstElementPtr next = params->get("next-server");
799  string pos;
800  if (next) {
801  pos = next->getPosition().str();
802  } else {
803  pos = params->getPosition().str();
804  }
805  isc_throw(DhcpConfigError, "invalid parameter next-server : "
806  << next_server << "(" << pos << ")");
807  }
808  }
809 
810  // Set server-hostname.
811  if (params->contains("server-hostname")) {
812  std::string sname = getString(params, "server-hostname");
813  if (!sname.empty()) {
814  if (sname.length() >= Pkt4::MAX_SNAME_LEN) {
815  ConstElementPtr error = params->get("server-hostname");
816  isc_throw(DhcpConfigError, "server-hostname must be at most "
817  << Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is "
818  << sname.length() << " ("
819  << error->getPosition() << ")");
820  }
821  subnet4->setSname(sname);
822  }
823  }
824 
825  // Set boot-file-name.
826  if (params->contains("boot-file-name")) {
827  std::string filename =getString(params, "boot-file-name");
828  if (!filename.empty()) {
829  if (filename.length() > Pkt4::MAX_FILE_LEN) {
830  ConstElementPtr error = params->get("boot-file-name");
831  isc_throw(DhcpConfigError, "boot-file-name must be at most "
832  << Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is "
833  << filename.length() << " ("
834  << error->getPosition() << ")");
835  }
836  subnet4->setFilename(filename);
837  }
838  }
839 
840  // Get interface name. If it is defined, then the subnet is available
841  // directly over specified network interface.
842  if (params->contains("interface")) {
843  std::string iface = getString(params, "interface");
844  if (!iface.empty()) {
845  if (check_iface_ && !IfaceMgr::instance().getIface(iface)) {
846  ConstElementPtr error = params->get("interface");
847  isc_throw(DhcpConfigError, "Specified network interface name " << iface
848  << " for subnet " << subnet4->toText()
849  << " is not present in the system ("
850  << error->getPosition() << ")");
851  }
852 
853  subnet4->setIface(iface);
854  }
855  }
856 
857  // Try setting up client class.
858  if (params->contains("client-class")) {
859  string client_class = getString(params, "client-class");
860  if (!client_class.empty()) {
861  subnet4->allowClientClass(client_class);
862  }
863  }
864 
865  // Try setting up required client classes.
866  ConstElementPtr class_list = params->get("require-client-classes");
867  if (class_list) {
868  const std::vector<data::ElementPtr>& classes = class_list->listValue();
869  for (auto cclass = classes.cbegin();
870  cclass != classes.cend(); ++cclass) {
871  if (((*cclass)->getType() != Element::string) ||
872  (*cclass)->stringValue().empty()) {
873  isc_throw(DhcpConfigError, "invalid class name ("
874  << (*cclass)->getPosition() << ")");
875  }
876  subnet4->requireClientClass((*cclass)->stringValue());
877  }
878  }
879 
880  // 4o6 specific parameter: 4o6-interface.
881  if (params->contains("4o6-interface")) {
882  string iface4o6 = getString(params, "4o6-interface");
883  if (!iface4o6.empty()) {
884  subnet4->get4o6().setIface4o6(iface4o6);
885  subnet4->get4o6().enabled(true);
886  }
887  }
888 
889  // 4o6 specific parameter: 4o6-subnet.
890  if (params->contains("4o6-subnet")) {
891  string subnet4o6 = getString(params, "4o6-subnet");
892  if (!subnet4o6.empty()) {
893  size_t slash = subnet4o6.find("/");
894  if (slash == std::string::npos) {
895  isc_throw(DhcpConfigError, "Missing / in the 4o6-subnet parameter:"
896  << subnet4o6 << ", expected format: prefix6/length");
897  }
898  string prefix = subnet4o6.substr(0, slash);
899  string lenstr = subnet4o6.substr(slash + 1);
900 
901  uint8_t len = 128;
902  try {
903  len = boost::lexical_cast<unsigned int>(lenstr.c_str());
904  } catch (const boost::bad_lexical_cast &) {
905  isc_throw(DhcpConfigError, "Invalid prefix length specified in "
906  "4o6-subnet parameter: " << subnet4o6 << ", expected 0..128 value");
907  }
908  subnet4->get4o6().setSubnet4o6(IOAddress(prefix), len);
909  subnet4->get4o6().enabled(true);
910  }
911  }
912 
913  // Try 4o6 specific parameter: 4o6-interface-id
914  if (params->contains("4o6-interface-id")) {
915  std::string ifaceid = getString(params, "4o6-interface-id");
916  if (!ifaceid.empty()) {
917  OptionBuffer tmp(ifaceid.begin(), ifaceid.end());
919  subnet4->get4o6().setInterfaceId(opt);
920  subnet4->get4o6().enabled(true);
921  }
922  }
923 
926 
927  // Here globally defined options were merged to the subnet specific
928  // options but this is no longer the case (they have a different
929  // and not consecutive priority).
930 
931  // Copy options to the subnet configuration.
932  options_->copyTo(*subnet4->getCfgOption());
933 
934  // Parse t1-percent and t2-percent
935  parseTeePercents(params, network);
936 
937  // Parse DDNS parameters
938  parseDdnsParams(params, network);
939 
940  // Parse lease cache parameters
941  parseCacheParams(params, network);
942 }
943 
944 void
946  const IOAddress& address = host->getIPv4Reservation();
947  if (!address.isV4Zero() && !subnet->inRange(address)) {
948  isc_throw(DhcpConfigError, "specified reservation '" << address
949  << "' is not within the IPv4 subnet '"
950  << subnet->toText() << "'");
951  }
952 }
953 
954 boost::shared_ptr<PoolsListParser>
956  auto parser = boost::make_shared<Pools4ListParser>();
957  return (parser);
958 }
959 
960 //**************************** Subnets4ListConfigParser **********************
961 
963  : check_iface_(check_iface) {
964 }
965 
966 size_t
968  ConstElementPtr subnets_list) {
969  size_t cnt = 0;
970  BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
971 
972  auto parser = createSubnetConfigParser();
973  Subnet4Ptr subnet = parser->parse(subnet_json);
974  if (subnet) {
975 
976  // Adding a subnet to the Configuration Manager may fail if the
977  // subnet id is invalid (duplicate). Thus, we catch exceptions
978  // here to append a position in the configuration string.
979  try {
980  cfg->getCfgSubnets4()->add(subnet);
981  cnt++;
982  } catch (const std::exception& ex) {
983  isc_throw(DhcpConfigError, ex.what() << " ("
984  << subnet_json->getPosition() << ")");
985  }
986  }
987  }
988  return (cnt);
989 }
990 
991 size_t
993  data::ConstElementPtr subnets_list) {
994  size_t cnt = 0;
995  BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
996 
997  auto parser = createSubnetConfigParser();
998  Subnet4Ptr subnet = parser->parse(subnet_json);
999  if (subnet) {
1000  try {
1001  auto ret = subnets.insert(subnet);
1002  if (!ret.second) {
1004  "can't store subnet because of conflict");
1005  }
1006  ++cnt;
1007  } catch (const std::exception& ex) {
1008  isc_throw(DhcpConfigError, ex.what() << " ("
1009  << subnet_json->getPosition() << ")");
1010  }
1011  }
1012  }
1013  return (cnt);
1014 }
1015 
1016 boost::shared_ptr<Subnet4ConfigParser>
1018  auto parser = boost::make_shared<Subnet4ConfigParser>(check_iface_);
1019  return (parser);
1020 }
1021 
1022 //**************************** Pool6Parser *********************************
1023 
1024 PoolPtr
1025 Pool6Parser::poolMaker (IOAddress &addr, uint32_t len, int32_t ptype)
1026 {
1027  return (PoolPtr(new Pool6(static_cast<isc::dhcp::Lease::Type>
1028  (ptype), addr, len)));
1029 }
1030 
1031 PoolPtr
1032 Pool6Parser::poolMaker (IOAddress &min, IOAddress &max, int32_t ptype)
1033 {
1034  return (PoolPtr(new Pool6(static_cast<isc::dhcp::Lease::Type>
1035  (ptype), min, max)));
1036 }
1037 
1038 
1039 //**************************** Pool6ListParser ***************************
1040 
1041 void
1043  BOOST_FOREACH(ConstElementPtr pool, pools_list->listValue()) {
1044  auto parser = createPoolConfigParser();
1045  parser->parse(pools, pool, AF_INET6);
1046  }
1047 }
1048 
1049 boost::shared_ptr<PoolParser>
1051  auto parser = boost::make_shared<Pool6Parser>();
1052  return (parser);
1053 }
1054 
1055 //**************************** PdPoolParser ******************************
1056 
1058 }
1059 
1060 void
1063 
1064  std::string addr_str = getString(pd_pool_, "prefix");
1065 
1066  uint8_t prefix_len = getUint8(pd_pool_, "prefix-len");
1067 
1068  uint8_t delegated_len = getUint8(pd_pool_, "delegated-len");
1069 
1070  std::string excluded_prefix_str = "::";
1071  if (pd_pool_->contains("excluded-prefix")) {
1072  excluded_prefix_str = getString(pd_pool_, "excluded-prefix");
1073  }
1074 
1075  uint8_t excluded_prefix_len = 0;
1076  if (pd_pool_->contains("excluded-prefix-len")) {
1077  excluded_prefix_len = getUint8(pd_pool_, "excluded-prefix-len");
1078  }
1079 
1080  ConstElementPtr option_data = pd_pool_->get("option-data");
1081  if (option_data) {
1082  auto opts_parser = createOptionDataListParser();
1083  opts_parser->parse(options_, option_data);
1084  }
1085 
1086  ConstElementPtr user_context = pd_pool_->get("user-context");
1087  if (user_context) {
1088  user_context_ = user_context;
1089  }
1090 
1091  ConstElementPtr client_class = pd_pool_->get("client-class");
1092  if (client_class) {
1093  client_class_ = client_class;
1094  }
1095 
1096  ConstElementPtr class_list = pd_pool_->get("require-client-classes");
1097 
1098  // Check the pool parameters. It will throw an exception if any
1099  // of the required parameters are invalid.
1100  try {
1101  // Attempt to construct the local pool.
1102  pool_.reset(new Pool6(IOAddress(addr_str),
1103  prefix_len,
1104  delegated_len,
1105  IOAddress(excluded_prefix_str),
1106  excluded_prefix_len));
1107  // Merge options specified for a pool into pool configuration.
1108  options_->copyTo(*pool_->getCfgOption());
1109  } catch (const std::exception& ex) {
1110  // Some parameters don't exist or are invalid. Since we are not
1111  // aware whether they don't exist or are invalid, let's append
1112  // the position of the pool map element.
1114  << " (" << pd_pool_->getPosition() << ")");
1115  }
1116 
1117  if (user_context_) {
1118  pool_->setContext(user_context_);
1119  }
1120 
1121  if (client_class_) {
1122  string cclass = client_class_->stringValue();
1123  if (!cclass.empty()) {
1124  pool_->allowClientClass(cclass);
1125  }
1126  }
1127 
1128  if (class_list) {
1129  const std::vector<data::ElementPtr>& classes = class_list->listValue();
1130  for (auto cclass = classes.cbegin();
1131  cclass != classes.cend(); ++cclass) {
1132  if (((*cclass)->getType() != Element::string) ||
1133  (*cclass)->stringValue().empty()) {
1134  isc_throw(DhcpConfigError, "invalid class name ("
1135  << (*cclass)->getPosition() << ")");
1136  }
1137  pool_->requireClientClass((*cclass)->stringValue());
1138  }
1139  }
1140 
1141  // Add the local pool to the external storage ptr.
1142  pools->push_back(pool_);
1143 }
1144 
1145 boost::shared_ptr<OptionDataListParser>
1147  auto parser = boost::make_shared<OptionDataListParser>(AF_INET6);
1148  return (parser);
1149 }
1150 
1151 //**************************** PdPoolsListParser ************************
1152 
1153 void
1155  // Loop through the list of pd pools.
1156  BOOST_FOREACH(ConstElementPtr pd_pool, pd_pool_list->listValue()) {
1157  auto parser = createPdPoolConfigParser();
1158  parser->parse(pools, pd_pool);
1159  }
1160 }
1161 
1162 boost::shared_ptr<PdPoolParser>
1164  auto parser = boost::make_shared<PdPoolParser>();
1165  return (parser);
1166 }
1167 
1168 //**************************** Subnet6ConfigParser ***********************
1169 
1171  : SubnetConfigParser(AF_INET6, check_iface) {
1172 }
1173 
1174 Subnet6Ptr
1176  // Check parameters.
1178 
1180  ConstElementPtr pools = subnet->get("pools");
1181  if (pools) {
1182  auto parser = createPoolsListParser();
1183  parser->parse(pools_, pools);
1184  }
1185  ConstElementPtr pd_pools = subnet->get("pd-pools");
1186  if (pd_pools) {
1187  auto parser = createPdPoolsListParser();
1188  parser->parse(pools_, pd_pools);
1189  }
1190 
1191  SubnetPtr generic = SubnetConfigParser::parse(subnet);
1192 
1193  if (!generic) {
1194  // Sanity check: not supposed to fail.
1196  "Failed to create an IPv6 subnet (" <<
1197  subnet->getPosition() << ")");
1198  }
1199 
1200  Subnet6Ptr sn6ptr = boost::dynamic_pointer_cast<Subnet6>(subnet_);
1201  if (!sn6ptr) {
1202  // If we hit this, it is a programming error.
1204  "Invalid Subnet6 cast in Subnet6ConfigParser::parse");
1205  }
1206 
1207  // Set relay information if it was provided
1208  if (relay_info_) {
1209  sn6ptr->setRelayInfo(*relay_info_);
1210  }
1211 
1212  // Parse Host Reservations for this subnet if any.
1213  ConstElementPtr reservations = subnet->get("reservations");
1214  if (reservations) {
1215  HostCollection hosts;
1217  parser.parse(subnet_->getID(), reservations, hosts);
1218  for (auto h = hosts.begin(); h != hosts.end(); ++h) {
1219  validateResvs(sn6ptr, *h);
1220  CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(*h);
1221  }
1222  }
1223 
1224  return (sn6ptr);
1225 }
1226 
1227 // Unused?
1228 void
1230  asiolink::IOAddress& addr) {
1232  .arg(code).arg(addr.toText());
1233 }
1234 
1235 void
1237  asiolink::IOAddress addr, uint8_t len) {
1238  // Subnet ID is optional. If it is not supplied the value of 0 is used,
1239  // which means autogenerate. The value was inserted earlier by calling
1240  // SimpleParser6::setAllDefaults.
1241  SubnetID subnet_id = static_cast<SubnetID>(getInteger(params, "id"));
1242 
1243  // We want to log whether rapid-commit is enabled, so we get this
1244  // before the actual subnet creation.
1245  Optional<bool> rapid_commit;
1246  if (params->contains("rapid-commit")) {
1247  rapid_commit = getBoolean(params, "rapid-commit");
1248  }
1249 
1250  // Parse preferred lifetime as it is not parsed by the common function.
1251  Triplet<uint32_t> pref = parseIntTriplet(params, "preferred-lifetime");
1252 
1253  // Create a new subnet.
1254  Subnet6* subnet6 = new Subnet6(addr, len, Triplet<uint32_t>(),
1256  pref,
1258  subnet_id);
1259  subnet_.reset(subnet6);
1260 
1261  // Move from reservation mode to new reservations flags.
1262  ElementPtr mutable_params;
1263  mutable_params = boost::const_pointer_cast<Element>(params);
1264  // @todo add warning
1266 
1267  // Parse parameters common to all Network derivations.
1268  NetworkPtr network = boost::dynamic_pointer_cast<Network>(subnet_);
1269  parseCommon(mutable_params, network);
1270 
1271  // Enable or disable Rapid Commit option support for the subnet.
1272  if (!rapid_commit.unspecified()) {
1273  subnet6->setRapidCommit(rapid_commit);
1274  }
1275 
1276  std::ostringstream output;
1277  output << addr << "/" << static_cast<int>(len) << " with params: ";
1278  // t1 and t2 are optional may be not specified.
1279 
1280  bool has_renew = !subnet6->getT1().unspecified();
1281  bool has_rebind = !subnet6->getT2().unspecified();
1282  int64_t renew = -1;
1283  int64_t rebind = -1;
1284 
1285  if (has_renew) {
1286  renew = subnet6->getT1().get();
1287  output << "t1=" << renew << ", ";
1288  }
1289  if (has_rebind) {
1290  rebind = subnet6->getT2().get();
1291  output << "t2=" << rebind << ", ";
1292  }
1293 
1294  if (has_renew && has_rebind && (renew > rebind)) {
1295  isc_throw(DhcpConfigError, "the value of renew-timer (" << renew
1296  << ") is greater than the value of rebind-timer ("
1297  << rebind << ")");
1298  }
1299 
1300  if (!subnet6->getPreferred().unspecified()) {
1301  output << "preferred-lifetime=" << subnet6->getPreferred().get() << ", ";
1302  }
1303  if (!subnet6->getValid().unspecified()) {
1304  output << "valid-lifetime=" << subnet6->getValid().get();
1305  }
1306  if (!subnet6->getRapidCommit().unspecified()) {
1307  output << ", rapid-commit is "
1308  << boolalpha << subnet6->getRapidCommit().get();
1309  }
1310 
1312 
1313  // Get interface-id option content. For now we support string
1314  // representation only
1315  Optional<std::string> ifaceid;
1316  if (params->contains("interface-id")) {
1317  ifaceid = getString(params, "interface-id");
1318  }
1319 
1320  Optional<std::string> iface;
1321  if (params->contains("interface")) {
1322  iface = getString(params, "interface");
1323  }
1324 
1325  // Specifying both interface for locally reachable subnets and
1326  // interface id for relays is mutually exclusive. Need to test for
1327  // this condition.
1328  if (!ifaceid.unspecified() && !iface.unspecified() && !ifaceid.empty() &&
1329  !iface.empty()) {
1331  "parser error: interface (defined for locally reachable "
1332  "subnets) and interface-id (defined for subnets reachable"
1333  " via relays) cannot be defined at the same time for "
1334  "subnet " << addr << "/" << (int)len << "("
1335  << params->getPosition() << ")");
1336  }
1337 
1338  // Configure interface-id for remote interfaces, if defined
1339  if (!ifaceid.unspecified() && !ifaceid.empty()) {
1340  std::string ifaceid_value = ifaceid.get();
1341  OptionBuffer tmp(ifaceid_value.begin(), ifaceid_value.end());
1342  OptionPtr opt(new Option(Option::V6, D6O_INTERFACE_ID, tmp));
1343  subnet6->setInterfaceId(opt);
1344  }
1345 
1346  // Get interface name. If it is defined, then the subnet is available
1347  // directly over specified network interface.
1348  if (!iface.unspecified() && !iface.empty()) {
1349  if (check_iface_ && !IfaceMgr::instance().getIface(iface)) {
1350  ConstElementPtr error = params->get("interface");
1351  isc_throw(DhcpConfigError, "Specified network interface name " << iface
1352  << " for subnet " << subnet6->toText()
1353  << " is not present in the system ("
1354  << error->getPosition() << ")");
1355  }
1356 
1357  subnet6->setIface(iface);
1358  }
1359 
1360  // Try setting up client class.
1361  if (params->contains("client-class")) {
1362  string client_class = getString(params, "client-class");
1363  if (!client_class.empty()) {
1364  subnet6->allowClientClass(client_class);
1365  }
1366  }
1367 
1368  if (params->contains("require-client-classes")) {
1369  // Try setting up required client classes.
1370  ConstElementPtr class_list = params->get("require-client-classes");
1371  if (class_list) {
1372  const std::vector<data::ElementPtr>& classes = class_list->listValue();
1373  for (auto cclass = classes.cbegin();
1374  cclass != classes.cend(); ++cclass) {
1375  if (((*cclass)->getType() != Element::string) ||
1376  (*cclass)->stringValue().empty()) {
1377  isc_throw(DhcpConfigError, "invalid class name ("
1378  << (*cclass)->getPosition() << ")");
1379  }
1380  subnet6->requireClientClass((*cclass)->stringValue());
1381  }
1382  }
1383  }
1384 
1387 
1388  // Copy options to the subnet configuration.
1389  options_->copyTo(*subnet6->getCfgOption());
1390 
1391  // Parse t1-percent and t2-percent
1392  parseTeePercents(params, network);
1393 
1394  // Parse DDNS parameters
1395  parseDdnsParams(params, network);
1396 
1397  // Parse lease cache parameters
1398  parseCacheParams(params, network);
1399 }
1400 
1401 void
1403  IPv6ResrvRange range = host->getIPv6Reservations(IPv6Resrv::TYPE_NA);
1404  for (auto it = range.first; it != range.second; ++it) {
1405  const IOAddress& address = it->second.getPrefix();
1406  if (!subnet->inRange(address)) {
1407  isc_throw(DhcpConfigError, "specified reservation '" << address
1408  << "' is not within the IPv6 subnet '"
1409  << subnet->toText() << "'");
1410  }
1411  }
1412 }
1413 
1414 boost::shared_ptr<PoolsListParser>
1416  auto parser = boost::make_shared<Pools6ListParser>();
1417  return (parser);
1418 }
1419 
1420 boost::shared_ptr<PdPoolsListParser>
1422  auto parser = boost::make_shared<PdPoolsListParser>();
1423  return (parser);
1424 }
1425 
1426 //**************************** Subnet6ListConfigParser ********************
1427 
1429  : check_iface_(check_iface) {
1430 }
1431 
1432 size_t
1434  ConstElementPtr subnets_list) {
1435  size_t cnt = 0;
1436  BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
1437 
1438  auto parser = createSubnetConfigParser();
1439  Subnet6Ptr subnet = parser->parse(subnet_json);
1440 
1441  // Adding a subnet to the Configuration Manager may fail if the
1442  // subnet id is invalid (duplicate). Thus, we catch exceptions
1443  // here to append a position in the configuration string.
1444  try {
1445  cfg->getCfgSubnets6()->add(subnet);
1446  cnt++;
1447  } catch (const std::exception& ex) {
1448  isc_throw(DhcpConfigError, ex.what() << " ("
1449  << subnet_json->getPosition() << ")");
1450  }
1451  }
1452  return (cnt);
1453 }
1454 
1455 size_t
1457  ConstElementPtr subnets_list) {
1458  size_t cnt = 0;
1459  BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
1460 
1461  auto parser = createSubnetConfigParser();
1462  Subnet6Ptr subnet = parser->parse(subnet_json);
1463  if (subnet) {
1464  try {
1465  auto ret = subnets.insert(subnet);
1466  if (!ret.second) {
1468  "can't store subnet because of conflict");
1469  }
1470  ++cnt;
1471  } catch (const std::exception& ex) {
1472  isc_throw(DhcpConfigError, ex.what() << " ("
1473  << subnet_json->getPosition() << ")");
1474  }
1475  }
1476  }
1477  return (cnt);
1478 }
1479 
1480 boost::shared_ptr<Subnet6ConfigParser>
1482  auto parser = boost::make_shared<Subnet6ConfigParser>(check_iface_);
1483  return (parser);
1484 }
1485 
1486 //**************************** D2ClientConfigParser **********************
1487 
1489 D2ClientConfigParser::getProtocol(ConstElementPtr scope,
1490  const std::string& name) {
1493  (scope, name, "NameChangeRequest protocol"));
1494 }
1495 
1497 D2ClientConfigParser::getFormat(ConstElementPtr scope,
1498  const std::string& name) {
1501  (scope, name, "NameChangeRequest format"));
1502 }
1503 
1505 D2ClientConfigParser::getMode(ConstElementPtr scope,
1506  const std::string& name) {
1509  (scope, name, "ReplaceClientName mode"));
1510 }
1511 
1514  D2ClientConfigPtr new_config;
1515 
1516  // Get all parameters that are needed to create the D2ClientConfig.
1517  bool enable_updates = getBoolean(client_config, "enable-updates");
1518 
1519  IOAddress server_ip = getAddress(client_config, "server-ip");
1520 
1521  uint32_t server_port = getUint32(client_config, "server-port");
1522 
1523  std::string sender_ip_str = getString(client_config, "sender-ip");
1524 
1525  uint32_t sender_port = getUint32(client_config, "sender-port");
1526 
1527  uint32_t max_queue_size = getUint32(client_config, "max-queue-size");
1528 
1529  dhcp_ddns::NameChangeProtocol ncr_protocol =
1530  getProtocol(client_config, "ncr-protocol");
1531 
1532  dhcp_ddns::NameChangeFormat ncr_format =
1533  getFormat(client_config, "ncr-format");
1534 
1535  IOAddress sender_ip(0);
1536  if (sender_ip_str.empty()) {
1537  // The default sender IP depends on the server IP family
1538  sender_ip = (server_ip.isV4() ? IOAddress::IPV4_ZERO_ADDRESS() :
1540  } else {
1541  try {
1542  sender_ip = IOAddress(sender_ip_str);
1543  } catch (const std::exception& ex) {
1544  isc_throw(DhcpConfigError, "invalid address (" << sender_ip_str
1545  << ") specified for parameter 'sender-ip' ("
1546  << getPosition("sender-ip", client_config) << ")");
1547  }
1548  }
1549 
1550  // Now we check for logical errors. This repeats what is done in
1551  // D2ClientConfig::validate(), but doing it here permits us to
1552  // emit meaningful parameter position info in the error.
1553  if (ncr_format != dhcp_ddns::FMT_JSON) {
1554  isc_throw(D2ClientError, "D2ClientConfig error: NCR Format: "
1555  << dhcp_ddns::ncrFormatToString(ncr_format)
1556  << " is not supported. ("
1557  << getPosition("ncr-format", client_config) << ")");
1558  }
1559 
1560  if (ncr_protocol != dhcp_ddns::NCR_UDP) {
1561  isc_throw(D2ClientError, "D2ClientConfig error: NCR Protocol: "
1562  << dhcp_ddns::ncrProtocolToString(ncr_protocol)
1563  << " is not supported. ("
1564  << getPosition("ncr-protocol", client_config) << ")");
1565  }
1566 
1567  if (sender_ip.getFamily() != server_ip.getFamily()) {
1569  "D2ClientConfig error: address family mismatch: "
1570  << "server-ip: " << server_ip.toText()
1571  << " is: " << (server_ip.isV4() ? "IPv4" : "IPv6")
1572  << " while sender-ip: " << sender_ip.toText()
1573  << " is: " << (sender_ip.isV4() ? "IPv4" : "IPv6")
1574  << " (" << getPosition("sender-ip", client_config) << ")");
1575  }
1576 
1577  if (server_ip == sender_ip && server_port == sender_port) {
1579  "D2ClientConfig error: server and sender cannot"
1580  " share the exact same IP address/port: "
1581  << server_ip.toText() << "/" << server_port
1582  << " (" << getPosition("sender-ip", client_config) << ")");
1583  }
1584 
1585  try {
1586  // Attempt to create the new client config.
1587  new_config.reset(new D2ClientConfig(enable_updates,
1588  server_ip,
1589  server_port,
1590  sender_ip,
1591  sender_port,
1592  max_queue_size,
1593  ncr_protocol,
1594  ncr_format));
1595  } catch (const std::exception& ex) {
1596  isc_throw(DhcpConfigError, ex.what() << " ("
1597  << client_config->getPosition() << ")");
1598  }
1599 
1600  // Add user context
1601  ConstElementPtr user_context = client_config->get("user-context");
1602  if (user_context) {
1603  new_config->setContext(user_context);
1604  }
1605 
1606  return(new_config);
1607 }
1608 
1611  // enable-updates is unconditionally required
1612  { "server-ip", Element::string, "127.0.0.1" },
1613  { "server-port", Element::integer, "53001" },
1614  // default sender-ip depends on server-ip family, so we leave default blank
1615  // parser knows to use the appropriate ZERO address based on server-ip
1616  { "sender-ip", Element::string, "" },
1617  { "sender-port", Element::integer, "0" },
1618  { "max-queue-size", Element::integer, "1024" },
1619  { "ncr-protocol", Element::string, "UDP" },
1620  { "ncr-format", Element::string, "JSON" }
1621 };
1622 
1623 size_t
1625  ElementPtr mutable_d2 = boost::const_pointer_cast<Element>(d2_config);
1626  return (SimpleParser::setDefaults(mutable_d2, D2_CLIENT_CONFIG_DEFAULTS));
1627 }
1628 
1629 } // namespace dhcp
1630 } // 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:894
#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:706
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:41
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:1296
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:181
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:521
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:794
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:528
void setInterfaceId(const OptionPtr &ifaceid)
sets interface-id option (if defined)
Definition: network.h:1323
boost::shared_ptr< CfgOptionDef > CfgOptionDefPtr
Non-const pointer.
CfgOptionPtr getCfgOption()
Returns pointer to the option data configuration for this network.
Definition: network.h:445
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:133
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: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:890
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: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:1345
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:123
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:788
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:961
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:363
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:676
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:91
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:346
#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:226
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:378
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:669
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:1335
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:512
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