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