Kea 1.9.11
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 CfgMgr::instance().getStagingCfg()->addConfiguredGlobal(config_pair.first,
673 config_pair.second);
674 continue;
675 }
676
677 // Nothing to configure for the user-context.
678 if (config_pair.first == "user-context") {
679 continue;
680 }
681
682 // If we got here, no code handled this parameter, so we bail out.
684 "unsupported global configuration parameter: " << config_pair.first
685 << " (" << config_pair.second->getPosition() << ")");
686 }
687
688 // Reset parameter name.
689 parameter_name = "<post parsing>";
690
691 // Apply global options in the staging config.
692 global_parser.parse(srv_cfg, mutable_cfg);
693
694 // This method conducts final sanity checks and tweaks. In particular,
695 // it checks that there is no conflict between plain subnets and those
696 // defined as part of shared networks.
697 global_parser.sanityChecks(srv_cfg, mutable_cfg);
698
699 // Validate D2 client configuration.
700 if (!d2_client_cfg) {
701 d2_client_cfg.reset(new D2ClientConfig());
702 }
703 d2_client_cfg->validateContents();
704 srv_cfg->setD2ClientConfig(d2_client_cfg);
705 } catch (const isc::Exception& ex) {
707 .arg(parameter_name).arg(ex.what());
709
710 // An error occurred, so make sure that we restore original data.
711 rollback = true;
712 } catch (...) {
713 // For things like bad_cast in boost::lexical_cast
714 LOG_ERROR(dhcp4_logger, DHCP4_PARSER_EXCEPTION).arg(parameter_name);
715 answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
716 " processing error");
717
718 // An error occurred, so make sure that we restore original data.
719 rollback = true;
720 }
721
722 if (check_only) {
723 rollback = true;
724 if (!answer) {
726 "Configuration seems sane. Control-socket, hook-libraries, and D2 "
727 "configuration were sanity checked, but not applied.");
728 }
729 }
730
731 // So far so good, there was no parsing error so let's commit the
732 // configuration. This will add created subnets and option values into
733 // the server's configuration.
734 // This operation should be exception safe but let's make sure.
735 if (!rollback) {
736 try {
737
738 // Setup the command channel.
740
741 // No need to commit interface names as this is handled by the
742 // CfgMgr::commit() function.
743
744 // Apply the staged D2ClientConfig, used to be done by parser commit
746 cfg = CfgMgr::instance().getStagingCfg()->getD2ClientConfig();
748
749 // This occurs last as if it succeeds, there is no easy way to
750 // revert it. As a result, the failure to commit a subsequent
751 // change causes problems when trying to roll back.
752 HooksManager::prepareUnloadLibraries();
753 static_cast<void>(HooksManager::unloadLibraries());
754 const HooksConfig& libraries =
755 CfgMgr::instance().getStagingCfg()->getHooksConfig();
756 libraries.loadLibraries();
757 }
758 catch (const isc::Exception& ex) {
761
762 // An error occurred, so make sure to restore the original data.
763 rollback = true;
764 } catch (...) {
765 // For things like bad_cast in boost::lexical_cast
767 answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
768 " parsing error");
769
770 // An error occurred, so make sure to restore the original data.
771 rollback = true;
772 }
773 }
774
775 // Moved from the commit block to add the config backend indication.
776 if (!rollback) {
777 try {
778
779 // If there are config backends, fetch and merge into staging config
780 server.getCBControl()->databaseConfigFetch(srv_cfg,
782 }
783 catch (const isc::Exception& ex) {
784 std::ostringstream err;
785 err << "during update from config backend database: " << ex.what();
788
789 // An error occurred, so make sure to restore the original data.
790 rollback = true;
791 } catch (...) {
792 // For things like bad_cast in boost::lexical_cast
793 std::ostringstream err;
794 err << "during update from config backend database: "
795 << "undefined configuration parsing error";
798
799 // An error occurred, so make sure to restore the original data.
800 rollback = true;
801 }
802 }
803
804 // Rollback changes as the configuration parsing failed.
805 if (rollback) {
806 // Revert to original configuration of runtime option definitions
807 // in the libdhcp++.
809 return (answer);
810 }
811
813 .arg(CfgMgr::instance().getStagingCfg()->
814 getConfigSummary(SrvConfig::CFGSEL_ALL4));
815
816 // Everything was fine. Configuration is successful.
817 answer = isc::config::createAnswer(CONTROL_RESULT_SUCCESS, "Configuration successful.");
818 return (answer);
819}
820
821} // namespace dhcp
822} // 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:210
void parse(SrvConfig &srv_cfg, isc::data::ConstElementPtr value)
"Parses" control-socket structure
Definition: dhcp_parsers.cc:76
Parser for D2ClientConfig.
Definition: dhcp_parsers.h:832
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:4093
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:253
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:579
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:174
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.