Kea 2.0.3
srv_config.cc
Go to the documentation of this file.
1// Copyright (C) 2014-2021 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>
9#include <dhcpsrv/cfgmgr.h>
12#include <dhcpsrv/srv_config.h>
14#include <dhcpsrv/dhcpsrv_log.h>
17#include <log/logger_manager.h>
19#include <dhcp/pkt.h> // Needed for HWADDR_SOURCE_*
20#include <stats/stats_mgr.h>
21#include <util/strutil.h>
22
23#include <boost/make_shared.hpp>
24
25#include <list>
26#include <sstream>
27
28using namespace isc::log;
29using namespace isc::data;
30using namespace isc::process;
31
32namespace isc {
33namespace dhcp {
34
36 : sequence_(0), cfg_iface_(new CfgIface()),
37 cfg_option_def_(new CfgOptionDef()), cfg_option_(new CfgOption()),
38 cfg_subnets4_(new CfgSubnets4()), cfg_subnets6_(new CfgSubnets6()),
39 cfg_shared_networks4_(new CfgSharedNetworks4()),
40 cfg_shared_networks6_(new CfgSharedNetworks6()),
41 cfg_hosts_(new CfgHosts()), cfg_rsoo_(new CfgRSOO()),
42 cfg_expiration_(new CfgExpiration()), cfg_duid_(new CfgDUID()),
43 cfg_db_access_(new CfgDbAccess()),
44 cfg_host_operations4_(CfgHostOperations::createConfig4()),
45 cfg_host_operations6_(CfgHostOperations::createConfig6()),
46 class_dictionary_(new ClientClassDictionary()),
47 decline_timer_(0), echo_v4_client_id_(true), dhcp4o6_port_(0),
48 d2_client_config_(new D2ClientConfig()),
49 configured_globals_(Element::createMap()),
50 cfg_consist_(new CfgConsistency()),
51 lenient_option_parsing_(false) {
52}
53
54SrvConfig::SrvConfig(const uint32_t sequence)
55 : sequence_(sequence), cfg_iface_(new CfgIface()),
56 cfg_option_def_(new CfgOptionDef()), cfg_option_(new CfgOption()),
57 cfg_subnets4_(new CfgSubnets4()), cfg_subnets6_(new CfgSubnets6()),
58 cfg_shared_networks4_(new CfgSharedNetworks4()),
59 cfg_shared_networks6_(new CfgSharedNetworks6()),
60 cfg_hosts_(new CfgHosts()), cfg_rsoo_(new CfgRSOO()),
61 cfg_expiration_(new CfgExpiration()), cfg_duid_(new CfgDUID()),
62 cfg_db_access_(new CfgDbAccess()),
63 cfg_host_operations4_(CfgHostOperations::createConfig4()),
64 cfg_host_operations6_(CfgHostOperations::createConfig6()),
65 class_dictionary_(new ClientClassDictionary()),
66 decline_timer_(0), echo_v4_client_id_(true), dhcp4o6_port_(0),
67 d2_client_config_(new D2ClientConfig()),
68 configured_globals_(Element::createMap()),
69 cfg_consist_(new CfgConsistency()),
70 lenient_option_parsing_(false) {
71}
72
73std::string
74SrvConfig::getConfigSummary(const uint32_t selection) const {
75 std::ostringstream s;
76 size_t subnets_num;
77 if ((selection & CFGSEL_SUBNET4) == CFGSEL_SUBNET4) {
78 subnets_num = getCfgSubnets4()->getAll()->size();
79 if (subnets_num > 0) {
80 s << "added IPv4 subnets: " << subnets_num;
81 } else {
82 s << "no IPv4 subnets!";
83 }
84 s << "; ";
85 }
86
87 if ((selection & CFGSEL_SUBNET6) == CFGSEL_SUBNET6) {
88 subnets_num = getCfgSubnets6()->getAll()->size();
89 if (subnets_num > 0) {
90 s << "added IPv6 subnets: " << subnets_num;
91 } else {
92 s << "no IPv6 subnets!";
93 }
94 s << "; ";
95 }
96
97 if ((selection & CFGSEL_DDNS) == CFGSEL_DDNS) {
98 bool ddns_enabled = getD2ClientConfig()->getEnableUpdates();
99 s << "DDNS: " << (ddns_enabled ? "enabled" : "disabled") << "; ";
100 }
101
102 if (s.tellp() == static_cast<std::streampos>(0)) {
103 s << "no config details available";
104 }
105
106 std::string summary = s.str();
107 size_t last_separator_pos = summary.find_last_of(";");
108 if (last_separator_pos == summary.length() - 2) {
109 summary.erase(last_separator_pos);
110 }
111 return (summary);
112}
113
114bool
116 return (getSequence() == other.getSequence());
117}
118
119void
120SrvConfig::copy(SrvConfig& new_config) const {
121 ConfigBase::copy(new_config);
122
123 // Replace interface configuration.
124 new_config.cfg_iface_.reset(new CfgIface(*cfg_iface_));
125 // Replace option definitions.
126 cfg_option_def_->copyTo(*new_config.cfg_option_def_);
127 cfg_option_->copyTo(*new_config.cfg_option_);
128 // Replace the client class dictionary
129 new_config.class_dictionary_.reset(new ClientClassDictionary(*class_dictionary_));
130 // Replace the D2 client configuration
132 // Replace configured hooks libraries.
133 new_config.hooks_config_.clear();
134 using namespace isc::hooks;
135 for (HookLibsCollection::const_iterator it =
136 hooks_config_.get().begin();
137 it != hooks_config_.get().end(); ++it) {
138 new_config.hooks_config_.add(it->first, it->second);
139 }
140}
141
142bool
143SrvConfig::equals(const SrvConfig& other) const {
144
145 // Checks common elements: logging & config control
146 if (!ConfigBase::equals(other)) {
147 return (false);
148 }
149
150 // Common information is equal between objects, so check other values.
151 if ((*cfg_iface_ != *other.cfg_iface_) ||
152 (*cfg_option_def_ != *other.cfg_option_def_) ||
153 (*cfg_option_ != *other.cfg_option_) ||
154 (*class_dictionary_ != *other.class_dictionary_) ||
155 (*d2_client_config_ != *other.d2_client_config_)) {
156 return (false);
157 }
158 // Now only configured hooks libraries can differ.
159 // If number of configured hooks libraries are different, then
160 // configurations aren't equal.
161 if (hooks_config_.get().size() != other.hooks_config_.get().size()) {
162 return (false);
163 }
164 // Pass through all configured hooks libraries.
165 return (hooks_config_.equal(other.hooks_config_));
166}
167
168void
170 ConfigBase::merge(other);
171 try {
172 SrvConfig& other_srv_config = dynamic_cast<SrvConfig&>(other);
173 // We merge objects in order of dependency (real or theoretical).
174 // First we merge the common stuff.
175
176 // Merge globals.
177 mergeGlobals(other_srv_config);
178
179 // Merge option defs. We need to do this next so we
180 // pass these into subsequent merges so option instances
181 // at each level can be created based on the merged
182 // definitions.
183 cfg_option_def_->merge((*other_srv_config.getCfgOptionDef()));
184
185 // Merge options.
186 cfg_option_->merge(cfg_option_def_, (*other_srv_config.getCfgOption()));
187
188 if (!other_srv_config.getClientClassDictionary()->empty()) {
189 // Client classes are complicated because they are ordered and may
190 // depend on each other. Merging two lists of classes with preserving
191 // the order would be very involved and could result in errors. Thus,
192 // we simply replace the current list of classes with a new list.
193 setClientClassDictionary(boost::make_shared
194 <ClientClassDictionary>(*other_srv_config.getClientClassDictionary()));
195 }
196
197 if (CfgMgr::instance().getFamily() == AF_INET) {
198 merge4(other_srv_config);
199 } else {
200 merge6(other_srv_config);
201 }
202 } catch (const std::bad_cast&) {
203 isc_throw(InvalidOperation, "internal server error: must use derivation"
204 " of the SrvConfig as an argument of the call to"
205 " SrvConfig::merge()");
206 }
207}
208
209void
210SrvConfig::merge4(SrvConfig& other) {
211 // Merge shared networks.
212 cfg_shared_networks4_->merge(cfg_option_def_, *(other.getCfgSharedNetworks4()));
213
214 // Merge subnets.
215 cfg_subnets4_->merge(cfg_option_def_, getCfgSharedNetworks4(),
216 *(other.getCfgSubnets4()));
217
219}
220
221void
222SrvConfig::merge6(SrvConfig& other) {
223 // Merge shared networks.
224 cfg_shared_networks6_->merge(cfg_option_def_, *(other.getCfgSharedNetworks6()));
225
226 // Merge subnets.
227 cfg_subnets6_->merge(cfg_option_def_, getCfgSharedNetworks6(),
228 *(other.getCfgSubnets6()));
229
231}
232
233void
234SrvConfig::mergeGlobals(SrvConfig& other) {
235 auto config_set = getConfiguredGlobals();
236 ElementPtr mutable_cfg = boost::const_pointer_cast<Element>(config_set);
237 // If the deprecated reservation-mode is found in database, overwrite other
238 // reservation flags so there is no conflict when merging to new flags.
239 if (other.getConfiguredGlobals()->find("reservation-mode")) {
240 mutable_cfg->remove("reservations-global");
241 mutable_cfg->remove("reservations-in-subnet");
242 mutable_cfg->remove("reservations-out-of-pool");
243 }
244 // Iterate over the "other" globals, adding/overwriting them into
245 // this config's list of globals.
246 for (auto other_global : other.getConfiguredGlobals()->mapValue()) {
247 addConfiguredGlobal(other_global.first, other_global.second);
248 }
249
250 // Merge the reservation-mode to new reservation flags.
252
253 // A handful of values are stored as members in SrvConfig. So we'll
254 // iterate over the merged globals, setting appropriate members.
255 for (auto merged_global : config_set->mapValue()) {
256 std::string name = merged_global.first;
257 ConstElementPtr element = merged_global.second;
258 try {
259 if (name == "decline-probation-period") {
260 setDeclinePeriod(element->intValue());
261 } else if (name == "echo-client-id") {
262 // echo-client-id is v4 only, but we'll let upstream
263 // worry about that.
264 setEchoClientId(element->boolValue());
265 } else if (name == "dhcp4o6-port") {
266 setDhcp4o6Port(element->intValue());
267 } else if (name == "server-tag") {
268 setServerTag(element->stringValue());
269 } else if (name == "ip-reservations-unique") {
270 setIPReservationsUnique(element->boolValue());
271 }
272 } catch(const std::exception& ex) {
273 isc_throw (BadValue, "Invalid value:" << element->str()
274 << " explicit global:" << name);
275 }
276 }
277}
278
279void
281 // Removes statistics for v4 and v6 subnets
282 getCfgSubnets4()->removeStatistics();
283
284 getCfgSubnets6()->removeStatistics();
285}
286
287void
289 // Update default sample limits.
291 ConstElementPtr samples =
292 getConfiguredGlobal("statistic-default-sample-count");
293 uint32_t max_samples = 0;
294 if (samples) {
295 max_samples = samples->intValue();
296 stats_mgr.setMaxSampleCountDefault(max_samples);
297 if (max_samples != 0) {
298 stats_mgr.setMaxSampleCountAll(max_samples);
299 }
300 }
301 ConstElementPtr duration =
302 getConfiguredGlobal("statistic-default-sample-age");
303 if (duration) {
304 int64_t time_duration = duration->intValue();
305 auto max_age = std::chrono::seconds(time_duration);
306 stats_mgr.setMaxSampleAgeDefault(max_age);
307 if (max_samples == 0) {
308 stats_mgr.setMaxSampleAgeAll(max_age);
309 }
310 }
311
312 // Updating subnet statistics involves updating lease statistics, which
313 // is done by the LeaseMgr. Since servers with subnets, must have a
314 // LeaseMgr, we do not bother updating subnet stats for servers without
315 // a lease manager, such as D2. @todo We should probably examine why
316 // "SrvConfig" is being used by D2.
318 // Updates statistics for v4 and v6 subnets
319 getCfgSubnets4()->updateStatistics();
320
321 getCfgSubnets6()->updateStatistics();
322 }
323}
324
326SrvConfig::getConfiguredGlobal(std::string name) const {
328 if (configured_globals_->contains(name)) {
329 global = configured_globals_->get(name);
330 }
331
332 return (global);
333}
334
335void
337 configured_globals_ = isc::data::Element::createMap();
338}
339
340void
342 // Code from SimpleParser::setDefaults
343 // This is the position representing a default value. As the values
344 // we're inserting here are not present in whatever the config file
345 // came from, we need to make sure it's clearly labeled as default.
346 const Element::Position pos("<default-value>", 0, 0);
348
349 // Let's go over all parameters we have defaults for.
350 for (auto def_value : defaults) {
351
352 // Try if such a parameter is there. If it is, let's
353 // skip it, because user knows best *cough*.
354 ConstElementPtr x = globals->get(def_value.name_);
355 if (x) {
356 // There is such a value already, skip it.
357 continue;
358 }
359
360 // There isn't such a value defined, let's create the default
361 // value...
362 switch (def_value.type_) {
363 case Element::string: {
364 x.reset(new StringElement(def_value.value_, pos));
365 break;
366 }
367 case Element::integer: {
368 try {
369 int int_value = boost::lexical_cast<int>(def_value.value_);
370 x.reset(new IntElement(int_value, pos));
371 }
372 catch (const std::exception& ex) {
374 "Internal error. Integer value expected for: "
375 << def_value.name_ << ", value is: "
376 << def_value.value_ );
377 }
378
379 break;
380 }
381 case Element::boolean: {
382 bool bool_value;
383 if (def_value.value_ == std::string("true")) {
384 bool_value = true;
385 } else if (def_value.value_ == std::string("false")) {
386 bool_value = false;
387 } else {
389 "Internal error. Boolean value for "
390 << def_value.name_ << " specified as "
391 << def_value.value_ << ", expected true or false");
392 }
393 x.reset(new BoolElement(bool_value, pos));
394 break;
395 }
396 case Element::real: {
397 double dbl_value = boost::lexical_cast<double>(def_value.value_);
398 x.reset(new DoubleElement(dbl_value, pos));
399 break;
400 }
401 default:
402 // No default values for null, list or map
404 "Internal error. Incorrect default value type for "
405 << def_value.name_);
406 }
407 addConfiguredGlobal(def_value.name_, x);
408 }
409}
410
411void
413 if (config->getType() != Element::map) {
414 isc_throw(BadValue, "extractConfiguredGlobals must be given a map element");
415 }
416
417 const std::map<std::string, ConstElementPtr>& values = config->mapValue();
418 for (auto value = values.begin(); value != values.end(); ++value) {
419 if (value->second->getType() != Element::list &&
420 value->second->getType() != Element::map) {
421 addConfiguredGlobal(value->first, value->second);
422 }
423 }
424}
425
426void
427SrvConfig::sanityChecksLifetime(const std::string& name) const {
428 // Initialize as some compilers complain otherwise.
429 uint32_t value = 0;
430 ConstElementPtr has_value = getConfiguredGlobal(name);
431 if (has_value) {
432 value = has_value->intValue();
433 }
434
435 uint32_t min_value = 0;
436 ConstElementPtr has_min = getConfiguredGlobal("min-" + name);
437 if (has_min) {
438 min_value = has_min->intValue();
439 }
440
441 uint32_t max_value = 0;
442 ConstElementPtr has_max = getConfiguredGlobal("max-" + name);
443 if (has_max) {
444 max_value = has_max->intValue();
445 }
446
447 if (!has_value && !has_min && !has_max) {
448 return;
449 }
450 if (has_value) {
451 if (!has_min && !has_max) {
452 // default only.
453 return;
454 } else if (!has_min) {
455 // default and max.
456 min_value = value;
457 } else if (!has_max) {
458 // default and min.
459 max_value = value;
460 }
461 } else if (has_min) {
462 if (!has_max) {
463 // min only.
464 return;
465 } else {
466 // min and max.
467 isc_throw(BadValue, "have min-" << name << " and max-"
468 << name << " but no " << name << " (default)");
469 }
470 } else {
471 // max only.
472 return;
473 }
474
475 // Check that min <= max.
476 if (min_value > max_value) {
477 if (has_min && has_max) {
478 isc_throw(BadValue, "the value of min-" << name << " ("
479 << min_value << ") is not less than max-" << name << " ("
480 << max_value << ")");
481 } else if (has_min) {
482 // Only min and default so min > default.
483 isc_throw(BadValue, "the value of min-" << name << " ("
484 << min_value << ") is not less than (default) " << name
485 << " (" << value << ")");
486 } else {
487 // Only default and max so default > max.
488 isc_throw(BadValue, "the value of (default) " << name
489 << " (" << value << ") is not less than max-" << name
490 << " (" << max_value << ")");
491 }
492 }
493
494 // Check that value is between min and max.
495 if ((value < min_value) || (value > max_value)) {
496 isc_throw(BadValue, "the value of (default) " << name << " ("
497 << value << ") is not between min-" << name << " ("
498 << min_value << ") and max-" << name << " ("
499 << max_value << ")");
500 }
501}
502
503void
505 const std::string& name) const {
506 // Three cases:
507 // - the external/source config has the parameter: use it.
508 // - only the target config has the parameter: use this one.
509 // - no config has the parameter.
510 uint32_t value = 0;
511 ConstElementPtr has_value = getConfiguredGlobal(name);
512 bool new_value = true;
513 if (!has_value) {
514 has_value = target_config.getConfiguredGlobal(name);
515 new_value = false;
516 }
517 if (has_value) {
518 value = has_value->intValue();
519 }
520
521 uint32_t min_value = 0;
522 ConstElementPtr has_min = getConfiguredGlobal("min-" + name);
523 bool new_min = true;
524 if (!has_min) {
525 has_min = target_config.getConfiguredGlobal("min-" + name);
526 new_min = false;
527 }
528 if (has_min) {
529 min_value = has_min->intValue();
530 }
531
532 uint32_t max_value = 0;
533 ConstElementPtr has_max = getConfiguredGlobal("max-" + name);
534 bool new_max = true;
535 if (!has_max) {
536 has_max = target_config.getConfiguredGlobal("max-" + name);
537 new_max = false;
538 }
539 if (has_max) {
540 max_value = has_max->intValue();
541 }
542
543 if (!has_value && !has_min && !has_max) {
544 return;
545 }
546 if (has_value) {
547 if (!has_min && !has_max) {
548 // default only.
549 return;
550 } else if (!has_min) {
551 // default and max.
552 min_value = value;
553 } else if (!has_max) {
554 // default and min.
555 max_value = value;
556 }
557 } else if (has_min) {
558 if (!has_max) {
559 // min only.
560 return;
561 } else {
562 // min and max.
563 isc_throw(BadValue, "have min-" << name << " and max-"
564 << name << " but no " << name << " (default)");
565 }
566 } else {
567 // max only.
568 return;
569 }
570
571 // Check that min <= max.
572 if (min_value > max_value) {
573 if (has_min && has_max) {
574 std::string from_min = (new_min ? "new" : "previous");
575 std::string from_max = (new_max ? "new" : "previous");
576 isc_throw(BadValue, "the value of " << from_min
577 << " min-" << name << " ("
578 << min_value << ") is not less than "
579 << from_max << " max-" << name
580 << " (" << max_value << ")");
581 } else if (has_min) {
582 // Only min and default so min > default.
583 std::string from_min = (new_min ? "new" : "previous");
584 std::string from_value = (new_value ? "new" : "previous");
585 isc_throw(BadValue, "the value of " << from_min
586 << " min-" << name << " ("
587 << min_value << ") is not less than " << from_value
588 << " (default) " << name
589 << " (" << value << ")");
590 } else {
591 // Only default and max so default > max.
592 std::string from_max = (new_max ? "new" : "previous");
593 std::string from_value = (new_value ? "new" : "previous");
594 isc_throw(BadValue, "the value of " << from_value
595 << " (default) " << name
596 << " (" << value << ") is not less than " << from_max
597 << " max-" << name << " (" << max_value << ")");
598 }
599 }
600
601 // Check that value is between min and max.
602 if ((value < min_value) || (value > max_value)) {
603 std::string from_value = (new_value ? "new" : "previous");
604 std::string from_min = (new_min ? "new" : "previous");
605 std::string from_max = (new_max ? "new" : "previous");
606 isc_throw(BadValue, "the value of " << from_value
607 <<" (default) " << name << " ("
608 << value << ") is not between " << from_min
609 << " min-" << name << " (" << min_value
610 << ") and " << from_max << " max-"
611 << name << " (" << max_value << ")");
612 }
613}
614
617 // Toplevel map
618 ElementPtr result = Element::createMap();
619
620 // Get family for the configuration manager
621 uint16_t family = CfgMgr::instance().getFamily();
622 // DhcpX global map
623 ElementPtr dhcp = ConfigBase::toElement();
624
625 // Add in explicitly configured globals.
626 dhcp->setValue(configured_globals_->mapValue());
627
628 // Set user-context
629 contextToElement(dhcp);
630
631 // Set data directory if DHCPv6 and specified.
632 if (family == AF_INET6) {
633 const util::Optional<std::string>& datadir =
635 if (!datadir.unspecified()) {
636 dhcp->set("data-directory", Element::create(datadir));
637 }
638 }
639
640 // Set decline-probation-period
641 dhcp->set("decline-probation-period",
642 Element::create(static_cast<long long>(decline_timer_)));
643 // Set echo-client-id (DHCPv4)
644 if (family == AF_INET) {
645 dhcp->set("echo-client-id", Element::create(echo_v4_client_id_));
646 }
647 // Set dhcp4o6-port
648 dhcp->set("dhcp4o6-port",
649 Element::create(static_cast<int>(dhcp4o6_port_)));
650 // Set dhcp-ddns
651 dhcp->set("dhcp-ddns", d2_client_config_->toElement());
652 // Set interfaces-config
653 dhcp->set("interfaces-config", cfg_iface_->toElement());
654 // Set option-def
655 dhcp->set("option-def", cfg_option_def_->toElement());
656 // Set option-data
657 dhcp->set("option-data", cfg_option_->toElement());
658
659 // Set subnets and shared networks.
660
661 // We have two problems to solve:
662 // - a subnet is unparsed once:
663 // * if it is a plain subnet in the global subnet list
664 // * if it is a member of a shared network in the shared network
665 // subnet list
666 // - unparsed subnets must be kept to add host reservations in them.
667 // Of course this can be done only when subnets are unparsed.
668
669 // The list of all unparsed subnets
670 std::vector<ElementPtr> sn_list;
671
672 if (family == AF_INET) {
673 // Get plain subnets
674 ElementPtr plain_subnets = Element::createList();
675 const Subnet4Collection* subnets = cfg_subnets4_->getAll();
676 for (Subnet4Collection::const_iterator subnet = subnets->cbegin();
677 subnet != subnets->cend(); ++subnet) {
678 // Skip subnets which are in a shared-network
679 SharedNetwork4Ptr network;
680 (*subnet)->getSharedNetwork(network);
681 if (network) {
682 continue;
683 }
684 ElementPtr subnet_cfg = (*subnet)->toElement();
685 sn_list.push_back(subnet_cfg);
686 plain_subnets->add(subnet_cfg);
687 }
688 dhcp->set("subnet4", plain_subnets);
689
690 // Get shared networks
691 ElementPtr shared_networks = cfg_shared_networks4_->toElement();
692 dhcp->set("shared-networks", shared_networks);
693
694 // Get subnets in shared network subnet lists
695 const std::vector<ElementPtr> networks = shared_networks->listValue();
696 for (auto network = networks.cbegin();
697 network != networks.cend(); ++network) {
698 const std::vector<ElementPtr> sh_list =
699 (*network)->get("subnet4")->listValue();
700 for (auto subnet = sh_list.cbegin();
701 subnet != sh_list.cend(); ++subnet) {
702 sn_list.push_back(*subnet);
703 }
704 }
705
706 } else {
707 // Get plain subnets
708 ElementPtr plain_subnets = Element::createList();
709 const Subnet6Collection* subnets = cfg_subnets6_->getAll();
710 for (Subnet6Collection::const_iterator subnet = subnets->cbegin();
711 subnet != subnets->cend(); ++subnet) {
712 // Skip subnets which are in a shared-network
713 SharedNetwork6Ptr network;
714 (*subnet)->getSharedNetwork(network);
715 if (network) {
716 continue;
717 }
718 ElementPtr subnet_cfg = (*subnet)->toElement();
719 sn_list.push_back(subnet_cfg);
720 plain_subnets->add(subnet_cfg);
721 }
722 dhcp->set("subnet6", plain_subnets);
723
724 // Get shared networks
725 ElementPtr shared_networks = cfg_shared_networks6_->toElement();
726 dhcp->set("shared-networks", shared_networks);
727
728 // Get subnets in shared network subnet lists
729 const std::vector<ElementPtr> networks = shared_networks->listValue();
730 for (auto network = networks.cbegin();
731 network != networks.cend(); ++network) {
732 const std::vector<ElementPtr> sh_list =
733 (*network)->get("subnet6")->listValue();
734 for (auto subnet = sh_list.cbegin();
735 subnet != sh_list.cend(); ++subnet) {
736 sn_list.push_back(*subnet);
737 }
738 }
739 }
740
741 // Host reservations
742 CfgHostsList resv_list;
743 resv_list.internalize(cfg_hosts_->toElement());
744
745 // Insert global reservations
746 ConstElementPtr global_resvs = resv_list.get(SUBNET_ID_GLOBAL);
747 if (global_resvs->size() > 0) {
748 dhcp->set("reservations", global_resvs);
749 }
750
751 // Insert subnet reservations
752 for (std::vector<ElementPtr>::const_iterator subnet = sn_list.cbegin();
753 subnet != sn_list.cend(); ++subnet) {
754 ConstElementPtr id = (*subnet)->get("id");
755 if (isNull(id)) {
756 isc_throw(ToElementError, "subnet has no id");
757 }
758 SubnetID subnet_id = id->intValue();
759 ConstElementPtr resvs = resv_list.get(subnet_id);
760 (*subnet)->set("reservations", resvs);
761 }
762
763 // Set expired-leases-processing
764 ConstElementPtr expired = cfg_expiration_->toElement();
765 dhcp->set("expired-leases-processing", expired);
766 if (family == AF_INET6) {
767 // Set server-id (DHCPv6)
768 dhcp->set("server-id", cfg_duid_->toElement());
769
770 // Set relay-supplied-options (DHCPv6)
771 dhcp->set("relay-supplied-options", cfg_rsoo_->toElement());
772 }
773 // Set lease-database
774 CfgLeaseDbAccess lease_db(*cfg_db_access_);
775 dhcp->set("lease-database", lease_db.toElement());
776 // Set hosts-databases
777 CfgHostDbAccess host_db(*cfg_db_access_);
778 ConstElementPtr hosts_databases = host_db.toElement();
779 if (hosts_databases->size() > 0) {
780 dhcp->set("hosts-databases", hosts_databases);
781 }
782 // Set host-reservation-identifiers
783 ConstElementPtr host_ids;
784 if (family == AF_INET) {
785 host_ids = cfg_host_operations4_->toElement();
786 } else {
787 host_ids = cfg_host_operations6_->toElement();
788 }
789 dhcp->set("host-reservation-identifiers", host_ids);
790 // Set mac-sources (DHCPv6)
791 if (family == AF_INET6) {
792 dhcp->set("mac-sources", cfg_mac_source_.toElement());
793 }
794 // Set control-socket (skip if null as empty is not legal)
795 if (!isNull(control_socket_)) {
796 dhcp->set("control-socket", UserContext::toElement(control_socket_));
797 }
798 // Set client-classes
799 ConstElementPtr client_classes = class_dictionary_->toElement();
801 if (!client_classes->empty()) {
802 dhcp->set("client-classes", client_classes);
803 }
804 // Set hooks-libraries
805 ConstElementPtr hooks_libs = hooks_config_.toElement();
806 dhcp->set("hooks-libraries", hooks_libs);
807 // Set DhcpX
808 result->set(family == AF_INET ? "Dhcp4" : "Dhcp6", dhcp);
809
810 ConstElementPtr cfg_consist = cfg_consist_->toElement();
811 dhcp->set("sanity-checks", cfg_consist);
812
813 // Set config-control (if it exists)
815 if (info) {
816 ConstElementPtr info_elem = info->toElement();
817 dhcp->set("config-control", info_elem);
818 }
819
820 // Set dhcp-packet-control (if it exists)
821 data::ConstElementPtr dhcp_queue_control = getDHCPQueueControl();
822 if (dhcp_queue_control) {
823 dhcp->set("dhcp-queue-control", dhcp_queue_control);
824 }
825
826 // Set multi-threading (if it exists)
827 data::ConstElementPtr dhcp_multi_threading = getDHCPMultiThreading();
828 if (dhcp_multi_threading) {
829 dhcp->set("multi-threading", dhcp_multi_threading);
830 }
831
832 return (result);
833}
834
837 return (DdnsParamsPtr(new DdnsParams(subnet,
838 getD2ClientConfig()->getEnableUpdates())));
839}
840
843 return(DdnsParamsPtr(new DdnsParams(subnet,
844 getD2ClientConfig()->getEnableUpdates())));
845}
846
847void
849 if (!srv_elem || (srv_elem->getType() != Element::map)) {
850 isc_throw(BadValue, "moveDdnsParams server config must be given a map element");
851 }
852
853 if (!srv_elem->contains("dhcp-ddns")) {
854 /* nothing to do */
855 return;
856 }
857
858 ElementPtr d2_elem = boost::const_pointer_cast<Element>(srv_elem->get("dhcp-ddns"));
859 if (!d2_elem || (d2_elem->getType() != Element::map)) {
860 isc_throw(BadValue, "moveDdnsParams dhcp-ddns is not a map");
861 }
862
863 struct Param {
864 std::string from_name;
865 std::string to_name;
866 };
867
868 std::vector<Param> params {
869 { "override-no-update", "ddns-override-no-update" },
870 { "override-client-update", "ddns-override-client-update" },
871 { "replace-client-name", "ddns-replace-client-name" },
872 { "generated-prefix", "ddns-generated-prefix" },
873 { "qualifying-suffix", "ddns-qualifying-suffix" },
874 { "hostname-char-set", "hostname-char-set" },
875 { "hostname-char-replacement", "hostname-char-replacement" }
876 };
877
878 for (auto param : params) {
879 if (d2_elem->contains(param.from_name)) {
880 if (!srv_elem->contains(param.to_name)) {
881 // No global value for it already, so let's add it.
882 srv_elem->set(param.to_name, d2_elem->get(param.from_name));
884 .arg(param.from_name).arg(param.to_name);
885 } else {
886 // Already a global value, we'll use it and ignore this one.
888 .arg(param.from_name).arg(param.to_name);
889 }
890
891 // Now remove it from d2_data, so D2ClientCfg won't complain.
892 d2_elem->remove(param.from_name);
893 }
894 }
895}
896
897void
899 if (!getCfgDbAccess()->getIPReservationsUnique() && unique) {
901 }
902 getCfgHosts()->setIPReservationsUnique(unique);
903 getCfgDbAccess()->setIPReservationsUnique(unique);
904}
905
906void
908 Option::lenient_parsing_ = lenient_option_parsing_;
909}
910
911bool
913 if (!subnet_) {
914 return (false);
915 }
916
917 return (d2_client_enabled_ && subnet_->getDdnsSendUpdates().get());
918}
919
920bool
922 if (!subnet_) {
923 return (false);
924 }
925
926 return (subnet_->getDdnsOverrideNoUpdate().get());
927}
928
930 if (!subnet_) {
931 return (false);
932 }
933
934 return (subnet_->getDdnsOverrideClientUpdate().get());
935}
936
939 if (!subnet_) {
941 }
942
943 return (subnet_->getDdnsReplaceClientNameMode().get());
944}
945
946std::string
948 if (!subnet_) {
949 return ("");
950 }
951
952 return (subnet_->getDdnsGeneratedPrefix().get());
953}
954
955std::string
957 if (!subnet_) {
958 return ("");
959 }
960
961 return (subnet_->getDdnsQualifyingSuffix().get());
962}
963
964std::string
966 if (!subnet_) {
967 return ("");
968 }
969
970 return (subnet_->getHostnameCharSet().get());
971}
972
973std::string
975 if (!subnet_) {
976 return ("");
977 }
978
979 return (subnet_->getHostnameCharReplacement().get());
980}
981
985 if (subnet_) {
986 std::string char_set = getHostnameCharSet();
987 if (!char_set.empty()) {
988 try {
989 sanitizer.reset(new util::str::StringSanitizer(char_set,
991 } catch (const std::exception& ex) {
992 isc_throw(BadValue, "hostname_char_set_: '" << char_set <<
993 "' is not a valid regular expression");
994 }
995 }
996 }
997
998 return (sanitizer);
999}
1000
1001bool
1003 if (!subnet_) {
1004 return (false);
1005 }
1006
1007 return (subnet_->getDdnsUpdateOnRenew().get());
1008}
1009
1010bool
1012 if (!subnet_) {
1013 return (true);
1014 }
1015
1016 return (subnet_->getDdnsUseConflictResolution().get());
1017}
1018
1019} // namespace dhcp
1020} // namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
A generic exception that is thrown if a function is called in a prohibited way.
Cannot unparse error.
The Element class represents a piece of data, used by the command channel and configuration parts.
Definition: data.h:70
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition: data.cc:286
Notes: IntElement type is changed to int64_t.
Definition: data.h:588
static void moveReservationMode(isc::data::ElementPtr config)
Moves deprecated reservation-mode parameter to new reservations flags.
Parameters for various consistency checks.
Holds manual configuration of the server identifier (DUID).
Definition: cfg_duid.h:30
Holds access parameters and the configuration of the lease and hosts database connection.
Definition: cfg_db_access.h:25
Holds configuration parameters pertaining to lease expiration and lease affinity.
Represents global configuration for host reservations.
Utility class to represent host reservation configurations internally as a map keyed by subnet IDs,...
isc::data::ConstElementPtr get(SubnetID id) const
Return the host reservations for a subnet ID.
void internalize(isc::data::ConstElementPtr list)
Internalize a list Element.
Represents the host reservations specified in the configuration file.
Definition: cfg_hosts.h:38
Represents selection of interfaces for DHCP server.
Definition: cfg_iface.h:130
virtual isc::data::ElementPtr toElement() const
Unparse a configuration object.
util::Optional< std::string > getDataDir() const
returns path do the data directory
Definition: cfgmgr.cc:31
uint16_t getFamily() const
Returns address family.
Definition: cfgmgr.h:280
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
Represents option definitions used by the DHCP server.
Represents option data configuration for the DHCP server.
Definition: cfg_option.h:314
Represents configuration of the RSOO options for the DHCP server.
Definition: cfg_rsoo.h:25
Represents configuration of IPv4 shared networks.
Represents configuration of IPv6 shared networks.
Holds subnets configured for the DHCPv4 server.
Definition: cfg_subnets4.h:33
Holds subnets configured for the DHCPv6 server.
Definition: cfg_subnets6.h:34
Maintains a list of ClientClassDef's.
Acts as a storage vault for D2 client configuration.
Definition: d2_client_cfg.h:56
ReplaceClientNameMode
Defines the client name replacement modes.
Definition: d2_client_cfg.h:75
Convenience container for conveying DDNS behavioral parameters It is intended to be created per Packe...
Definition: srv_config.h:46
std::string getHostnameCharReplacement() const
Returns the string to replace invalid characters when scrubbing hostnames.
Definition: srv_config.cc:974
bool getUseConflictResolution() const
Returns whether or not keah-dhcp-ddns should use conflict resolution.
Definition: srv_config.cc:1011
D2ClientConfig::ReplaceClientNameMode getReplaceClientNameMode() const
Returns how Kea should handle the domain-name supplied by the client.
Definition: srv_config.cc:938
std::string getGeneratedPrefix() const
Returns the Prefix Kea should use when generating domain-names.
Definition: srv_config.cc:947
isc::util::str::StringSanitizerPtr getHostnameSanitizer() const
Returns a regular expression string sanitizer.
Definition: srv_config.cc:983
std::string getHostnameCharSet() const
Returns the regular expression describing invalid characters for client hostnames.
Definition: srv_config.cc:965
std::string getQualifyingSuffix() const
Returns the suffix Kea should use when to qualify partial domain-names.
Definition: srv_config.cc:956
bool getUpdateOnRenew() const
Returns whether or not DNS should be updated when leases renew.
Definition: srv_config.cc:1002
bool getOverrideNoUpdate() const
Returns whether or not Kea should perform updates, even if client requested no updates.
Definition: srv_config.cc:921
bool getEnableUpdates() const
Returns whether or not DHCP DDNS updating is enabled.
Definition: srv_config.cc:912
bool getOverrideClientUpdate() const
Returns whether or not Kea should perform updates, even if client requested delegation.
Definition: srv_config.cc:929
static bool haveInstance()
Indicates if the lease manager has been instantiated.
static bool lenient_parsing_
Governs whether options should be parsed less strictly.
Definition: option.h:464
Specifies current DHCP configuration.
Definition: srv_config.h:167
ClientClassDictionaryPtr getClientClassDictionary()
Returns pointer to the dictionary of global client class definitions.
Definition: srv_config.h:512
static const uint32_t CFGSEL_SUBNET4
Number of IPv4 subnets.
Definition: srv_config.h:175
static void moveDdnsParams(isc::data::ElementPtr srv_elem)
Moves deprecated parameters from dhcp-ddns element to global element.
Definition: srv_config.cc:848
void setDhcp4o6Port(uint16_t port)
Sets DHCP4o6 IPC port.
Definition: srv_config.h:744
void addConfiguredGlobal(const std::string &name, isc::data::ConstElementPtr value)
Adds a parameter to the collection configured globals.
Definition: srv_config.h:800
isc::data::ConstElementPtr getConfiguredGlobals() const
Returns pointer to configured global parameters.
Definition: srv_config.h:773
void clearConfiguredGlobals()
Removes all configured global parameters.
Definition: srv_config.cc:336
void setClientClassDictionary(const ClientClassDictionaryPtr &dictionary)
Sets the client class dictionary.
Definition: srv_config.h:524
virtual void merge(ConfigBase &other)
Merges the configuration specified as a parameter into this configuration.
Definition: srv_config.cc:169
void extractConfiguredGlobals(isc::data::ConstElementPtr config)
Saves scalar elements from the global scope of a configuration.
Definition: srv_config.cc:412
isc::data::ConstElementPtr getConfiguredGlobal(std::string name) const
Returns pointer to a given configured global parameter.
Definition: srv_config.cc:326
CfgSharedNetworks6Ptr getCfgSharedNetworks6() const
Returns pointer to non-const object holding configuration of shared networks in DHCPv6.
Definition: srv_config.h:329
void setD2ClientConfig(const D2ClientConfigPtr &d2_client_config)
Sets the D2 client configuration.
Definition: srv_config.h:768
void applyDefaultsConfiguredGlobals(const isc::data::SimpleDefaults &defaults)
Applies defaults to global parameters.
Definition: srv_config.cc:341
void setIPReservationsUnique(const bool unique)
Configures the server to allow or disallow specifying multiple hosts with the same IP address/subnet.
Definition: srv_config.cc:898
void configureLowerLevelLibraries() const
Convenience method to propagate configuration parameters through inversion of control.
Definition: srv_config.cc:907
bool sequenceEquals(const SrvConfig &other)
Compares configuration sequence with other sequence.
Definition: srv_config.cc:115
CfgSubnets4Ptr getCfgSubnets4()
Returns pointer to non-const object holding subnets configuration for DHCPv4.
Definition: srv_config.h:311
CfgSubnets6Ptr getCfgSubnets6()
Returns pointer to non-const object holding subnets configuration for DHCPv6.
Definition: srv_config.h:345
CfgOptionDefPtr getCfgOptionDef()
Return pointer to non-const object representing user-defined option definitions.
Definition: srv_config.h:272
D2ClientConfigPtr getD2ClientConfig()
Returns pointer to the D2 client configuration.
Definition: srv_config.h:757
const isc::data::ConstElementPtr getDHCPMultiThreading() const
Returns DHCP multi threading information.
Definition: srv_config.h:500
void sanityChecksLifetime(const std::string &name) const
Conducts sanity checks on global lifetime parameters.
Definition: srv_config.cc:427
std::string getConfigSummary(const uint32_t selection) const
Returns summary of the configuration in the textual format.
Definition: srv_config.cc:74
const isc::data::ConstElementPtr getDHCPQueueControl() const
Returns DHCP queue control information.
Definition: srv_config.h:488
bool equals(const SrvConfig &other) const
Compares two objects for equality.
Definition: srv_config.cc:143
uint32_t getSequence() const
Returns configuration sequence number.
Definition: srv_config.h:229
static const uint32_t CFGSEL_DDNS
DDNS enabled/disabled.
Definition: srv_config.h:183
void setDeclinePeriod(const uint32_t decline_timer)
Sets decline probation-period.
Definition: srv_config.h:710
void removeStatistics()
Removes statistics.
Definition: srv_config.cc:280
CfgOptionPtr getCfgOption()
Returns pointer to the non-const object holding options.
Definition: srv_config.h:293
virtual isc::data::ElementPtr toElement() const
Unparse a configuration object.
Definition: srv_config.cc:616
static const uint32_t CFGSEL_SUBNET6
Number of IPv6 subnets.
Definition: srv_config.h:177
void updateStatistics()
Updates statistics.
Definition: srv_config.cc:288
CfgDbAccessPtr getCfgDbAccess()
Returns pointer to the object holding configuration of the lease and host database connection paramet...
Definition: srv_config.h:417
void setEchoClientId(const bool echo)
Sets whether server should send back client-id in DHCPv4.
Definition: srv_config.h:728
void copy(SrvConfig &new_config) const
Copies the current configuration to a new configuration.
Definition: srv_config.cc:120
CfgSharedNetworks4Ptr getCfgSharedNetworks4() const
Returns pointer to non-const object holding configuration of shared networks in DHCPv4;.
Definition: srv_config.h:320
CfgHostsPtr getCfgHosts()
Returns pointer to the non-const objects representing host reservations for different IPv4 and IPv6 s...
Definition: srv_config.h:361
DdnsParamsPtr getDdnsParams(const Subnet4Ptr &subnet) const
Fetches the DDNS parameters for a given DHCPv4 subnet.
Definition: srv_config.cc:836
SrvConfig()
Default constructor.
Definition: srv_config.cc:35
void clear()
Removes all configured hooks libraries.
Definition: hooks_config.h:59
bool equal(const HooksConfig &other) const
Compares two Hooks Config classes for equality.
Definition: hooks_config.cc:67
const isc::hooks::HookLibsCollection & get() const
Provides access to the configured hooks libraries.
Definition: hooks_config.h:54
isc::data::ElementPtr toElement() const
Unparse a configuration object.
void add(std::string libname, isc::data::ConstElementPtr parameters)
Adds additional hooks libraries.
Definition: hooks_config.h:46
Base class for all configurations.
Definition: config_base.h:33
process::ConstConfigControlInfoPtr getConfigControlInfo() const
Fetches a read-only copy of the configuration control information.
Definition: config_base.h:106
void setServerTag(const util::Optional< std::string > &server_tag)
Sets the server's logical name.
Definition: config_base.h:127
Statistics Manager class.
static StatsMgr & instance()
Statistics Manager accessor method.
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
Definition: optional.h:121
Implements a regular expression based string scrubber.
Definition: strutil.h:303
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
void setMaxSampleCountDefault(uint32_t max_samples)
Set default count limit.
void setMaxSampleAgeAll(const StatsDuration &duration)
Set duration limit for all collected statistics.
void setMaxSampleCountAll(uint32_t max_samples)
Set count limit for all collected statistics.
void setMaxSampleAgeDefault(const StatsDuration &duration)
Set default duration limit.
#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
ElementPtr copy(ConstElementPtr from, int level)
Copy the data up to a nesting level.
Definition: data.cc:1152
void merge(ElementPtr element, ConstElementPtr other)
Merges the data from other into element.
Definition: data.cc:1134
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
bool isNull(ConstElementPtr p)
Checks whether the given ElementPtr is a NULL pointer.
Definition: data.cc:1083
std::vector< SimpleDefault > SimpleDefaults
This specifies all default values in a given scope (e.g. a subnet).
boost::shared_ptr< Element > ElementPtr
Definition: data.h:24
@ info
Definition: db_log.h:120
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
boost::shared_ptr< Subnet4 > Subnet4Ptr
A pointer to a Subnet4 object.
Definition: subnet.h:522
const isc::log::MessageID DHCPSRV_CFGMGR_DDNS_PARAMETER_IGNORED
const isc::log::MessageID DHCPSRV_CFGMGR_DDNS_PARAMETER_MOVED
boost::shared_ptr< Subnet6 > Subnet6Ptr
A pointer to a Subnet6 object.
Definition: subnet.h:670
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:914
boost::shared_ptr< DdnsParams > DdnsParamsPtr
Defines a pointer for DdnsParams instances.
Definition: srv_config.h:162
boost::shared_ptr< SharedNetwork6 > SharedNetwork6Ptr
Pointer to SharedNetwork6 object.
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:867
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
Definition: lease.h:24
const isc::log::MessageID DHCPSRV_CFGMGR_IP_RESERVATIONS_UNIQUE_DUPLICATES_POSSIBLE
boost::shared_ptr< SharedNetwork4 > SharedNetwork4Ptr
Pointer to SharedNetwork4 object.
boost::shared_ptr< const ConfigControlInfo > ConstConfigControlInfoPtr
Defines a pointer to a const ConfigControlInfo.
boost::shared_ptr< StringSanitizer > StringSanitizerPtr
Definition: strutil.h:348
Defines the logger used by the top-level component of kea-lfc.
Represents the position of the data element within a configuration string.
Definition: data.h:92
void contextToElement(data::ElementPtr map) const
Merge unparse a user_context object.
Definition: user_context.cc:15
virtual isc::data::ElementPtr toElement() const
Unparse.
utility class for unparsing
virtual isc::data::ElementPtr toElement() const
Unparse.