Kea 3.1.1
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 // Parse adaptive lease time parameter.
976 parseAdaptiveLeaseTimeParam(params, network);
977
978 // Set the offer_lft value for the subnet.
979 if (params->contains("offer-lifetime")) {
980 uint32_t offer_lft = getInteger(params, "offer-lifetime");
981 subnet4->setOfferLft(offer_lft);
982 }
983
984 // Parse offer-lifetime parameter.
985 Network4Ptr network4 = boost::dynamic_pointer_cast<Network4>(subnet4);
986 parseOfferLft(params, network4);
987
988}
989
990void
992 const IOAddress& address = host->getIPv4Reservation();
993 if (!address.isV4Zero() && !subnet->inRange(address)) {
994 isc_throw(DhcpConfigError, "specified reservation '" << address
995 << "' is not within the IPv4 subnet '"
996 << subnet->toText() << "'");
997 }
998}
999
1000boost::shared_ptr<PoolsListParser>
1002 return (boost::make_shared<Pools4ListParser>());
1003}
1004
1005//**************************** Subnets4ListConfigParser **********************
1006
1008 : check_iface_(check_iface) {
1009}
1010
1011size_t
1013 ConstElementPtr subnets_list,
1014 bool encapsulate_options) {
1015 size_t cnt = 0;
1016 for (auto const& subnet_json : subnets_list->listValue()) {
1017
1018 auto const& parser = createSubnetConfigParser();
1019 Subnet4Ptr subnet = parser->parse(subnet_json, encapsulate_options);
1020 if (subnet) {
1021
1022 // Adding a subnet to the Configuration Manager may fail if the
1023 // subnet id is invalid (duplicate). Thus, we catch exceptions
1024 // here to append a position in the configuration string.
1025 try {
1026 cfg->getCfgSubnets4()->add(subnet);
1027 cnt++;
1028 } catch (const std::exception& ex) {
1029 isc_throw(DhcpConfigError, ex.what() << " ("
1030 << subnet_json->getPosition() << ")");
1031 }
1032 }
1033 }
1034 return (cnt);
1035}
1036
1037size_t
1039 data::ConstElementPtr subnets_list,
1040 bool encapsulate_options) {
1041 size_t cnt = 0;
1042 for (auto const& subnet_json : subnets_list->listValue()) {
1043
1044 auto const& parser = createSubnetConfigParser();
1045 Subnet4Ptr subnet = parser->parse(subnet_json, encapsulate_options);
1046 if (subnet) {
1047 try {
1048 auto ret = subnets.insert(subnet);
1049 if (!ret.second) {
1051 "can't store subnet because of conflict");
1052 }
1053 ++cnt;
1054 } catch (const std::exception& ex) {
1055 isc_throw(DhcpConfigError, ex.what() << " ("
1056 << subnet_json->getPosition() << ")");
1057 }
1058 }
1059 }
1060 return (cnt);
1061}
1062
1063boost::shared_ptr<Subnet4ConfigParser>
1065 return (boost::make_shared<Subnet4ConfigParser>(check_iface_));
1066}
1067
1068//**************************** Pool6Parser *********************************
1069
1070PoolPtr
1071Pool6Parser::poolMaker(IOAddress &addr, uint32_t len, int32_t ptype)
1072{
1073 return (PoolPtr(new Pool6(static_cast<isc::dhcp::Lease::Type>
1074 (ptype), addr, len)));
1075}
1076
1077PoolPtr
1079{
1080 return (PoolPtr(new Pool6(static_cast<isc::dhcp::Lease::Type>
1081 (ptype), min, max)));
1082}
1083
1084
1085//**************************** Pool6ListParser ***************************
1086
1087void
1089 bool encapsulate_options) {
1090 for (auto const& pool : pools_list->listValue()) {
1091 auto const& parser = createPoolConfigParser();
1092 parser->parse(pools, pool, AF_INET6, encapsulate_options);
1093 }
1094}
1095
1096boost::shared_ptr<PoolParser>
1098 return (boost::make_shared<Pool6Parser>());
1099}
1100
1101//**************************** PdPoolParser ******************************
1102
1105
1106void
1108 bool encapsulate_options) {
1110
1111 std::string addr_str = getString(pd_pool, "prefix");
1112
1113 uint8_t prefix_len = getUint8(pd_pool, "prefix-len");
1114
1115 uint8_t delegated_len = getUint8(pd_pool, "delegated-len");
1116
1117 std::string excluded_prefix_str = "::";
1118 if (pd_pool->contains("excluded-prefix")) {
1119 excluded_prefix_str = getString(pd_pool, "excluded-prefix");
1120 }
1121
1122 uint8_t excluded_prefix_len = 0;
1123 if (pd_pool->contains("excluded-prefix-len")) {
1124 excluded_prefix_len = getUint8(pd_pool, "excluded-prefix-len");
1125 }
1126
1127 ConstElementPtr user_context = pd_pool->get("user-context");
1128 if (user_context) {
1129 user_context_ = user_context;
1130 }
1131
1132 ConstElementPtr client_class = pd_pool->get("client-class");
1133 if (client_class) {
1134 client_class_ = client_class;
1135 }
1136
1137 // Check the pool parameters. It will throw an exception if any
1138 // of the required parameters are invalid.
1139 try {
1140 // Attempt to construct the local pool.
1141 pool_.reset(new Pool6(IOAddress(addr_str),
1142 prefix_len,
1143 delegated_len,
1144 IOAddress(excluded_prefix_str),
1145 excluded_prefix_len));
1146 } catch (const std::exception& ex) {
1147 // Some parameters don't exist or are invalid. Since we are not
1148 // aware whether they don't exist or are invalid, let's append
1149 // the position of the pool map element.
1151 << " (" << pd_pool->getPosition() << ")");
1152 }
1153
1154 // If there is a pool-id, store it.
1155 ConstElementPtr pool_id = pd_pool->get("pool-id");
1156 if (pool_id) {
1157 if (pool_id->intValue() <= 0) {
1158 isc_throw(BadValue, "pool-id " << pool_id->intValue() << " is not"
1159 << " a positive integer greater than 0");
1160 } else if (pool_id->intValue() > numeric_limits<uint32_t>::max()) {
1161 isc_throw(BadValue, "pool-id " << pool_id->intValue() << " is not"
1162 << " a 32 bit unsigned integer");
1163 }
1164
1165 pool_->setID(pool_id->intValue());
1166 }
1167
1168 // We create subnet first and then parse the options straight into the subnet's
1169 // CfgOption structure. Previously, we first parsed the options and then copied
1170 // them into the CfgOption after creating the subnet but it had two issues. First,
1171 // it cost performance. Second, copying options reset the isEncapsulated() flag.
1172 // If the options have been encapsulated we want to preserve the flag to ensure
1173 // they are not encapsulated several times.
1174 ConstElementPtr option_data = pd_pool->get("option-data");
1175 if (option_data) {
1176 auto opts_parser = createOptionDataListParser();
1177 opts_parser->parse(pool_->getCfgOption(), option_data, encapsulate_options);
1178 }
1179
1180 if (user_context_) {
1181 pool_->setContext(user_context_);
1182 }
1183
1184 if (client_class_) {
1185 string cclass = client_class_->stringValue();
1186 if (!cclass.empty()) {
1187 pool_->allowClientClass(cclass);
1188 }
1189 }
1190
1191 // Setup client class list.
1193 std::bind(&Pool::allowClientClass,
1194 boost::dynamic_pointer_cast<Pool>(pool_), ph::_1));
1195
1196 // Setup additional class list.
1198 std::bind(&Pool::addAdditionalClass,
1199 boost::dynamic_pointer_cast<Pool>(pool_), ph::_1));
1200
1201 // Add the local pool to the external storage ptr.
1202 pools->push_back(pool_);
1203}
1204
1205boost::shared_ptr<OptionDataListParser>
1207 return (boost::make_shared<OptionDataListParser>(AF_INET6));
1208}
1209
1210//**************************** PdPoolsListParser ************************
1211
1212void
1214 // Loop through the list of pd pools.
1215 for (auto const& pd_pool : pd_pool_list->listValue()) {
1216 auto const& parser = createPdPoolConfigParser();
1217 parser->parse(pools, pd_pool);
1218 }
1219}
1220
1221boost::shared_ptr<PdPoolParser>
1223 return (boost::make_shared<PdPoolParser>());
1224}
1225
1226//**************************** Subnet6ConfigParser ***********************
1227
1229 : SubnetConfigParser(AF_INET6, check_iface) {
1230}
1231
1233Subnet6ConfigParser::parse(ConstElementPtr subnet, bool encapsulate_options) {
1234 // Check parameters.
1236
1238 ConstElementPtr pools = subnet->get("pools");
1239 if (pools) {
1240 auto const& parser = createPoolsListParser();
1241 parser->parse(pools_, pools, encapsulate_options);
1242 }
1243 ConstElementPtr pd_pools = subnet->get("pd-pools");
1244 if (pd_pools) {
1245 auto const& parser = createPdPoolsListParser();
1246 parser->parse(pools_, pd_pools);
1247 }
1248
1249 SubnetPtr generic = SubnetConfigParser::parse(subnet, encapsulate_options);
1250
1251 if (!generic) {
1252 // Sanity check: not supposed to fail.
1254 "Failed to create an IPv6 subnet (" <<
1255 subnet->getPosition() << ")");
1256 }
1257
1258 Subnet6Ptr sn6ptr = boost::dynamic_pointer_cast<Subnet6>(subnet_);
1259 if (!sn6ptr) {
1260 // If we hit this, it is a programming error.
1262 "Invalid Subnet6 cast in Subnet6ConfigParser::parse");
1263 }
1264
1265 // Set relay information if it was provided
1266 if (relay_info_) {
1267 sn6ptr->setRelayInfo(*relay_info_);
1268 }
1269
1270 // Parse Host Reservations for this subnet if any.
1271 ConstElementPtr reservations = subnet->get("reservations");
1272 if (reservations) {
1273 HostCollection hosts;
1275 parser.parse(subnet_->getID(), reservations, hosts);
1276 for (auto const& h : hosts) {
1277 validateResvs(sn6ptr, h);
1278 CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(h);
1279 }
1280 }
1281
1282 // Parse allocator specification.
1283 auto network = boost::dynamic_pointer_cast<Network>(sn6ptr);
1284 parseAllocatorParams(subnet, network);
1285
1286 // Parse pd-allocator specification.
1287 auto network6 = boost::dynamic_pointer_cast<Network6>(sn6ptr);
1288 parsePdAllocatorParams(subnet, network6);
1289
1290 // Instantiate the allocators.
1291 sn6ptr->createAllocators();
1292
1293 return (sn6ptr);
1294}
1295
1296// Unused?
1297void
1303
1304void
1306 asiolink::IOAddress addr, uint8_t len) {
1307 // Subnet ID is required and must be in 1..SUBNET_ID_MAX.
1308 int64_t subnet_id_max = static_cast<int64_t>(SUBNET_ID_MAX);
1309 SubnetID subnet_id = static_cast<SubnetID>(getInteger(params, "id", 1,
1310 subnet_id_max));
1311
1312 // We want to log whether rapid-commit is enabled, so we get this
1313 // before the actual subnet creation.
1314 Optional<bool> rapid_commit;
1315 if (params->contains("rapid-commit")) {
1316 rapid_commit = getBoolean(params, "rapid-commit");
1317 }
1318
1319 // Parse preferred lifetime as it is not parsed by the common function.
1320 Triplet<uint32_t> pref = parseIntTriplet(params, "preferred-lifetime");
1321
1322 // Create a new subnet.
1323 auto subnet6 = Subnet6::create(addr, len, Triplet<uint32_t>(),
1325 pref,
1327 subnet_id);
1328 subnet_ = subnet6;
1329
1330 ElementPtr mutable_params;
1331 mutable_params = boost::const_pointer_cast<Element>(params);
1332
1333 // Parse parameters common to all Network derivations.
1334 NetworkPtr network = boost::dynamic_pointer_cast<Network>(subnet_);
1335 parseCommon(mutable_params, network);
1336
1337 // Enable or disable Rapid Commit option support for the subnet.
1338 if (!rapid_commit.unspecified()) {
1339 subnet6->setRapidCommit(rapid_commit);
1340 }
1341
1342 std::ostringstream output;
1343 output << addr << "/" << static_cast<int>(len) << " with params: ";
1344 // t1 and t2 are optional may be not specified.
1345
1346 bool has_renew = !subnet6->getT1().unspecified();
1347 bool has_rebind = !subnet6->getT2().unspecified();
1348 int64_t renew = -1;
1349 int64_t rebind = -1;
1350
1351 if (has_renew) {
1352 renew = subnet6->getT1().get();
1353 output << "t1=" << renew << ", ";
1354 }
1355 if (has_rebind) {
1356 rebind = subnet6->getT2().get();
1357 output << "t2=" << rebind << ", ";
1358 }
1359
1360 if (!subnet6->getPreferred().unspecified()) {
1361 output << "preferred-lifetime=" << subnet6->getPreferred().get() << ", ";
1362 }
1363 if (!subnet6->getValid().unspecified()) {
1364 output << "valid-lifetime=" << subnet6->getValid().get();
1365 }
1366 if (!subnet6->getRapidCommit().unspecified()) {
1367 output << ", rapid-commit is "
1368 << boolalpha << subnet6->getRapidCommit().get();
1369 }
1370
1372
1373 // Get interface-id option content. For now we support string
1374 // representation only
1375 Optional<std::string> ifaceid;
1376 if (params->contains("interface-id")) {
1377 ifaceid = getString(params, "interface-id");
1378 }
1379
1381 if (params->contains("interface")) {
1382 iface = getString(params, "interface");
1383 }
1384
1385 // Specifying both interface for locally reachable subnets and
1386 // interface id for relays is mutually exclusive. Need to test for
1387 // this condition.
1388 if (!ifaceid.unspecified() && !iface.unspecified() && !ifaceid.empty() &&
1389 !iface.empty()) {
1391 "parser error: interface (defined for locally reachable "
1392 "subnets) and interface-id (defined for subnets reachable"
1393 " via relays) cannot be defined at the same time for "
1394 "subnet " << addr << "/" << (int)len << "("
1395 << params->getPosition() << ")");
1396 }
1397
1398 // Configure interface-id for remote interfaces, if defined
1399 if (!ifaceid.unspecified() && !ifaceid.empty()) {
1400 std::string ifaceid_value = ifaceid.get();
1401 OptionBuffer tmp(ifaceid_value.begin(), ifaceid_value.end());
1403 subnet6->setInterfaceId(opt);
1404 }
1405
1406 // Get interface name. If it is defined, then the subnet is available
1407 // directly over specified network interface.
1408 if (!iface.unspecified() && !iface.empty()) {
1409 if (check_iface_ && !IfaceMgr::instance().getIface(iface)) {
1410 ConstElementPtr error = params->get("interface");
1411 isc_throw(DhcpConfigError, "Specified network interface name " << iface
1412 << " for subnet " << subnet6->toText()
1413 << " is not present in the system ("
1414 << error->getPosition() << ")");
1415 }
1416
1417 subnet6->setIface(iface);
1418 }
1419
1420 // Try setting up client class.
1421 if (params->contains("client-class")) {
1422 string client_class = getString(params, "client-class");
1423 if (!client_class.empty()) {
1424 subnet6->allowClientClass(client_class);
1425 }
1426 }
1427
1428 // Setup client class list.
1430 boost::dynamic_pointer_cast<Network>(subnet6), ph::_1));
1431
1432 // Setup additional class list.
1434 boost::dynamic_pointer_cast<Network>(subnet6), ph::_1));
1435
1438
1439 // Parse t1-percent and t2-percent
1440 parseTeePercents(params, network);
1441
1442 // Parse DDNS parameters
1443 parseDdnsParams(params, network);
1444
1445 // Parse lease cache parameters
1446 parseCacheParams(params, network);
1447
1448 // Parse adaptive lease time parameter.
1449 parseAdaptiveLeaseTimeParam(params, network);
1450}
1451
1452void
1454 const IPv6ResrvRange& range = host->getIPv6Reservations(IPv6Resrv::TYPE_NA);
1455 BOOST_FOREACH(auto const& it, range) {
1456 const IOAddress& address = it.second.getPrefix();
1457 if (!subnet->inRange(address)) {
1458 isc_throw(DhcpConfigError, "specified reservation '" << address
1459 << "' is not within the IPv6 subnet '"
1460 << subnet->toText() << "'");
1461 }
1462 }
1463}
1464
1465boost::shared_ptr<PoolsListParser>
1467 return (boost::make_shared<Pools6ListParser>());
1468}
1469
1470boost::shared_ptr<PdPoolsListParser>
1472 return (boost::make_shared<PdPoolsListParser>());
1473}
1474
1475//**************************** Subnet6ListConfigParser ********************
1476
1478 : check_iface_(check_iface) {
1479}
1480
1481size_t
1483 ConstElementPtr subnets_list,
1484 bool encapsulate_options) {
1485 size_t cnt = 0;
1486 for (auto const& subnet_json : subnets_list->listValue()) {
1487
1488 auto const& parser = createSubnetConfigParser();
1489 Subnet6Ptr subnet = parser->parse(subnet_json, encapsulate_options);
1490
1491 // Adding a subnet to the Configuration Manager may fail if the
1492 // subnet id is invalid (duplicate). Thus, we catch exceptions
1493 // here to append a position in the configuration string.
1494 try {
1495 cfg->getCfgSubnets6()->add(subnet);
1496 cnt++;
1497 } catch (const std::exception& ex) {
1498 isc_throw(DhcpConfigError, ex.what() << " ("
1499 << subnet_json->getPosition() << ")");
1500 }
1501 }
1502 return (cnt);
1503}
1504
1505size_t
1507 ConstElementPtr subnets_list,
1508 bool encapsulate_options) {
1509 size_t cnt = 0;
1510 for (auto const& subnet_json : subnets_list->listValue()) {
1511
1512 auto const& parser = createSubnetConfigParser();
1513 Subnet6Ptr subnet = parser->parse(subnet_json, encapsulate_options);
1514 if (subnet) {
1515 try {
1516 auto ret = subnets.insert(subnet);
1517 if (!ret.second) {
1519 "can't store subnet because of conflict");
1520 }
1521 ++cnt;
1522 } catch (const std::exception& ex) {
1523 isc_throw(DhcpConfigError, ex.what() << " ("
1524 << subnet_json->getPosition() << ")");
1525 }
1526 }
1527 }
1528 return (cnt);
1529}
1530
1531boost::shared_ptr<Subnet6ConfigParser>
1533 return (boost::make_shared<Subnet6ConfigParser>(check_iface_));
1534}
1535
1536//**************************** D2ClientConfigParser **********************
1537
1539D2ClientConfigParser::getProtocol(ConstElementPtr scope,
1540 const std::string& name) {
1543 (scope, name, "NameChangeRequest protocol"));
1544}
1545
1547D2ClientConfigParser::getFormat(ConstElementPtr scope,
1548 const std::string& name) {
1551 (scope, name, "NameChangeRequest format"));
1552}
1553
1555D2ClientConfigParser::getMode(ConstElementPtr scope,
1556 const std::string& name) {
1559 (scope, name, "ReplaceClientName mode"));
1560}
1561
1564 D2ClientConfigPtr new_config;
1565
1566 // Get all parameters that are needed to create the D2ClientConfig.
1567 bool enable_updates = getBoolean(client_config, "enable-updates");
1568
1569 IOAddress server_ip = getAddress(client_config, "server-ip");
1570
1571 uint32_t server_port = getUint32(client_config, "server-port");
1572
1573 std::string sender_ip_str = getString(client_config, "sender-ip");
1574
1575 uint32_t sender_port = getUint32(client_config, "sender-port");
1576
1577 uint32_t max_queue_size = getUint32(client_config, "max-queue-size");
1578
1579 dhcp_ddns::NameChangeProtocol ncr_protocol =
1580 getProtocol(client_config, "ncr-protocol");
1581
1582 dhcp_ddns::NameChangeFormat ncr_format =
1583 getFormat(client_config, "ncr-format");
1584
1585 IOAddress sender_ip(0);
1586 if (sender_ip_str.empty()) {
1587 // The default sender IP depends on the server IP family
1588 sender_ip = (server_ip.isV4() ? IOAddress::IPV4_ZERO_ADDRESS() :
1590 } else {
1591 try {
1592 sender_ip = IOAddress(sender_ip_str);
1593 } catch (const std::exception& ex) {
1594 isc_throw(DhcpConfigError, "invalid address (" << sender_ip_str
1595 << ") specified for parameter 'sender-ip' ("
1596 << getPosition("sender-ip", client_config) << ")");
1597 }
1598 }
1599
1600 // Now we check for logical errors. This repeats what is done in
1601 // D2ClientConfig::validate(), but doing it here permits us to
1602 // emit meaningful parameter position info in the error.
1603 if (ncr_format != dhcp_ddns::FMT_JSON) {
1604 isc_throw(D2ClientError, "D2ClientConfig error: NCR Format: "
1605 << dhcp_ddns::ncrFormatToString(ncr_format)
1606 << " is not supported. ("
1607 << getPosition("ncr-format", client_config) << ")");
1608 }
1609
1610 if (ncr_protocol != dhcp_ddns::NCR_UDP) {
1611 isc_throw(D2ClientError, "D2ClientConfig error: NCR Protocol: "
1612 << dhcp_ddns::ncrProtocolToString(ncr_protocol)
1613 << " is not supported. ("
1614 << getPosition("ncr-protocol", client_config) << ")");
1615 }
1616
1617 if (sender_ip.getFamily() != server_ip.getFamily()) {
1619 "D2ClientConfig error: address family mismatch: "
1620 << "server-ip: " << server_ip.toText()
1621 << " is: " << (server_ip.isV4() ? "IPv4" : "IPv6")
1622 << " while sender-ip: " << sender_ip.toText()
1623 << " is: " << (sender_ip.isV4() ? "IPv4" : "IPv6")
1624 << " (" << getPosition("sender-ip", client_config) << ")");
1625 }
1626
1627 if (server_ip == sender_ip && server_port == sender_port) {
1629 "D2ClientConfig error: server and sender cannot"
1630 " share the exact same IP address/port: "
1631 << server_ip.toText() << "/" << server_port
1632 << " (" << getPosition("sender-ip", client_config) << ")");
1633 }
1634
1635 try {
1636 // Attempt to create the new client config.
1637 new_config.reset(new D2ClientConfig(enable_updates,
1638 server_ip,
1639 server_port,
1640 sender_ip,
1641 sender_port,
1642 max_queue_size,
1643 ncr_protocol,
1644 ncr_format));
1645 } catch (const std::exception& ex) {
1646 isc_throw(DhcpConfigError, ex.what() << " ("
1647 << client_config->getPosition() << ")");
1648 }
1649
1650 // Add user context
1651 ConstElementPtr user_context = client_config->get("user-context");
1652 if (user_context) {
1653 new_config->setContext(user_context);
1654 }
1655
1656 return (new_config);
1657}
1658
1661 // enable-updates is unconditionally required
1662 { "server-ip", Element::string, "127.0.0.1" },
1663 { "server-port", Element::integer, "53001" },
1664 // default sender-ip depends on server-ip family, so we leave default blank
1665 // parser knows to use the appropriate ZERO address based on server-ip
1666 { "sender-ip", Element::string, "" },
1667 { "sender-port", Element::integer, "0" },
1668 { "max-queue-size", Element::integer, "1024" },
1669 { "ncr-protocol", Element::string, "UDP" },
1670 { "ncr-format", Element::string, "JSON" }
1671};
1672
1673size_t
1675 ElementPtr mutable_d2 = boost::const_pointer_cast<Element>(d2_config);
1677}
1678
1679void
1681 if (compatibility) {
1682 auto family = CfgMgr::instance().getFamily();
1683 for (auto const& kv : compatibility->mapValue()) {
1684 if (!kv.second || (kv.second->getType() != Element::boolean)) {
1686 "compatibility parameter values must be "
1687 << "boolean (" << kv.first << " at "
1688 << kv.second->getPosition() << ")");
1689 }
1690 if (kv.first == "lenient-option-parsing") {
1691 srv_cfg.setLenientOptionParsing(kv.second->boolValue());
1692 } else if (family == AF_INET) {
1693 if (kv.first == "ignore-dhcp-server-identifier") {
1694 srv_cfg.setIgnoreServerIdentifier(kv.second->boolValue());
1695 } else if (kv.first == "ignore-rai-link-selection") {
1696 srv_cfg.setIgnoreRAILinkSelection(kv.second->boolValue());
1697 } else if (kv.first == "exclude-first-last-24") {
1698 srv_cfg.setExcludeFirstLast24(kv.second->boolValue());
1699 } else {
1701 "unsupported compatibility parameter: "
1702 << kv.first << " (" << kv.second->getPosition()
1703 << ")");
1704 }
1705 } else {
1707 "unsupported compatibility parameter: "
1708 << kv.first << " (" << kv.second->getPosition()
1709 << ")");
1710 }
1711 }
1712 }
1713}
1714
1715} // namespace dhcp
1716} // namespace isc
@ integer
Definition data.h:140
@ string
Definition data.h:144
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 parseAdaptiveLeaseTimeParam(const data::ConstElementPtr &network_data, NetworkPtr &network)
Parses parameter related to adaptive lease time.
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:246
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:29
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition cfgmgr.cc:121
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
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:1503
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:973
@ 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