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