Kea 2.0.0
dhcp4/json_config_parser.cc
Go to the documentation of this file.
1// Copyright (C) 2012-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>
8
13#include <dhcp4/dhcp4_log.h>
14#include <dhcp4/dhcp4_srv.h>
16#include <dhcp/libdhcp++.h>
19#include <dhcpsrv/cfg_option.h>
20#include <dhcpsrv/cfgmgr.h>
22#include <dhcpsrv/db_type.h>
36#include <dhcpsrv/timer_mgr.h>
38#include <hooks/hooks_manager.h>
39#include <hooks/hooks_parser.h>
40#include <config/command_mgr.h>
41#include <util/encode/hex.h>
42#include <util/strutil.h>
43
44#include <boost/foreach.hpp>
45#include <boost/lexical_cast.hpp>
46#include <boost/algorithm/string.hpp>
47
48#include <limits>
49#include <iostream>
50#include <iomanip>
51#include <netinet/in.h>
52#include <vector>
53#include <map>
54
55using namespace std;
56using namespace isc;
57using namespace isc::dhcp;
58using namespace isc::data;
59using namespace isc::asiolink;
60using namespace isc::hooks;
61using namespace isc::process;
62using namespace isc::config;
63
64namespace {
65
74class Dhcp4ConfigParser : public isc::data::SimpleParser {
75public:
76
91 void parse(const SrvConfigPtr& cfg, const ConstElementPtr& global) {
92
93 // Set whether v4 server is supposed to echo back client-id
94 // (yes = RFC6842 compatible, no = backward compatibility)
95 bool echo_client_id = getBoolean(global, "echo-client-id");
96 cfg->setEchoClientId(echo_client_id);
97
98 // Set the probation period for decline handling.
99 uint32_t probation_period =
100 getUint32(global, "decline-probation-period");
101 cfg->setDeclinePeriod(probation_period);
102
103 // Set the DHCPv4-over-DHCPv6 interserver port.
104 uint16_t dhcp4o6_port = getUint16(global, "dhcp4o6-port");
105 cfg->setDhcp4o6Port(dhcp4o6_port);
106
107 // Set the global user context.
108 ConstElementPtr user_context = global->get("user-context");
109 if (user_context) {
110 cfg->setContext(user_context);
111 }
112
113 // Set the server's logical name
114 std::string server_tag = getString(global, "server-tag");
115 cfg->setServerTag(server_tag);
116 }
117
129 void parseEarly(const SrvConfigPtr& cfg, const ConstElementPtr& global) {
130 // Set ip-reservations-unique flag.
131 bool ip_reservations_unique = getBoolean(global, "ip-reservations-unique");
132 cfg->setIPReservationsUnique(ip_reservations_unique);
133 }
134
141 void
142 copySubnets4(const CfgSubnets4Ptr& dest, const CfgSharedNetworks4Ptr& from) {
143
144 if (!dest || !from) {
145 isc_throw(BadValue, "Unable to copy subnets: at least one pointer is null");
146 }
147
148 const SharedNetwork4Collection* networks = from->getAll();
149 if (!networks) {
150 // Nothing to copy. Technically, it should return a pointer to empty
151 // container, but let's handle null pointer as well.
152 return;
153 }
154
155 // Let's go through all the networks one by one
156 for (auto net = networks->begin(); net != networks->end(); ++net) {
157
158 // For each network go through all the subnets in it.
159 const Subnet4Collection* subnets = (*net)->getAllSubnets();
160 if (!subnets) {
161 // Shared network without subnets it weird, but we decided to
162 // accept such configurations.
163 continue;
164 }
165
166 // For each subnet, add it to a list of regular subnets.
167 for (auto subnet = subnets->begin(); subnet != subnets->end(); ++subnet) {
168 dest->add(*subnet);
169 }
170 }
171 }
172
181 void
182 sanityChecks(const SrvConfigPtr& cfg, const ConstElementPtr& global) {
183
185 cfg->sanityChecksLifetime("valid-lifetime");
186
188 const SharedNetwork4Collection* networks = cfg->getCfgSharedNetworks4()->getAll();
189 if (networks) {
190 sharedNetworksSanityChecks(*networks, global->get("shared-networks"));
191 }
192 }
193
200 void
201 sharedNetworksSanityChecks(const SharedNetwork4Collection& networks,
202 ConstElementPtr json) {
203
205 if (!json) {
206 // No json? That means that the shared-networks was never specified
207 // in the config.
208 return;
209 }
210
211 // Used for names uniqueness checks.
212 std::set<string> names;
213
214 // Let's go through all the networks one by one
215 for (auto net = networks.begin(); net != networks.end(); ++net) {
216 string txt;
217
218 // Let's check if all subnets have either the same interface
219 // or don't have the interface specified at all.
220 bool authoritative = (*net)->getAuthoritative();
221 string iface = (*net)->getIface();
222
223 const Subnet4Collection* subnets = (*net)->getAllSubnets();
224 if (subnets) {
225 // For each subnet, add it to a list of regular subnets.
226 for (auto subnet = subnets->begin(); subnet != subnets->end(); ++subnet) {
227 if ((*subnet)->getAuthoritative() != authoritative) {
228 isc_throw(DhcpConfigError, "Subnet " << boolalpha
229 << (*subnet)->toText()
230 << " has different authoritative setting "
231 << (*subnet)->getAuthoritative()
232 << " than the shared-network itself: "
233 << authoritative);
234 }
235
236 if (iface.empty()) {
237 iface = (*subnet)->getIface();
238 continue;
239 }
240
241 if ((*subnet)->getIface().empty()) {
242 continue;
243 }
244
245 if ((*subnet)->getIface() != iface) {
246 isc_throw(DhcpConfigError, "Subnet " << (*subnet)->toText()
247 << " has specified interface " << (*subnet)->getIface()
248 << ", but earlier subnet in the same shared-network"
249 << " or the shared-network itself used " << iface);
250 }
251
252 // Let's collect the subnets in case we later find out the
253 // subnet doesn't have a mandatory name.
254 txt += (*subnet)->toText() + " ";
255 }
256 }
257
258 // Next, let's check name of the shared network.
259 if ((*net)->getName().empty()) {
260 isc_throw(DhcpConfigError, "Shared-network with subnets "
261 << txt << " is missing mandatory 'name' parameter");
262 }
263
264 // Is it unique?
265 if (names.find((*net)->getName()) != names.end()) {
266 isc_throw(DhcpConfigError, "A shared-network with "
267 "name " << (*net)->getName() << " defined twice.");
268 }
269 names.insert((*net)->getName());
270
271 }
272 }
273};
274
275} // anonymous namespace
276
277namespace isc {
278namespace dhcp {
279
288 // Get new socket configuration.
289 ConstElementPtr sock_cfg =
290 CfgMgr::instance().getStagingCfg()->getControlSocketInfo();
291
292 // Get current socket configuration.
293 ConstElementPtr current_sock_cfg =
294 CfgMgr::instance().getCurrentCfg()->getControlSocketInfo();
295
296 // Determine if the socket configuration has changed. It has if
297 // both old and new configuration is specified but respective
298 // data elements aren't equal.
299 bool sock_changed = (sock_cfg && current_sock_cfg &&
300 !sock_cfg->equals(*current_sock_cfg));
301
302 // If the previous or new socket configuration doesn't exist or
303 // the new configuration differs from the old configuration we
304 // close the existing socket and open a new socket as appropriate.
305 // Note that closing an existing socket means the client will not
306 // receive the configuration result.
307 if (!sock_cfg || !current_sock_cfg || sock_changed) {
308 // Close the existing socket (if any).
310
311 if (sock_cfg) {
312 // This will create a control socket and install the external
313 // socket in IfaceMgr. That socket will be monitored when
314 // Dhcp4Srv::receivePacket() calls IfaceMgr::receive4() and
315 // callback in CommandMgr will be called, if necessary.
317 }
318 }
319}
320
323 bool check_only) {
324 if (!config_set) {
326 string("Can't parse NULL config"));
327 return (answer);
328 }
329
331 .arg(server.redactConfig(config_set)->str());
332
333 // Before starting any subnet operations, let's reset the subnet-id counter,
334 // so newly recreated configuration starts with first subnet-id equal 1.
336
337 // Close DHCP sockets and remove any existing timers.
338 if (!check_only) {
340 TimerMgr::instance()->unregisterTimers();
341 server.discardPackets();
342 server.getCBControl()->reset();
343 }
344
345 // Revert any runtime option definitions configured so far and not committed.
347 // Let's set empty container in case a user hasn't specified any configuration
348 // for option definitions. This is equivalent to committing empty container.
350
351 // Print the list of known backends.
353
354 // Answer will hold the result.
355 ConstElementPtr answer;
356 // Rollback informs whether error occurred and original data
357 // have to be restored to global storages.
358 bool rollback = false;
359 // Global parameter name in case of an error.
360 string parameter_name;
361 ElementPtr mutable_cfg;
362 SrvConfigPtr srv_cfg;
363 try {
364 // Get the staging configuration
365 srv_cfg = CfgMgr::instance().getStagingCfg();
366
367 // This is a way to convert ConstElementPtr to ElementPtr.
368 // We need a config that can be edited, because we will insert
369 // default values and will insert derived values as well.
370 mutable_cfg = boost::const_pointer_cast<Element>(config_set);
371
372 // Relocate dhcp-ddns parameters that have moved to global scope.
373 // Rule is that a global value overrides the dhcp-ddns value, so
374 // we need to do this before we apply global defaults.
375 // Note this is done for backward compatibility.
376 srv_cfg->moveDdnsParams(mutable_cfg);
377
378 // Move from reservation mode to new reservations flags.
379 // @todo add warning
381
382 // Set all default values if not specified by the user.
384
385 // And now derive (inherit) global parameters to subnets, if not specified.
387
388 // In principle we could have the following code structured as a series
389 // of long if else if clauses. That would give a marginal performance
390 // boost, but would make the code less readable. We had serious issues
391 // with the parser code debugability, so I decided to keep it as a
392 // series of independent ifs.
393
394 // This parser is used in several places.
395 Dhcp4ConfigParser global_parser;
396
397 // Apply global options in the staging config, e.g. ip-reservations-unique
398 global_parser.parseEarly(srv_cfg, mutable_cfg);
399
400 // We need definitions first
401 ConstElementPtr option_defs = mutable_cfg->get("option-def");
402 if (option_defs) {
403 parameter_name = "option-def";
404 OptionDefListParser parser(AF_INET);
405 CfgOptionDefPtr cfg_option_def = srv_cfg->getCfgOptionDef();
406 parser.parse(cfg_option_def, option_defs);
407 }
408
409 ConstElementPtr option_datas = mutable_cfg->get("option-data");
410 if (option_datas) {
411 parameter_name = "option-data";
412 OptionDataListParser parser(AF_INET);
413 CfgOptionPtr cfg_option = srv_cfg->getCfgOption();
414 parser.parse(cfg_option, option_datas);
415 }
416
417 ConstElementPtr control_socket = mutable_cfg->get("control-socket");
418 if (control_socket) {
419 parameter_name = "control-socket";
420 ControlSocketParser parser;
421 parser.parse(*srv_cfg, control_socket);
422 }
423
424 ConstElementPtr multi_threading = mutable_cfg->get("multi-threading");
425 if (multi_threading) {
426 parameter_name = "multi-threading";
428 parser.parse(*srv_cfg, multi_threading);
429 }
430
431 ConstElementPtr queue_control = mutable_cfg->get("dhcp-queue-control");
432 if (queue_control) {
433 parameter_name = "dhcp-queue-control";
435 srv_cfg->setDHCPQueueControl(parser.parse(queue_control));
436 }
437
438 ConstElementPtr hr_identifiers =
439 mutable_cfg->get("host-reservation-identifiers");
440 if (hr_identifiers) {
441 parameter_name = "host-reservation-identifiers";
443 parser.parse(hr_identifiers);
444 }
445
446 ConstElementPtr ifaces_config = mutable_cfg->get("interfaces-config");
447 if (ifaces_config) {
448 parameter_name = "interfaces-config";
449 IfacesConfigParser parser(AF_INET, check_only);
450 CfgIfacePtr cfg_iface = srv_cfg->getCfgIface();
451 parser.parse(cfg_iface, ifaces_config);
452 }
453
454 ConstElementPtr sanity_checks = mutable_cfg->get("sanity-checks");
455 if (sanity_checks) {
456 parameter_name = "sanity-checks";
457 SanityChecksParser parser;
458 parser.parse(*srv_cfg, sanity_checks);
459 }
460
461 ConstElementPtr expiration_cfg =
462 mutable_cfg->get("expired-leases-processing");
463 if (expiration_cfg) {
464 parameter_name = "expired-leases-processing";
466 parser.parse(expiration_cfg);
467 }
468
469 // The hooks-libraries configuration must be parsed after parsing
470 // multi-threading configuration so that libraries are checked
471 // for multi-threading compatibility.
472 ConstElementPtr hooks_libraries = mutable_cfg->get("hooks-libraries");
473 if (hooks_libraries) {
474 parameter_name = "hooks-libraries";
475 HooksLibrariesParser hooks_parser;
476 HooksConfig& libraries = srv_cfg->getHooksConfig();
477 hooks_parser.parse(libraries, hooks_libraries);
478 libraries.verifyLibraries(hooks_libraries->getPosition());
479 }
480
481 // D2 client configuration.
482 D2ClientConfigPtr d2_client_cfg;
483
484 // Legacy DhcpConfigParser stuff below.
485 ConstElementPtr dhcp_ddns = mutable_cfg->get("dhcp-ddns");
486 if (dhcp_ddns) {
487 parameter_name = "dhcp-ddns";
488 // Apply defaults
491 d2_client_cfg = parser.parse(dhcp_ddns);
492 }
493
494 ConstElementPtr client_classes = mutable_cfg->get("client-classes");
495 if (client_classes) {
496 parameter_name = "client-classes";
498 ClientClassDictionaryPtr dictionary =
499 parser.parse(client_classes, AF_INET);
500 srv_cfg->setClientClassDictionary(dictionary);
501 }
502
503 // Please move at the end when migration will be finished.
504 ConstElementPtr lease_database = mutable_cfg->get("lease-database");
505 if (lease_database) {
506 parameter_name = "lease-database";
507 db::DbAccessParser parser;
508 std::string access_string;
509 parser.parse(access_string, lease_database);
510 CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
511 cfg_db_access->setLeaseDbAccessString(access_string);
512 }
513
514 ConstElementPtr hosts_database = mutable_cfg->get("hosts-database");
515 if (hosts_database) {
516 parameter_name = "hosts-database";
517 db::DbAccessParser parser;
518 std::string access_string;
519 parser.parse(access_string, hosts_database);
520 CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
521 cfg_db_access->setHostDbAccessString(access_string);
522 }
523
524 ConstElementPtr hosts_databases = mutable_cfg->get("hosts-databases");
525 if (hosts_databases) {
526 parameter_name = "hosts-databases";
527 CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
528 db::DbAccessParser parser;
529 for (auto it : hosts_databases->listValue()) {
530 std::string access_string;
531 parser.parse(access_string, it);
532 cfg_db_access->setHostDbAccessString(access_string);
533 }
534 }
535
536 // Keep relative orders of shared networks and subnets.
537 ConstElementPtr shared_networks = mutable_cfg->get("shared-networks");
538 if (shared_networks) {
539 parameter_name = "shared-networks";
546 CfgSharedNetworks4Ptr cfg = srv_cfg->getCfgSharedNetworks4();
547 parser.parse(cfg, shared_networks);
548
549 // We also need to put the subnets it contains into normal
550 // subnets list.
551 global_parser.copySubnets4(srv_cfg->getCfgSubnets4(), cfg);
552 }
553
554 ConstElementPtr subnet4 = mutable_cfg->get("subnet4");
555 if (subnet4) {
556 parameter_name = "subnet4";
557 Subnets4ListConfigParser subnets_parser;
558 // parse() returns number of subnets parsed. We may log it one day.
559 subnets_parser.parse(srv_cfg, subnet4);
560 }
561
562 ConstElementPtr reservations = mutable_cfg->get("reservations");
563 if (reservations) {
564 parameter_name = "reservations";
565 HostCollection hosts;
567 parser.parse(SUBNET_ID_GLOBAL, reservations, hosts);
568 for (auto h = hosts.begin(); h != hosts.end(); ++h) {
569 srv_cfg->getCfgHosts()->add(*h);
570 }
571 }
572
573 ConstElementPtr config_control = mutable_cfg->get("config-control");
574 if (config_control) {
575 parameter_name = "config-control";
576 ConfigControlParser parser;
577 ConfigControlInfoPtr config_ctl_info = parser.parse(config_control);
578 CfgMgr::instance().getStagingCfg()->setConfigControlInfo(config_ctl_info);
579 }
580
581 ConstElementPtr compatibility = mutable_cfg->get("compatibility");
582 if (compatibility) {
583 for (auto kv : compatibility->mapValue()) {
584 if (kv.first == "lenient-option-parsing") {
585 CfgMgr::instance().getStagingCfg()->setLenientOptionParsing(
586 kv.second->boolValue());
587 }
588 }
589 }
590
591 // Make parsers grouping.
592 ConfigPair config_pair;
593 const std::map<std::string, ConstElementPtr>& values_map =
594 mutable_cfg->mapValue();
595
596 BOOST_FOREACH(config_pair, values_map) {
597
598 parameter_name = config_pair.first;
599
600 // These are converted to SimpleParser and are handled already above.
601 if ((config_pair.first == "option-def") ||
602 (config_pair.first == "option-data") ||
603 (config_pair.first == "control-socket") ||
604 (config_pair.first == "multi-threading") ||
605 (config_pair.first == "dhcp-queue-control") ||
606 (config_pair.first == "host-reservation-identifiers") ||
607 (config_pair.first == "interfaces-config") ||
608 (config_pair.first == "sanity-checks") ||
609 (config_pair.first == "expired-leases-processing") ||
610 (config_pair.first == "hooks-libraries") ||
611 (config_pair.first == "dhcp-ddns") ||
612 (config_pair.first == "client-classes") ||
613 (config_pair.first == "lease-database") ||
614 (config_pair.first == "hosts-database") ||
615 (config_pair.first == "hosts-databases") ||
616 (config_pair.first == "subnet4") ||
617 (config_pair.first == "shared-networks") ||
618 (config_pair.first == "reservations") ||
619 (config_pair.first == "config-control") ||
620 (config_pair.first == "compatibility")) {
621 continue;
622 }
623
624 // As of Kea 1.6.0 we have two ways of inheriting the global parameters.
625 // The old method is used in JSON configuration parsers when the global
626 // parameters are derived into the subnets and shared networks and are
627 // being treated as explicitly specified. The new way used by the config
628 // backend is the dynamic inheritance whereby each subnet and shared
629 // network uses a callback function to return global parameter if it
630 // is not specified at lower level. This callback uses configured globals.
631 // We deliberately include both default and explicitly specified globals
632 // so as the callback can access the appropriate global values regardless
633 // whether they are set to a default or other value.
634 if ( (config_pair.first == "renew-timer") ||
635 (config_pair.first == "rebind-timer") ||
636 (config_pair.first == "valid-lifetime") ||
637 (config_pair.first == "min-valid-lifetime") ||
638 (config_pair.first == "max-valid-lifetime") ||
639 (config_pair.first == "decline-probation-period") ||
640 (config_pair.first == "dhcp4o6-port") ||
641 (config_pair.first == "echo-client-id") ||
642 (config_pair.first == "match-client-id") ||
643 (config_pair.first == "authoritative") ||
644 (config_pair.first == "next-server") ||
645 (config_pair.first == "server-hostname") ||
646 (config_pair.first == "boot-file-name") ||
647 (config_pair.first == "server-tag") ||
648 (config_pair.first == "reservation-mode") ||
649 (config_pair.first == "reservations-global") ||
650 (config_pair.first == "reservations-in-subnet") ||
651 (config_pair.first == "reservations-out-of-pool") ||
652 (config_pair.first == "calculate-tee-times") ||
653 (config_pair.first == "t1-percent") ||
654 (config_pair.first == "t2-percent") ||
655 (config_pair.first == "cache-threshold") ||
656 (config_pair.first == "cache-max-age") ||
657 (config_pair.first == "loggers") ||
658 (config_pair.first == "hostname-char-set") ||
659 (config_pair.first == "hostname-char-replacement") ||
660 (config_pair.first == "ddns-send-updates") ||
661 (config_pair.first == "ddns-override-no-update") ||
662 (config_pair.first == "ddns-override-client-update") ||
663 (config_pair.first == "ddns-replace-client-name") ||
664 (config_pair.first == "ddns-generated-prefix") ||
665 (config_pair.first == "ddns-qualifying-suffix") ||
666 (config_pair.first == "ddns-update-on-renew") ||
667 (config_pair.first == "ddns-use-conflict-resolution") ||
668 (config_pair.first == "store-extended-info") ||
669 (config_pair.first == "statistic-default-sample-count") ||
670 (config_pair.first == "statistic-default-sample-age") ||
671 (config_pair.first == "ip-reservations-unique") ||
672 (config_pair.first == "parked-packet-limit")) {
673 CfgMgr::instance().getStagingCfg()->addConfiguredGlobal(config_pair.first,
674 config_pair.second);
675 continue;
676 }
677
678 // Nothing to configure for the user-context.
679 if (config_pair.first == "user-context") {
680 continue;
681 }
682
683 // If we got here, no code handled this parameter, so we bail out.
685 "unsupported global configuration parameter: " << config_pair.first
686 << " (" << config_pair.second->getPosition() << ")");
687 }
688
689 // Reset parameter name.
690 parameter_name = "<post parsing>";
691
692 // Apply global options in the staging config.
693 global_parser.parse(srv_cfg, mutable_cfg);
694
695 // This method conducts final sanity checks and tweaks. In particular,
696 // it checks that there is no conflict between plain subnets and those
697 // defined as part of shared networks.
698 global_parser.sanityChecks(srv_cfg, mutable_cfg);
699
700 // Validate D2 client configuration.
701 if (!d2_client_cfg) {
702 d2_client_cfg.reset(new D2ClientConfig());
703 }
704 d2_client_cfg->validateContents();
705 srv_cfg->setD2ClientConfig(d2_client_cfg);
706 } catch (const isc::Exception& ex) {
708 .arg(parameter_name).arg(ex.what());
710
711 // An error occurred, so make sure that we restore original data.
712 rollback = true;
713 } catch (...) {
714 // For things like bad_cast in boost::lexical_cast
715 LOG_ERROR(dhcp4_logger, DHCP4_PARSER_EXCEPTION).arg(parameter_name);
716 answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
717 " processing error");
718
719 // An error occurred, so make sure that we restore original data.
720 rollback = true;
721 }
722
723 if (check_only) {
724 rollback = true;
725 if (!answer) {
727 "Configuration seems sane. Control-socket, hook-libraries, and D2 "
728 "configuration were sanity checked, but not applied.");
729 }
730 }
731
732 // So far so good, there was no parsing error so let's commit the
733 // configuration. This will add created subnets and option values into
734 // the server's configuration.
735 // This operation should be exception safe but let's make sure.
736 if (!rollback) {
737 try {
738
739 // Setup the command channel.
741
742 // No need to commit interface names as this is handled by the
743 // CfgMgr::commit() function.
744
745 // Apply the staged D2ClientConfig, used to be done by parser commit
747 cfg = CfgMgr::instance().getStagingCfg()->getD2ClientConfig();
749
750 // This occurs last as if it succeeds, there is no easy way to
751 // revert it. As a result, the failure to commit a subsequent
752 // change causes problems when trying to roll back.
753 HooksManager::prepareUnloadLibraries();
754 static_cast<void>(HooksManager::unloadLibraries());
755 const HooksConfig& libraries =
756 CfgMgr::instance().getStagingCfg()->getHooksConfig();
757 libraries.loadLibraries();
758 }
759 catch (const isc::Exception& ex) {
762
763 // An error occurred, so make sure to restore the original data.
764 rollback = true;
765 } catch (...) {
766 // For things like bad_cast in boost::lexical_cast
768 answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
769 " parsing error");
770
771 // An error occurred, so make sure to restore the original data.
772 rollback = true;
773 }
774 }
775
776 // Moved from the commit block to add the config backend indication.
777 if (!rollback) {
778 try {
779
780 // If there are config backends, fetch and merge into staging config
781 server.getCBControl()->databaseConfigFetch(srv_cfg,
783 }
784 catch (const isc::Exception& ex) {
785 std::ostringstream err;
786 err << "during update from config backend database: " << ex.what();
789
790 // An error occurred, so make sure to restore the original data.
791 rollback = true;
792 } catch (...) {
793 // For things like bad_cast in boost::lexical_cast
794 std::ostringstream err;
795 err << "during update from config backend database: "
796 << "undefined configuration parsing error";
799
800 // An error occurred, so make sure to restore the original data.
801 rollback = true;
802 }
803 }
804
805 // Rollback changes as the configuration parsing failed.
806 if (rollback) {
807 // Revert to original configuration of runtime option definitions
808 // in the libdhcp++.
810 return (answer);
811 }
812
814 .arg(CfgMgr::instance().getStagingCfg()->
815 getConfigSummary(SrvConfig::CFGSEL_ALL4));
816
817 // Everything was fine. Configuration is successful.
818 answer = isc::config::createAnswer(CONTROL_RESULT_SUCCESS, "Configuration successful.");
819 return (answer);
820}
821
822} // namespace dhcp
823} // namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
void closeCommandSocket()
Shuts down any open control sockets.
Definition: command_mgr.cc:628
static CommandMgr & instance()
CommandMgr is a singleton class.
Definition: command_mgr.cc:651
void openCommandSocket(const isc::data::ConstElementPtr &socket_info)
Opens control socket with parameters specified in socket_info.
Definition: command_mgr.cc:624
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.
static bool getBoolean(isc::data::ConstElementPtr scope, const std::string &name)
Returns a boolean parameter from a scope.
uint16_t getUint16(isc::data::ConstElementPtr scope, const std::string &name)
Returns a value converted to uint16_t.
Parse Database Parameters.
void parse(std::string &access_string, isc::data::ConstElementPtr database_config)
Parse configuration value.
static void moveReservationMode(isc::data::ElementPtr config)
Moves deprecated reservation-mode parameter to new reservations flags.
void setD2ClientConfig(D2ClientConfigPtr &new_config)
Updates the DHCP-DDNS client configuration to the given value.
Definition: cfgmgr.cc:41
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition: cfgmgr.cc:167
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition: cfgmgr.cc:161
Parser for a list of client class definitions.
ClientClassDictionaryPtr parse(isc::data::ConstElementPtr class_def_list, uint16_t family, bool check_dependencies=true)
Parse configuration entries.
Parser for the control-socket structure.
Definition: dhcp_parsers.h:211
void parse(SrvConfig &srv_cfg, isc::data::ConstElementPtr value)
"Parses" control-socket structure
Definition: dhcp_parsers.cc:77
Parser for D2ClientConfig.
Definition: dhcp_parsers.h:981
D2ClientConfigPtr parse(isc::data::ConstElementPtr d2_client_cfg)
Parses a given dhcp-ddns element into D2ClientConfig.
static size_t setAllDefaults(isc::data::ConstElementPtr d2_config)
Sets all defaults for D2 client configuration.
Acts as a storage vault for D2 client configuration.
Definition: d2_client_cfg.h:56
Parser for the configuration of DHCP packet queue controls.
data::ElementPtr parse(const isc::data::ConstElementPtr &control_elem)
Parses content of the "dhcp-queue-control".
To be removed. Please use ConfigError instead.
DHCPv4 server service.
Definition: dhcp4_srv.h:241
CBControlDHCPv4Ptr getCBControl() const
Returns an object which controls access to the configuration backends.
Definition: dhcp4_srv.h:306
void discardPackets()
Discards parked packets Clears the packet parking lots of all packets.
Definition: dhcp4_srv.cc:4118
Parser for the configuration parameters pertaining to the processing of expired leases.
void parse(isc::data::ConstElementPtr expiration_config)
Parses parameters in the JSON map, pertaining to the processing of the expired leases.
static void printRegistered()
Prints out all registered backends.
Parser for a list of host identifiers for DHCPv4.
void parse(isc::data::ConstElementPtr ids_list)
Parses a list of host identifiers.
Parser for a list of host reservations for a subnet.
void parse(const SubnetID &subnet_id, isc::data::ConstElementPtr hr_list, HostCollection &hosts_list)
Parses a list of host reservation entries for a subnet.
static IfaceMgr & instance()
IfaceMgr is a singleton class.
Definition: iface_mgr.cc:53
void closeSockets()
Closes all open sockets.
Definition: iface_mgr.cc:286
Parser for the configuration of interfaces.
void parse(const CfgIfacePtr &config, const isc::data::ConstElementPtr &values)
Parses content of the "interfaces-config".
static void setRuntimeOptionDefs(const OptionDefSpaceContainer &defs)
Copies option definitions created at runtime.
Definition: libdhcp++.cc:214
static void revertRuntimeOptionDefs()
Reverts uncommitted changes to runtime option definitions.
Definition: libdhcp++.cc:235
Simple parser for multi-threading structure.
void parse(SrvConfig &srv_cfg, const isc::data::ConstElementPtr &value)
parses JSON structure.
Parser for option data values within a subnet.
void parse(const CfgOptionPtr &cfg, isc::data::ConstElementPtr option_data_list)
Parses a list of options, instantiates them and stores in cfg.
Parser for a list of option definitions.
Definition: dhcp_parsers.h:254
void parse(CfgOptionDefPtr cfg, isc::data::ConstElementPtr def_list)
Parses a list of option definitions, create them and store in cfg.
Class of option definition space container.
Simple parser for sanity-checks structure.
void parse(SrvConfig &srv_cfg, const isc::data::ConstElementPtr &value)
parses JSON structure
Parser for a list of shared networks.
void parse(CfgSharedNetworksTypePtr &cfg, const data::ConstElementPtr &shared_networks_list_data)
Parses a list of shared networks.
static size_t deriveParameters(isc::data::ElementPtr global)
Derives (inherits) all parameters from global to more specific scopes.
static size_t setAllDefaults(isc::data::ElementPtr global)
Sets all defaults for DHCPv4 configuration.
static const uint32_t CFGSEL_ALL4
IPv4 related config.
Definition: srv_config.h:191
static void resetSubnetID()
Resets subnet-id counter to its initial value (1).
Definition: subnet.h:241
this class parses list of DHCP4 subnets
Definition: dhcp_parsers.h:641
size_t parse(SrvConfigPtr cfg, data::ConstElementPtr subnets_list)
parses contents of the list
static const TimerMgrPtr & instance()
Returns pointer to the sole instance of the TimerMgr.
Definition: timer_mgr.cc:449
Wrapper class that holds hooks libraries configuration.
Definition: hooks_config.h:36
void verifyLibraries(const isc::data::Element::Position &position) const
Verifies that libraries stored in libraries_ are valid.
Definition: hooks_config.cc:20
void loadLibraries() const
Commits hooks libraries configuration.
Definition: hooks_config.cc:55
Parser for hooks library list.
Definition: hooks_parser.h:21
void parse(HooksConfig &libraries, isc::data::ConstElementPtr value)
Parses parameters value.
Definition: hooks_parser.cc:28
Implements parser for config control information, "config-control".
ConfigControlInfoPtr parse(const data::ConstElementPtr &config_control)
Parses a configuration control Element.
isc::data::ConstElementPtr redactConfig(isc::data::ConstElementPtr const &config)
Redact a configuration.
Definition: daemon.cc:257
Parsers for client class definitions.
This file contains several functions and constants that are used for handling commands and responses ...
Contains declarations for loggers used by the DHCPv4 server component.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
ConstElementPtr createAnswer(const int status_code, const std::string &text, const ConstElementPtr &arg)
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
boost::shared_ptr< Element > ElementPtr
Definition: data.h:24
void configureCommandChannel()
Initialize the command channel based on the staging configuration.
std::pair< std::string, isc::data::ConstElementPtr > ConfigPair
Combination of parameter name and configuration contents.
Definition: dhcp_parsers.h:175
const isc::log::MessageID DHCP4_CONFIG_START
boost::shared_ptr< D2ClientConfig > D2ClientConfigPtr
Defines a pointer for D2ClientConfig instances.
const isc::log::MessageID DHCP4_PARSER_EXCEPTION
boost::shared_ptr< CfgOption > CfgOptionPtr
Non-const pointer.
Definition: cfg_option.h:706
boost::shared_ptr< CfgOptionDef > CfgOptionDefPtr
Non-const pointer.
boost::shared_ptr< CfgDbAccess > CfgDbAccessPtr
A pointer to the CfgDbAccess.
isc::data::ConstElementPtr configureDhcp4Server(Dhcpv4Srv &server, isc::data::ConstElementPtr config_set, bool check_only)
Configure DHCPv4 server (Dhcpv4Srv) with a set of configuration values.
boost::shared_ptr< CfgIface > CfgIfacePtr
A pointer to the CfgIface .
Definition: cfg_iface.h:387
const isc::log::MessageID DHCP4_PARSER_COMMIT_EXCEPTION
boost::shared_ptr< SrvConfig > SrvConfigPtr
Non-const pointer to the SrvConfig.
Definition: srv_config.h:1044
const isc::log::MessageID DHCP4_PARSER_FAIL
std::vector< HostPtr > HostCollection
Collection of the Host objects.
Definition: host.h:794
const int DBG_DHCP4_COMMAND
Debug level used to log receiving commands.
Definition: dhcp4_log.h:30
const isc::log::MessageID DHCP4_PARSER_COMMIT_FAIL
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
boost::shared_ptr< ClientClassDictionary > ClientClassDictionaryPtr
Defines a pointer to a ClientClassDictionary.
boost::shared_ptr< CfgSubnets4 > CfgSubnets4Ptr
Non-const pointer.
Definition: cfg_subnets4.h:332
const isc::log::MessageID DHCP4_CONFIG_COMPLETE
boost::multi_index_container< SharedNetwork4Ptr, boost::multi_index::indexed_by< boost::multi_index::random_access< boost::multi_index::tag< SharedNetworkRandomAccessIndexTag > >, boost::multi_index::hashed_non_unique< boost::multi_index::tag< SharedNetworkIdIndexTag >, boost::multi_index::const_mem_fun< data::BaseStampedElement, uint64_t, &data::BaseStampedElement::getId > >, boost::multi_index::ordered_unique< boost::multi_index::tag< SharedNetworkNameIndexTag >, boost::multi_index::const_mem_fun< SharedNetwork4, std::string, &SharedNetwork4::getName > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SharedNetworkServerIdIndexTag >, boost::multi_index::const_mem_fun< Network4, asiolink::IOAddress, &Network4::getServerId > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SharedNetworkModificationTimeIndexTag >, boost::multi_index::const_mem_fun< data::BaseStampedElement, boost::posix_time::ptime, &data::BaseStampedElement::getModificationTime > > > > SharedNetwork4Collection
Multi index container holding shared networks.
boost::shared_ptr< CfgSharedNetworks4 > CfgSharedNetworks4Ptr
Pointer to the configuration of IPv4 shared networks.
isc::log::Logger dhcp4_logger(DHCP4_APP_LOGGER_NAME)
Base logger for DHCPv4 server.
Definition: dhcp4_log.h:90
boost::shared_ptr< ConfigControlInfo > ConfigControlInfoPtr
Defines a pointer to a ConfigControlInfo.
Defines the logger used by the top-level component of kea-lfc.