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