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 client class list.
528 std::bind(&Pool::allowClientClass,
529 pool, ph::_1));
530
531 // Setup additional class list.
533 std::bind(&Pool::addAdditionalClass,
534 pool, ph::_1));
535}
536
537boost::shared_ptr<OptionDataListParser>
538PoolParser::createOptionDataListParser(const uint16_t address_family) const {
539 return (boost::make_shared<OptionDataListParser>(address_family));
540}
541
542//****************************** Pool4Parser *************************
543
545Pool4Parser::poolMaker (IOAddress &addr, uint32_t len, int32_t) {
546 return (PoolPtr(new Pool4(addr, len)));
547}
548
551 return (PoolPtr(new Pool4(min, max)));
552}
553
554//****************************** Pools4ListParser *************************
555
556void
558 bool encapsulate_options) {
559 for (auto const& pool : pools_list->listValue()) {
560 auto const& parser = createPoolConfigParser();
561 parser->parse(pools, pool, AF_INET, encapsulate_options);
562 }
563}
564
565boost::shared_ptr<PoolParser>
567 return (boost::make_shared<Pool4Parser>());
568}
569
570//****************************** SubnetConfigParser *************************
571
572SubnetConfigParser::SubnetConfigParser(uint16_t family, bool check_iface)
573 : pools_(new PoolStorage()),
574 address_family_(family),
575 check_iface_(check_iface) {
577}
578
580SubnetConfigParser::parse(ConstElementPtr subnet, bool encapsulate_options) {
581
582 ConstElementPtr relay_params = subnet->get("relay");
583 if (relay_params) {
585 RelayInfoParser parser(u);
586 parser.parse(relay_info_, relay_params);
587 }
588
589 // Create a subnet.
590 try {
591 createSubnet(subnet);
592 } catch (const std::exception& ex) {
594 "subnet configuration failed: " << ex.what());
595 }
596
597 // We create subnet first and then parse the options straight into the subnet's
598 // CfgOption structure. Previously, we first parsed the options and then copied
599 // them into the CfgOption after creating the subnet but it had two issues. First,
600 // it cost performance. Second, copying options reset the isEncapsulated() flag.
601 // If the options have been encapsulated we want to preserve the flag to ensure
602 // they are not encapsulated several times.
603 ConstElementPtr options_params = subnet->get("option-data");
604 if (options_params) {
605 auto opt_parser = createOptionDataListParser();
606 opt_parser->parse(subnet_->getCfgOption(), options_params, encapsulate_options);
607 }
608
609 return (subnet_);
610}
611
612void
614 std::string subnet_txt;
615 try {
616 subnet_txt = getString(params, "subnet");
617 } catch (const DhcpConfigError &) {
618 // rethrow with precise error
620 "mandatory 'subnet' parameter is missing for a subnet being"
621 " configured (" << params->getPosition() << ")");
622 }
623
624 // Remove any spaces or tabs.
625 boost::erase_all(subnet_txt, " ");
626 boost::erase_all(subnet_txt, "\t");
627
628 // The subnet format is prefix/len. We are going to extract
629 // the prefix portion of a subnet string to create IOAddress
630 // object from it. IOAddress will be passed to the Subnet's
631 // constructor later on. In order to extract the prefix we
632 // need to get all characters preceding "/".
633 size_t pos = subnet_txt.find("/");
634 if (pos == string::npos) {
635 ConstElementPtr elem = params->get("subnet");
637 "Invalid subnet syntax (prefix/len expected):" << subnet_txt
638 << " (" << elem->getPosition() << ")");
639 }
640
641 // Try to create the address object. It also validates that
642 // the address syntax is ok.
643 isc::asiolink::IOAddress addr(subnet_txt.substr(0, pos));
644
645 // Now parse out the prefix length.
646 unsigned int len;
647 try {
648 len = boost::lexical_cast<unsigned int>(subnet_txt.substr(pos + 1));
649 } catch (const boost::bad_lexical_cast&) {
650 ConstElementPtr elem = params->get("subnet");
651 isc_throw(DhcpConfigError, "prefix length: '" <<
652 subnet_txt.substr(pos+1) << "' is not an integer ("
653 << elem->getPosition() << ")");
654 }
655
656 // Sanity check the prefix length
657 if ((addr.isV6() && len > 128) ||
658 (addr.isV4() && len > 32)) {
659 ConstElementPtr elem = params->get("subnet");
661 "Invalid prefix length specified for subnet: " << len
662 << " (" << elem->getPosition() << ")");
663 }
664
665 // Call the subclass's method to instantiate the subnet
666 initSubnet(params, addr, len);
667
668 // Add pools to it.
669 for (auto const& pool : *pools_) {
670 try {
671 subnet_->addPool(pool);
672 } catch (const BadValue& ex) {
673 // addPool() can throw BadValue if the pool is overlapping or
674 // is out of bounds for the subnet.
676 ex.what() << " (" << params->getPosition() << ")");
677 }
678 }
679 // If there's user-context specified, store it.
680 ConstElementPtr user_context = params->get("user-context");
681 if (user_context) {
682 // The grammar accepts only maps but still check it.
683 if (user_context->getType() != Element::map) {
684 isc_throw(isc::dhcp::DhcpConfigError, "User context has to be a map ("
685 << user_context->getPosition() << ")");
686 }
687 subnet_->setContext(user_context);
688 }
689
690 // In order to take advantage of the dynamic inheritance of global
691 // parameters to a subnet we need to set a callback function for each
692 // subnet to allow for fetching global parameters.
693 subnet_->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr {
694 return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals());
695 });
696}
697
698boost::shared_ptr<OptionDataListParser>
700 return (boost::make_shared<OptionDataListParser>(address_family_));
701}
702
703//****************************** Subnet4ConfigParser *************************
704
706 : SubnetConfigParser(AF_INET, check_iface) {
707}
708
710Subnet4ConfigParser::parse(ConstElementPtr subnet, bool encapsulate_options) {
711 // Check parameters.
713
715 ConstElementPtr pools = subnet->get("pools");
716 if (pools) {
717 auto const& parser = createPoolsListParser();
718 parser->parse(pools_, pools, encapsulate_options);
719 }
720
721 SubnetPtr generic = SubnetConfigParser::parse(subnet, encapsulate_options);
722
723 if (!generic) {
724 // Sanity check: not supposed to fail.
726 "Failed to create an IPv4 subnet (" <<
727 subnet->getPosition() << ")");
728 }
729
730 Subnet4Ptr sn4ptr = boost::dynamic_pointer_cast<Subnet4>(subnet_);
731 if (!sn4ptr) {
732 // If we hit this, it is a programming error.
734 "Invalid Subnet4 cast in Subnet4ConfigParser::parse");
735 }
736
737 // Set relay information if it was parsed
738 if (relay_info_) {
739 sn4ptr->setRelayInfo(*relay_info_);
740 }
741
742 // Parse Host Reservations for this subnet if any.
743 ConstElementPtr reservations = subnet->get("reservations");
744 if (reservations) {
745 HostCollection hosts;
746 HostReservationsListParser<HostReservationParser4> parser;
747 parser.parse(subnet_->getID(), reservations, hosts);
748 for (auto const& h : hosts) {
749 validateResv(sn4ptr, h);
750 CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(h);
751 }
752 }
753
754 // Parse allocator specification.
755 auto network4 = boost::dynamic_pointer_cast<Network>(sn4ptr);
756 parseAllocatorParams(subnet, network4);
757
758 // Instantiate the allocator.
759 sn4ptr->createAllocators();
760
761 return (sn4ptr);
762}
763
764void
766 asiolink::IOAddress addr, uint8_t len) {
767 // Subnet ID is required and must be in 1..SUBNET_ID_MAX.
768 int64_t subnet_id_max = static_cast<int64_t>(SUBNET_ID_MAX);
769 SubnetID subnet_id = static_cast<SubnetID>(getInteger(params, "id", 1,
770 subnet_id_max));
771
772 auto subnet4 = Subnet4::create(addr, len, Triplet<uint32_t>(),
773 Triplet<uint32_t>(), Triplet<uint32_t>(),
774 subnet_id);
775 subnet_ = subnet4;
776
777 ElementPtr mutable_params;
778 mutable_params = boost::const_pointer_cast<Element>(params);
779
780 // Parse parameters common to all Network derivations.
781 NetworkPtr network = boost::dynamic_pointer_cast<Network>(subnet4);
782 parseCommon(mutable_params, network);
783
784 std::ostringstream output;
785 output << addr << "/" << static_cast<int>(len) << " with params: ";
786
787 bool has_renew = !subnet4->getT1().unspecified();
788 bool has_rebind = !subnet4->getT2().unspecified();
789 int64_t renew = -1;
790 int64_t rebind = -1;
791
792 // t1 and t2 are optional may be not specified.
793 if (has_renew) {
794 renew = subnet4->getT1().get();
795 output << "t1=" << renew << ", ";
796 }
797 if (has_rebind) {
798 rebind = subnet4->getT2().get();
799 output << "t2=" << rebind << ", ";
800 }
801
802 if (!subnet4->getValid().unspecified()) {
803 output << "valid-lifetime=" << subnet4->getValid().get();
804 }
805
807
808 // Set the match-client-id value for the subnet.
809 if (params->contains("match-client-id")) {
810 bool match_client_id = getBoolean(params, "match-client-id");
811 subnet4->setMatchClientId(match_client_id);
812 }
813
814 // Set the authoritative value for the subnet.
815 if (params->contains("authoritative")) {
816 bool authoritative = getBoolean(params, "authoritative");
817 subnet4->setAuthoritative(authoritative);
818 }
819
820 // Set next-server. The default value is 0.0.0.0. Nevertheless, the
821 // user could have messed that up by specifying incorrect value.
822 // To avoid using 0.0.0.0, user can specify "".
823 if (params->contains("next-server")) {
824 string next_server;
825 try {
826 next_server = getString(params, "next-server");
827 if (!next_server.empty()) {
828 subnet4->setSiaddr(IOAddress(next_server));
829 }
830 } catch (...) {
831 ConstElementPtr next = params->get("next-server");
832 string pos;
833 if (next) {
834 pos = next->getPosition().str();
835 } else {
836 pos = params->getPosition().str();
837 }
838 isc_throw(DhcpConfigError, "invalid parameter next-server : "
839 << next_server << "(" << pos << ")");
840 }
841 }
842
843 // Set server-hostname.
844 if (params->contains("server-hostname")) {
845 std::string sname = getString(params, "server-hostname");
846 if (!sname.empty()) {
847 if (sname.length() >= Pkt4::MAX_SNAME_LEN) {
848 ConstElementPtr error = params->get("server-hostname");
849 isc_throw(DhcpConfigError, "server-hostname must be at most "
850 << Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is "
851 << sname.length() << " ("
852 << error->getPosition() << ")");
853 }
854 subnet4->setSname(sname);
855 }
856 }
857
858 // Set boot-file-name.
859 if (params->contains("boot-file-name")) {
860 std::string filename =getString(params, "boot-file-name");
861 if (!filename.empty()) {
862 if (filename.length() > Pkt4::MAX_FILE_LEN) {
863 ConstElementPtr error = params->get("boot-file-name");
864 isc_throw(DhcpConfigError, "boot-file-name must be at most "
865 << Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is "
866 << filename.length() << " ("
867 << error->getPosition() << ")");
868 }
869 subnet4->setFilename(filename);
870 }
871 }
872
873 // Get interface name. If it is defined, then the subnet is available
874 // directly over specified network interface.
875 if (params->contains("interface")) {
876 std::string iface = getString(params, "interface");
877 if (!iface.empty()) {
878 if (check_iface_ && !IfaceMgr::instance().getIface(iface)) {
879 ConstElementPtr error = params->get("interface");
880 isc_throw(DhcpConfigError, "Specified network interface name " << iface
881 << " for subnet " << subnet4->toText()
882 << " is not present in the system ("
883 << error->getPosition() << ")");
884 }
885
886 subnet4->setIface(iface);
887 }
888 }
889
890 // Try setting up client class.
891 if (params->contains("client-class")) {
892 string client_class = getString(params, "client-class");
893 if (!client_class.empty()) {
894 subnet4->allowClientClass(client_class);
895 }
896 }
897
898 // Setup client class list.
900 subnet4, ph::_1));
901
902 // Setup additional class list.
904 subnet4, ph::_1));
905
906 // 4o6 specific parameter: 4o6-interface.
907 if (params->contains("4o6-interface")) {
908 string iface4o6 = getString(params, "4o6-interface");
909 if (!iface4o6.empty()) {
910 subnet4->get4o6().setIface4o6(iface4o6);
911 subnet4->get4o6().enabled(true);
912 }
913 }
914
915 // 4o6 specific parameter: 4o6-subnet.
916 if (params->contains("4o6-subnet")) {
917 string subnet4o6 = getString(params, "4o6-subnet");
918 if (!subnet4o6.empty()) {
919 size_t slash = subnet4o6.find("/");
920 if (slash == std::string::npos) {
921 isc_throw(DhcpConfigError, "Missing / in the 4o6-subnet parameter:"
922 << subnet4o6 << ", expected format: prefix6/length");
923 }
924 string prefix = subnet4o6.substr(0, slash);
925 string lenstr = subnet4o6.substr(slash + 1);
926
927 len = 128;
928 try {
929 len = boost::lexical_cast<unsigned int>(lenstr.c_str());
930 } catch (const boost::bad_lexical_cast &) {
931 isc_throw(DhcpConfigError, "Invalid prefix length specified in "
932 "4o6-subnet parameter: " << subnet4o6 << ", expected 0..128 value");
933 }
934 subnet4->get4o6().setSubnet4o6(IOAddress(prefix), len);
935 subnet4->get4o6().enabled(true);
936 }
937 }
938
939 // Try 4o6 specific parameter: 4o6-interface-id
940 if (params->contains("4o6-interface-id")) {
941 std::string ifaceid = getString(params, "4o6-interface-id");
942 if (!ifaceid.empty()) {
943 OptionBuffer tmp(ifaceid.begin(), ifaceid.end());
945 subnet4->get4o6().setInterfaceId(opt);
946 subnet4->get4o6().enabled(true);
947 }
948 }
949
952
953 // Here globally defined options were merged to the subnet specific
954 // options but this is no longer the case (they have a different
955 // and not consecutive priority).
956
957 // Parse t1-percent and t2-percent
958 parseTeePercents(params, network);
959
960 // Parse DDNS parameters
961 parseDdnsParams(params, network);
962
963 // Parse lease cache parameters
964 parseCacheParams(params, network);
965
966 // Set the offer_lft value for the subnet.
967 if (params->contains("offer-lifetime")) {
968 uint32_t offer_lft = getInteger(params, "offer-lifetime");
969 subnet4->setOfferLft(offer_lft);
970 }
971
972 // Parse offer-lifetime parameter.
973 Network4Ptr network4 = boost::dynamic_pointer_cast<Network4>(subnet4);
974 parseOfferLft(params, network4);
975
976}
977
978void
980 const IOAddress& address = host->getIPv4Reservation();
981 if (!address.isV4Zero() && !subnet->inRange(address)) {
982 isc_throw(DhcpConfigError, "specified reservation '" << address
983 << "' is not within the IPv4 subnet '"
984 << subnet->toText() << "'");
985 }
986}
987
988boost::shared_ptr<PoolsListParser>
990 return (boost::make_shared<Pools4ListParser>());
991}
992
993//**************************** Subnets4ListConfigParser **********************
994
996 : check_iface_(check_iface) {
997}
998
999size_t
1001 ConstElementPtr subnets_list,
1002 bool encapsulate_options) {
1003 size_t cnt = 0;
1004 for (auto const& subnet_json : subnets_list->listValue()) {
1005
1006 auto const& parser = createSubnetConfigParser();
1007 Subnet4Ptr subnet = parser->parse(subnet_json, encapsulate_options);
1008 if (subnet) {
1009
1010 // Adding a subnet to the Configuration Manager may fail if the
1011 // subnet id is invalid (duplicate). Thus, we catch exceptions
1012 // here to append a position in the configuration string.
1013 try {
1014 cfg->getCfgSubnets4()->add(subnet);
1015 cnt++;
1016 } catch (const std::exception& ex) {
1017 isc_throw(DhcpConfigError, ex.what() << " ("
1018 << subnet_json->getPosition() << ")");
1019 }
1020 }
1021 }
1022 return (cnt);
1023}
1024
1025size_t
1027 data::ConstElementPtr subnets_list,
1028 bool encapsulate_options) {
1029 size_t cnt = 0;
1030 for (auto const& subnet_json : subnets_list->listValue()) {
1031
1032 auto const& parser = createSubnetConfigParser();
1033 Subnet4Ptr subnet = parser->parse(subnet_json, encapsulate_options);
1034 if (subnet) {
1035 try {
1036 auto ret = subnets.insert(subnet);
1037 if (!ret.second) {
1039 "can't store subnet because of conflict");
1040 }
1041 ++cnt;
1042 } catch (const std::exception& ex) {
1043 isc_throw(DhcpConfigError, ex.what() << " ("
1044 << subnet_json->getPosition() << ")");
1045 }
1046 }
1047 }
1048 return (cnt);
1049}
1050
1051boost::shared_ptr<Subnet4ConfigParser>
1053 return (boost::make_shared<Subnet4ConfigParser>(check_iface_));
1054}
1055
1056//**************************** Pool6Parser *********************************
1057
1058PoolPtr
1059Pool6Parser::poolMaker(IOAddress &addr, uint32_t len, int32_t ptype)
1060{
1061 return (PoolPtr(new Pool6(static_cast<isc::dhcp::Lease::Type>
1062 (ptype), addr, len)));
1063}
1064
1065PoolPtr
1067{
1068 return (PoolPtr(new Pool6(static_cast<isc::dhcp::Lease::Type>
1069 (ptype), min, max)));
1070}
1071
1072
1073//**************************** Pool6ListParser ***************************
1074
1075void
1077 bool encapsulate_options) {
1078 for (auto const& pool : pools_list->listValue()) {
1079 auto const& parser = createPoolConfigParser();
1080 parser->parse(pools, pool, AF_INET6, encapsulate_options);
1081 }
1082}
1083
1084boost::shared_ptr<PoolParser>
1086 return (boost::make_shared<Pool6Parser>());
1087}
1088
1089//**************************** PdPoolParser ******************************
1090
1093
1094void
1096 bool encapsulate_options) {
1098
1099 std::string addr_str = getString(pd_pool, "prefix");
1100
1101 uint8_t prefix_len = getUint8(pd_pool, "prefix-len");
1102
1103 uint8_t delegated_len = getUint8(pd_pool, "delegated-len");
1104
1105 std::string excluded_prefix_str = "::";
1106 if (pd_pool->contains("excluded-prefix")) {
1107 excluded_prefix_str = getString(pd_pool, "excluded-prefix");
1108 }
1109
1110 uint8_t excluded_prefix_len = 0;
1111 if (pd_pool->contains("excluded-prefix-len")) {
1112 excluded_prefix_len = getUint8(pd_pool, "excluded-prefix-len");
1113 }
1114
1115 ConstElementPtr user_context = pd_pool->get("user-context");
1116 if (user_context) {
1117 user_context_ = user_context;
1118 }
1119
1120 ConstElementPtr client_class = pd_pool->get("client-class");
1121 if (client_class) {
1122 client_class_ = client_class;
1123 }
1124
1125 // Check the pool parameters. It will throw an exception if any
1126 // of the required parameters are invalid.
1127 try {
1128 // Attempt to construct the local pool.
1129 pool_.reset(new Pool6(IOAddress(addr_str),
1130 prefix_len,
1131 delegated_len,
1132 IOAddress(excluded_prefix_str),
1133 excluded_prefix_len));
1134 } catch (const std::exception& ex) {
1135 // Some parameters don't exist or are invalid. Since we are not
1136 // aware whether they don't exist or are invalid, let's append
1137 // the position of the pool map element.
1139 << " (" << pd_pool->getPosition() << ")");
1140 }
1141
1142 // If there is a pool-id, store it.
1143 ConstElementPtr pool_id = pd_pool->get("pool-id");
1144 if (pool_id) {
1145 if (pool_id->intValue() <= 0) {
1146 isc_throw(BadValue, "pool-id " << pool_id->intValue() << " is not"
1147 << " a positive integer greater than 0");
1148 } else if (pool_id->intValue() > numeric_limits<uint32_t>::max()) {
1149 isc_throw(BadValue, "pool-id " << pool_id->intValue() << " is not"
1150 << " a 32 bit unsigned integer");
1151 }
1152
1153 pool_->setID(pool_id->intValue());
1154 }
1155
1156 // We create subnet first and then parse the options straight into the subnet's
1157 // CfgOption structure. Previously, we first parsed the options and then copied
1158 // them into the CfgOption after creating the subnet but it had two issues. First,
1159 // it cost performance. Second, copying options reset the isEncapsulated() flag.
1160 // If the options have been encapsulated we want to preserve the flag to ensure
1161 // they are not encapsulated several times.
1162 ConstElementPtr option_data = pd_pool->get("option-data");
1163 if (option_data) {
1164 auto opts_parser = createOptionDataListParser();
1165 opts_parser->parse(pool_->getCfgOption(), option_data, encapsulate_options);
1166 }
1167
1168 if (user_context_) {
1169 pool_->setContext(user_context_);
1170 }
1171
1172 if (client_class_) {
1173 string cclass = client_class_->stringValue();
1174 if (!cclass.empty()) {
1175 pool_->allowClientClass(cclass);
1176 }
1177 }
1178
1179 // Setup client class list.
1181 std::bind(&Pool::allowClientClass,
1182 pool_, ph::_1));
1183
1184 // Setup additional class list.
1186 std::bind(&Pool::addAdditionalClass,
1187 pool_, ph::_1));
1188
1189 // Add the local pool to the external storage ptr.
1190 pools->push_back(pool_);
1191}
1192
1193boost::shared_ptr<OptionDataListParser>
1195 return (boost::make_shared<OptionDataListParser>(AF_INET6));
1196}
1197
1198//**************************** PdPoolsListParser ************************
1199
1200void
1202 // Loop through the list of pd pools.
1203 for (auto const& pd_pool : pd_pool_list->listValue()) {
1204 auto const& parser = createPdPoolConfigParser();
1205 parser->parse(pools, pd_pool);
1206 }
1207}
1208
1209boost::shared_ptr<PdPoolParser>
1211 return (boost::make_shared<PdPoolParser>());
1212}
1213
1214//**************************** Subnet6ConfigParser ***********************
1215
1217 : SubnetConfigParser(AF_INET6, check_iface) {
1218}
1219
1221Subnet6ConfigParser::parse(ConstElementPtr subnet, bool encapsulate_options) {
1222 // Check parameters.
1224
1226 ConstElementPtr pools = subnet->get("pools");
1227 if (pools) {
1228 auto const& parser = createPoolsListParser();
1229 parser->parse(pools_, pools, encapsulate_options);
1230 }
1231 ConstElementPtr pd_pools = subnet->get("pd-pools");
1232 if (pd_pools) {
1233 auto const& parser = createPdPoolsListParser();
1234 parser->parse(pools_, pd_pools);
1235 }
1236
1237 SubnetPtr generic = SubnetConfigParser::parse(subnet, encapsulate_options);
1238
1239 if (!generic) {
1240 // Sanity check: not supposed to fail.
1242 "Failed to create an IPv6 subnet (" <<
1243 subnet->getPosition() << ")");
1244 }
1245
1246 Subnet6Ptr sn6ptr = boost::dynamic_pointer_cast<Subnet6>(subnet_);
1247 if (!sn6ptr) {
1248 // If we hit this, it is a programming error.
1250 "Invalid Subnet6 cast in Subnet6ConfigParser::parse");
1251 }
1252
1253 // Set relay information if it was provided
1254 if (relay_info_) {
1255 sn6ptr->setRelayInfo(*relay_info_);
1256 }
1257
1258 // Parse Host Reservations for this subnet if any.
1259 ConstElementPtr reservations = subnet->get("reservations");
1260 if (reservations) {
1261 HostCollection hosts;
1262 HostReservationsListParser<HostReservationParser6> parser;
1263 parser.parse(subnet_->getID(), reservations, hosts);
1264 for (auto const& h : hosts) {
1265 validateResvs(sn6ptr, h);
1266 CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(h);
1267 }
1268 }
1269
1270 // Parse allocator specification.
1271 auto network = boost::dynamic_pointer_cast<Network>(sn6ptr);
1272 parseAllocatorParams(subnet, network);
1273
1274 // Parse pd-allocator specification.
1275 auto network6 = boost::dynamic_pointer_cast<Network6>(sn6ptr);
1276 parsePdAllocatorParams(subnet, network6);
1277
1278 // Instantiate the allocators.
1279 sn6ptr->createAllocators();
1280
1281 return (sn6ptr);
1282}
1283
1284// Unused?
1285void
1291
1292void
1294 asiolink::IOAddress addr, uint8_t len) {
1295 // Subnet ID is required and must be in 1..SUBNET_ID_MAX.
1296 int64_t subnet_id_max = static_cast<int64_t>(SUBNET_ID_MAX);
1297 SubnetID subnet_id = static_cast<SubnetID>(getInteger(params, "id", 1,
1298 subnet_id_max));
1299
1300 // We want to log whether rapid-commit is enabled, so we get this
1301 // before the actual subnet creation.
1302 Optional<bool> rapid_commit;
1303 if (params->contains("rapid-commit")) {
1304 rapid_commit = getBoolean(params, "rapid-commit");
1305 }
1306
1307 // Parse preferred lifetime as it is not parsed by the common function.
1308 Triplet<uint32_t> pref = parseIntTriplet(params, "preferred-lifetime");
1309
1310 // Create a new subnet.
1311 auto subnet6 = Subnet6::create(addr, len, Triplet<uint32_t>(),
1312 Triplet<uint32_t>(),
1313 pref,
1314 Triplet<uint32_t>(),
1315 subnet_id);
1316 subnet_ = subnet6;
1317
1318 ElementPtr mutable_params;
1319 mutable_params = boost::const_pointer_cast<Element>(params);
1320
1321 // Parse parameters common to all Network derivations.
1322 NetworkPtr network = boost::dynamic_pointer_cast<Network>(subnet_);
1323 parseCommon(mutable_params, network);
1324
1325 // Enable or disable Rapid Commit option support for the subnet.
1326 if (!rapid_commit.unspecified()) {
1327 subnet6->setRapidCommit(rapid_commit);
1328 }
1329
1330 std::ostringstream output;
1331 output << addr << "/" << static_cast<int>(len) << " with params: ";
1332 // t1 and t2 are optional may be not specified.
1333
1334 bool has_renew = !subnet6->getT1().unspecified();
1335 bool has_rebind = !subnet6->getT2().unspecified();
1336 int64_t renew = -1;
1337 int64_t rebind = -1;
1338
1339 if (has_renew) {
1340 renew = subnet6->getT1().get();
1341 output << "t1=" << renew << ", ";
1342 }
1343 if (has_rebind) {
1344 rebind = subnet6->getT2().get();
1345 output << "t2=" << rebind << ", ";
1346 }
1347
1348 if (!subnet6->getPreferred().unspecified()) {
1349 output << "preferred-lifetime=" << subnet6->getPreferred().get() << ", ";
1350 }
1351 if (!subnet6->getValid().unspecified()) {
1352 output << "valid-lifetime=" << subnet6->getValid().get();
1353 }
1354 if (!subnet6->getRapidCommit().unspecified()) {
1355 output << ", rapid-commit is "
1356 << boolalpha << subnet6->getRapidCommit().get();
1357 }
1358
1360
1361 // Get interface-id option content. For now we support string
1362 // representation only
1363 Optional<std::string> ifaceid;
1364 if (params->contains("interface-id")) {
1365 ifaceid = getString(params, "interface-id");
1366 }
1367
1368 Optional<std::string> iface;
1369 if (params->contains("interface")) {
1370 iface = getString(params, "interface");
1371 }
1372
1373 // Specifying both interface for locally reachable subnets and
1374 // interface id for relays is mutually exclusive. Need to test for
1375 // this condition.
1376 if (!ifaceid.unspecified() && !iface.unspecified() && !ifaceid.empty() &&
1377 !iface.empty()) {
1379 "parser error: interface (defined for locally reachable "
1380 "subnets) and interface-id (defined for subnets reachable"
1381 " via relays) cannot be defined at the same time for "
1382 "subnet " << addr << "/" << (int)len << "("
1383 << params->getPosition() << ")");
1384 }
1385
1386 // Configure interface-id for remote interfaces, if defined
1387 if (!ifaceid.unspecified() && !ifaceid.empty()) {
1388 std::string ifaceid_value = ifaceid.get();
1389 OptionBuffer tmp(ifaceid_value.begin(), ifaceid_value.end());
1391 subnet6->setInterfaceId(opt);
1392 }
1393
1394 // Get interface name. If it is defined, then the subnet is available
1395 // directly over specified network interface.
1396 if (!iface.unspecified() && !iface.empty()) {
1397 if (check_iface_ && !IfaceMgr::instance().getIface(iface)) {
1398 ConstElementPtr error = params->get("interface");
1399 isc_throw(DhcpConfigError, "Specified network interface name " << iface
1400 << " for subnet " << subnet6->toText()
1401 << " is not present in the system ("
1402 << error->getPosition() << ")");
1403 }
1404
1405 subnet6->setIface(iface);
1406 }
1407
1408 // Try setting up client class.
1409 if (params->contains("client-class")) {
1410 string client_class = getString(params, "client-class");
1411 if (!client_class.empty()) {
1412 subnet6->allowClientClass(client_class);
1413 }
1414 }
1415
1416 // Setup client class list.
1418 subnet6, ph::_1));
1419
1420 // Setup additional class list.
1422 subnet6, ph::_1));
1423
1426
1427 // Parse t1-percent and t2-percent
1428 parseTeePercents(params, network);
1429
1430 // Parse DDNS parameters
1431 parseDdnsParams(params, network);
1432
1433 // Parse lease cache parameters
1434 parseCacheParams(params, network);
1435}
1436
1437void
1439 const IPv6ResrvRange& range = host->getIPv6Reservations(IPv6Resrv::TYPE_NA);
1440 BOOST_FOREACH(auto const& it, range) {
1441 const IOAddress& address = it.second.getPrefix();
1442 if (!subnet->inRange(address)) {
1443 isc_throw(DhcpConfigError, "specified reservation '" << address
1444 << "' is not within the IPv6 subnet '"
1445 << subnet->toText() << "'");
1446 }
1447 }
1448}
1449
1450boost::shared_ptr<PoolsListParser>
1452 return (boost::make_shared<Pools6ListParser>());
1453}
1454
1455boost::shared_ptr<PdPoolsListParser>
1457 return (boost::make_shared<PdPoolsListParser>());
1458}
1459
1460//**************************** Subnet6ListConfigParser ********************
1461
1463 : check_iface_(check_iface) {
1464}
1465
1466size_t
1468 ConstElementPtr subnets_list,
1469 bool encapsulate_options) {
1470 size_t cnt = 0;
1471 for (auto const& subnet_json : subnets_list->listValue()) {
1472
1473 auto const& parser = createSubnetConfigParser();
1474 Subnet6Ptr subnet = parser->parse(subnet_json, encapsulate_options);
1475
1476 // Adding a subnet to the Configuration Manager may fail if the
1477 // subnet id is invalid (duplicate). Thus, we catch exceptions
1478 // here to append a position in the configuration string.
1479 try {
1480 cfg->getCfgSubnets6()->add(subnet);
1481 cnt++;
1482 } catch (const std::exception& ex) {
1483 isc_throw(DhcpConfigError, ex.what() << " ("
1484 << subnet_json->getPosition() << ")");
1485 }
1486 }
1487 return (cnt);
1488}
1489
1490size_t
1492 ConstElementPtr subnets_list,
1493 bool encapsulate_options) {
1494 size_t cnt = 0;
1495 for (auto const& subnet_json : subnets_list->listValue()) {
1496
1497 auto const& parser = createSubnetConfigParser();
1498 Subnet6Ptr subnet = parser->parse(subnet_json, encapsulate_options);
1499 if (subnet) {
1500 try {
1501 auto ret = subnets.insert(subnet);
1502 if (!ret.second) {
1504 "can't store subnet because of conflict");
1505 }
1506 ++cnt;
1507 } catch (const std::exception& ex) {
1508 isc_throw(DhcpConfigError, ex.what() << " ("
1509 << subnet_json->getPosition() << ")");
1510 }
1511 }
1512 }
1513 return (cnt);
1514}
1515
1516boost::shared_ptr<Subnet6ConfigParser>
1518 return (boost::make_shared<Subnet6ConfigParser>(check_iface_));
1519}
1520
1521//**************************** D2ClientConfigParser **********************
1522
1524D2ClientConfigParser::getProtocol(ConstElementPtr scope,
1525 const std::string& name) {
1528 (scope, name, "NameChangeRequest protocol"));
1529}
1530
1532D2ClientConfigParser::getFormat(ConstElementPtr scope,
1533 const std::string& name) {
1536 (scope, name, "NameChangeRequest format"));
1537}
1538
1540D2ClientConfigParser::getMode(ConstElementPtr scope,
1541 const std::string& name) {
1544 (scope, name, "ReplaceClientName mode"));
1545}
1546
1549 D2ClientConfigPtr new_config;
1550
1551 // Get all parameters that are needed to create the D2ClientConfig.
1552 bool enable_updates = getBoolean(client_config, "enable-updates");
1553
1554 IOAddress server_ip = getAddress(client_config, "server-ip");
1555
1556 uint32_t server_port = getUint32(client_config, "server-port");
1557
1558 std::string sender_ip_str = getString(client_config, "sender-ip");
1559
1560 uint32_t sender_port = getUint32(client_config, "sender-port");
1561
1562 uint32_t max_queue_size = getUint32(client_config, "max-queue-size");
1563
1564 dhcp_ddns::NameChangeProtocol ncr_protocol =
1565 getProtocol(client_config, "ncr-protocol");
1566
1567 dhcp_ddns::NameChangeFormat ncr_format =
1568 getFormat(client_config, "ncr-format");
1569
1570 IOAddress sender_ip(0);
1571 if (sender_ip_str.empty()) {
1572 // The default sender IP depends on the server IP family
1573 sender_ip = (server_ip.isV4() ? IOAddress::IPV4_ZERO_ADDRESS() :
1575 } else {
1576 try {
1577 sender_ip = IOAddress(sender_ip_str);
1578 } catch (const std::exception& ex) {
1579 isc_throw(DhcpConfigError, "invalid address (" << sender_ip_str
1580 << ") specified for parameter 'sender-ip' ("
1581 << getPosition("sender-ip", client_config) << ")");
1582 }
1583 }
1584
1585 // Now we check for logical errors. This repeats what is done in
1586 // D2ClientConfig::validate(), but doing it here permits us to
1587 // emit meaningful parameter position info in the error.
1588 if (ncr_format != dhcp_ddns::FMT_JSON) {
1589 isc_throw(D2ClientError, "D2ClientConfig error: NCR Format: "
1590 << dhcp_ddns::ncrFormatToString(ncr_format)
1591 << " is not supported. ("
1592 << getPosition("ncr-format", client_config) << ")");
1593 }
1594
1595 if (ncr_protocol != dhcp_ddns::NCR_UDP) {
1596 isc_throw(D2ClientError, "D2ClientConfig error: NCR Protocol: "
1597 << dhcp_ddns::ncrProtocolToString(ncr_protocol)
1598 << " is not supported. ("
1599 << getPosition("ncr-protocol", client_config) << ")");
1600 }
1601
1602 if (sender_ip.getFamily() != server_ip.getFamily()) {
1604 "D2ClientConfig error: address family mismatch: "
1605 << "server-ip: " << server_ip.toText()
1606 << " is: " << (server_ip.isV4() ? "IPv4" : "IPv6")
1607 << " while sender-ip: " << sender_ip.toText()
1608 << " is: " << (sender_ip.isV4() ? "IPv4" : "IPv6")
1609 << " (" << getPosition("sender-ip", client_config) << ")");
1610 }
1611
1612 if (server_ip == sender_ip && server_port == sender_port) {
1614 "D2ClientConfig error: server and sender cannot"
1615 " share the exact same IP address/port: "
1616 << server_ip.toText() << "/" << server_port
1617 << " (" << getPosition("sender-ip", client_config) << ")");
1618 }
1619
1620 try {
1621 // Attempt to create the new client config.
1622 new_config.reset(new D2ClientConfig(enable_updates,
1623 server_ip,
1624 server_port,
1625 sender_ip,
1626 sender_port,
1627 max_queue_size,
1628 ncr_protocol,
1629 ncr_format));
1630 } catch (const std::exception& ex) {
1631 isc_throw(DhcpConfigError, ex.what() << " ("
1632 << client_config->getPosition() << ")");
1633 }
1634
1635 // Add user context
1636 ConstElementPtr user_context = client_config->get("user-context");
1637 if (user_context) {
1638 new_config->setContext(user_context);
1639 }
1640
1641 return (new_config);
1642}
1643
1646 // enable-updates is unconditionally required
1647 { "server-ip", Element::string, "127.0.0.1" },
1648 { "server-port", Element::integer, "53001" },
1649 // default sender-ip depends on server-ip family, so we leave default blank
1650 // parser knows to use the appropriate ZERO address based on server-ip
1651 { "sender-ip", Element::string, "" },
1652 { "sender-port", Element::integer, "0" },
1653 { "max-queue-size", Element::integer, "1024" },
1654 { "ncr-protocol", Element::string, "UDP" },
1655 { "ncr-format", Element::string, "JSON" }
1656};
1657
1658size_t
1660 ElementPtr mutable_d2 = boost::const_pointer_cast<Element>(d2_config);
1662}
1663
1664void
1666 if (compatibility) {
1667 auto family = CfgMgr::instance().getFamily();
1668 for (auto const& kv : compatibility->mapValue()) {
1669 if (!kv.second || (kv.second->getType() != Element::boolean)) {
1671 "compatibility parameter values must be "
1672 << "boolean (" << kv.first << " at "
1673 << kv.second->getPosition() << ")");
1674 }
1675 if (kv.first == "lenient-option-parsing") {
1676 srv_cfg.setLenientOptionParsing(kv.second->boolValue());
1677 } else if (family == AF_INET) {
1678 if (kv.first == "ignore-dhcp-server-identifier") {
1679 srv_cfg.setIgnoreServerIdentifier(kv.second->boolValue());
1680 } else if (kv.first == "ignore-rai-link-selection") {
1681 srv_cfg.setIgnoreRAILinkSelection(kv.second->boolValue());
1682 } else if (kv.first == "exclude-first-last-24") {
1683 srv_cfg.setExcludeFirstLast24(kv.second->boolValue());
1684 } else {
1686 "unsupported compatibility parameter: "
1687 << kv.first << " (" << kv.second->getPosition()
1688 << ")");
1689 }
1690 } else {
1692 "unsupported compatibility parameter: "
1693 << kv.first << " (" << kv.second->getPosition()
1694 << ")");
1695 }
1696 }
1697 }
1698}
1699
1700} // namespace dhcp
1701} // 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.
static void getClientClassesElem(data::ConstElementPtr params, ClassAdderFunc adder_func)
Fetches the element for either 'client-classes' or deprecated 'client-class'.
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:28
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 allowClientClass(const isc::dhcp::ClientClass &class_name)
Adds class clas_name to the allowed client classes list.
Definition network.cc:79
void addAdditionalClass(const isc::dhcp::ClientClass &class_name)
Adds class class_name to the additional classes list.
Definition network.cc:86
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:242
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:301
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 allowClientClass(const isc::dhcp::ClientClass &class_name)
Adds class clas_name to the allowed client classes list.
Definition pool.cc:38
void addAdditionalClass(const ClientClass &class_name)
Adds class class_name to the additional classes list.
Definition pool.cc:45
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:1416
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:485
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