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