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