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