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