Kea 2.2.0
dhcp4/json_config_parser.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2022 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
10#include <config/command_mgr.h>
14#include <dhcp4/dhcp4_log.h>
15#include <dhcp4/dhcp4_srv.h>
17#include <dhcp/libdhcp++.h>
20#include <dhcpsrv/cfg_option.h>
21#include <dhcpsrv/cfgmgr.h>
23#include <dhcpsrv/db_type.h>
37#include <dhcpsrv/timer_mgr.h>
38#include <hooks/hooks_manager.h>
39#include <hooks/hooks_parser.h>
41#include <util/encode/hex.h>
43#include <util/strutil.h>
44
45#include <boost/algorithm/string.hpp>
46#include <boost/foreach.hpp>
47#include <boost/lexical_cast.hpp>
48
49#include <iomanip>
50#include <iostream>
51#include <limits>
52#include <map>
53#include <netinet/in.h>
54#include <vector>
55
56using namespace std;
57using namespace isc;
58using namespace isc::data;
59using namespace isc::dhcp;
60using namespace isc::asiolink;
61using namespace isc::hooks;
62using namespace isc::process;
63using namespace isc::config;
64using namespace isc::util;
65
66namespace {
67
76class Dhcp4ConfigParser : public isc::data::SimpleParser {
77public:
78
93 void parse(const SrvConfigPtr& cfg, const ConstElementPtr& global) {
94
95 // Set whether v4 server is supposed to echo back client-id
96 // (yes = RFC6842 compatible, no = backward compatibility)
97 bool echo_client_id = getBoolean(global, "echo-client-id");
98 cfg->setEchoClientId(echo_client_id);
99
100 // Set the probation period for decline handling.
101 uint32_t probation_period =
102 getUint32(global, "decline-probation-period");
103 cfg->setDeclinePeriod(probation_period);
104
105 // Set the DHCPv4-over-DHCPv6 interserver port.
106 uint16_t dhcp4o6_port = getUint16(global, "dhcp4o6-port");
107 cfg->setDhcp4o6Port(dhcp4o6_port);
108
109 // Set the global user context.
110 ConstElementPtr user_context = global->get("user-context");
111 if (user_context) {
112 cfg->setContext(user_context);
113 }
114
115 // Set the server's logical name
116 std::string server_tag = getString(global, "server-tag");
117 cfg->setServerTag(server_tag);
118 }
119
131 void parseEarly(const SrvConfigPtr& cfg, const ConstElementPtr& global) {
132 // Set ip-reservations-unique flag.
133 bool ip_reservations_unique = getBoolean(global, "ip-reservations-unique");
134 cfg->setIPReservationsUnique(ip_reservations_unique);
135 }
136
143 void
144 copySubnets4(const CfgSubnets4Ptr& dest, const CfgSharedNetworks4Ptr& from) {
145
146 if (!dest || !from) {
147 isc_throw(BadValue, "Unable to copy subnets: at least one pointer is null");
148 }
149
150 const SharedNetwork4Collection* networks = from->getAll();
151 if (!networks) {
152 // Nothing to copy. Technically, it should return a pointer to empty
153 // container, but let's handle null pointer as well.
154 return;
155 }
156
157 // Let's go through all the networks one by one
158 for (auto net = networks->begin(); net != networks->end(); ++net) {
159
160 // For each network go through all the subnets in it.
161 const Subnet4SimpleCollection* subnets = (*net)->getAllSubnets();
162 if (!subnets) {
163 // Shared network without subnets it weird, but we decided to
164 // accept such configurations.
165 continue;
166 }
167
168 // For each subnet, add it to a list of regular subnets.
169 for (auto subnet = subnets->begin(); subnet != subnets->end(); ++subnet) {
170 dest->add(*subnet);
171 }
172 }
173 }
174
183 void
184 sanityChecks(const SrvConfigPtr& cfg, const ConstElementPtr& global) {
185
187 cfg->sanityChecksLifetime("valid-lifetime");
188
190 const SharedNetwork4Collection* networks = cfg->getCfgSharedNetworks4()->getAll();
191 if (networks) {
192 sharedNetworksSanityChecks(*networks, global->get("shared-networks"));
193 }
194 }
195
202 void
203 sharedNetworksSanityChecks(const SharedNetwork4Collection& networks,
204 ConstElementPtr json) {
205
207 if (!json) {
208 // No json? That means that the shared-networks was never specified
209 // in the config.
210 return;
211 }
212
213 // Used for names uniqueness checks.
214 std::set<string> names;
215
216 // Let's go through all the networks one by one
217 for (auto net = networks.begin(); net != networks.end(); ++net) {
218 string txt;
219
220 // Let's check if all subnets have either the same interface
221 // or don't have the interface specified at all.
222 bool authoritative = (*net)->getAuthoritative();
223 string iface = (*net)->getIface();
224
225 const Subnet4SimpleCollection* subnets = (*net)->getAllSubnets();
226 if (subnets) {
227 // For each subnet, add it to a list of regular subnets.
228 for (auto subnet = subnets->begin(); subnet != subnets->end(); ++subnet) {
229 if ((*subnet)->getAuthoritative() != authoritative) {
230 isc_throw(DhcpConfigError, "Subnet " << boolalpha
231 << (*subnet)->toText()
232 << " has different authoritative setting "
233 << (*subnet)->getAuthoritative()
234 << " than the shared-network itself: "
235 << authoritative);
236 }
237
238 if (iface.empty()) {
239 iface = (*subnet)->getIface();
240 continue;
241 }
242
243 if ((*subnet)->getIface().empty()) {
244 continue;
245 }
246
247 if ((*subnet)->getIface() != iface) {
248 isc_throw(DhcpConfigError, "Subnet " << (*subnet)->toText()
249 << " has specified interface " << (*subnet)->getIface()
250 << ", but earlier subnet in the same shared-network"
251 << " or the shared-network itself used " << iface);
252 }
253
254 // Let's collect the subnets in case we later find out the
255 // subnet doesn't have a mandatory name.
256 txt += (*subnet)->toText() + " ";
257 }
258 }
259
260 // Next, let's check name of the shared network.
261 if ((*net)->getName().empty()) {
262 isc_throw(DhcpConfigError, "Shared-network with subnets "
263 << txt << " is missing mandatory 'name' parameter");
264 }
265
266 // Is it unique?
267 if (names.find((*net)->getName()) != names.end()) {
268 isc_throw(DhcpConfigError, "A shared-network with "
269 "name " << (*net)->getName() << " defined twice.");
270 }
271 names.insert((*net)->getName());
272
273 }
274 }
275};
276
277} // anonymous namespace
278
279namespace isc {
280namespace dhcp {
281
290 // Get new socket configuration.
291 ConstElementPtr sock_cfg =
292 CfgMgr::instance().getStagingCfg()->getControlSocketInfo();
293
294 // Get current socket configuration.
295 ConstElementPtr current_sock_cfg =
296 CfgMgr::instance().getCurrentCfg()->getControlSocketInfo();
297
298 // Determine if the socket configuration has changed. It has if
299 // both old and new configuration is specified but respective
300 // data elements aren't equal.
301 bool sock_changed = (sock_cfg && current_sock_cfg &&
302 !sock_cfg->equals(*current_sock_cfg));
303
304 // If the previous or new socket configuration doesn't exist or
305 // the new configuration differs from the old configuration we
306 // close the existing socket and open a new socket as appropriate.
307 // Note that closing an existing socket means the client will not
308 // receive the configuration result.
309 if (!sock_cfg || !current_sock_cfg || sock_changed) {
310 // Close the existing socket (if any).
312
313 if (sock_cfg) {
314 // This will create a control socket and install the external
315 // socket in IfaceMgr. That socket will be monitored when
316 // Dhcp4Srv::receivePacket() calls IfaceMgr::receive4() and
317 // callback in CommandMgr will be called, if necessary.
319 }
320 }
321}
322
325 bool check_only) {
326 if (!config_set) {
328 string("Can't parse NULL config"));
329 return (answer);
330 }
331
333 .arg(server.redactConfig(config_set)->str());
334
335 // Before starting any subnet operations, let's reset the subnet-id counter,
336 // so newly recreated configuration starts with first subnet-id equal 1.
338
339 // Close DHCP sockets and remove any existing timers.
340 if (!check_only) {
342 TimerMgr::instance()->unregisterTimers();
343 server.discardPackets();
344 server.getCBControl()->reset();
345 }
346
347 // Revert any runtime option definitions configured so far and not committed.
349 // Let's set empty container in case a user hasn't specified any configuration
350 // for option definitions. This is equivalent to committing empty container.
352
353 // Print the list of known backends.
355
356 // Answer will hold the result.
357 ConstElementPtr answer;
358 // Rollback informs whether error occurred and original data
359 // have to be restored to global storages.
360 bool rollback = false;
361 // Global parameter name in case of an error.
362 string parameter_name;
363 ElementPtr mutable_cfg;
364 SrvConfigPtr srv_config;
365 try {
366 // Get the staging configuration.
367 srv_config = CfgMgr::instance().getStagingCfg();
368
369 // This is a way to convert ConstElementPtr to ElementPtr.
370 // We need a config that can be edited, because we will insert
371 // default values and will insert derived values as well.
372 mutable_cfg = boost::const_pointer_cast<Element>(config_set);
373
374 // Relocate dhcp-ddns parameters that have moved to global scope.
375 // Rule is that a global value overrides the dhcp-ddns value, so
376 // we need to do this before we apply global defaults.
377 // Note this is done for backward compatibility.
378 srv_config->moveDdnsParams(mutable_cfg);
379
380 // Move from reservation mode to new reservations flags.
381 // @todo add warning
383
384 // Set all default values if not specified by the user.
386
387 // And now derive (inherit) global parameters to subnets, if not specified.
389
390 // In principle we could have the following code structured as a series
391 // of long if else if clauses. That would give a marginal performance
392 // boost, but would make the code less readable. We had serious issues
393 // with the parser code debugability, so I decided to keep it as a
394 // series of independent ifs.
395
396 // This parser is used in several places.
397 Dhcp4ConfigParser global_parser;
398
399 // Apply global options in the staging config, e.g. ip-reservations-unique
400 global_parser.parseEarly(srv_config, mutable_cfg);
401
402 // We need definitions first
403 ConstElementPtr option_defs = mutable_cfg->get("option-def");
404 if (option_defs) {
405 parameter_name = "option-def";
406 OptionDefListParser parser(AF_INET);
407 CfgOptionDefPtr cfg_option_def = srv_config->getCfgOptionDef();
408 parser.parse(cfg_option_def, option_defs);
409 }
410
411 ConstElementPtr option_datas = mutable_cfg->get("option-data");
412 if (option_datas) {
413 parameter_name = "option-data";
414 OptionDataListParser parser(AF_INET);
415 CfgOptionPtr cfg_option = srv_config->getCfgOption();
416 parser.parse(cfg_option, option_datas);
417 }
418
419 ConstElementPtr control_socket = mutable_cfg->get("control-socket");
420 if (control_socket) {
421 parameter_name = "control-socket";
422 ControlSocketParser parser;
423 parser.parse(*srv_config, control_socket);
424 }
425
426 ConstElementPtr multi_threading = mutable_cfg->get("multi-threading");
427 if (multi_threading) {
428 parameter_name = "multi-threading";
430 parser.parse(*srv_config, multi_threading);
431 }
432
434 ConstElementPtr queue_control = mutable_cfg->get("dhcp-queue-control");
435 if (queue_control) {
436 parameter_name = "dhcp-queue-control";
438 srv_config->setDHCPQueueControl(parser.parse(queue_control));
439 }
440
442 ConstElementPtr reservations_lookup_first = mutable_cfg->get("reservations-lookup-first");
443 if (reservations_lookup_first) {
444 parameter_name = "reservations-lookup-first";
445 if (MultiThreadingMgr::instance().getMode()) {
447 }
448 srv_config->setReservationsLookupFirst(reservations_lookup_first->boolValue());
449 }
450
451 ConstElementPtr hr_identifiers =
452 mutable_cfg->get("host-reservation-identifiers");
453 if (hr_identifiers) {
454 parameter_name = "host-reservation-identifiers";
456 parser.parse(hr_identifiers);
457 }
458
459 ConstElementPtr ifaces_config = mutable_cfg->get("interfaces-config");
460 if (ifaces_config) {
461 parameter_name = "interfaces-config";
462 IfacesConfigParser parser(AF_INET, check_only);
463 CfgIfacePtr cfg_iface = srv_config->getCfgIface();
464 parser.parse(cfg_iface, ifaces_config);
465 }
466
467 ConstElementPtr sanity_checks = mutable_cfg->get("sanity-checks");
468 if (sanity_checks) {
469 parameter_name = "sanity-checks";
470 SanityChecksParser parser;
471 parser.parse(*srv_config, sanity_checks);
472 }
473
474 ConstElementPtr expiration_cfg =
475 mutable_cfg->get("expired-leases-processing");
476 if (expiration_cfg) {
477 parameter_name = "expired-leases-processing";
479 parser.parse(expiration_cfg);
480 }
481
482 // The hooks-libraries configuration must be parsed after parsing
483 // multi-threading configuration so that libraries are checked
484 // for multi-threading compatibility.
485 ConstElementPtr hooks_libraries = mutable_cfg->get("hooks-libraries");
486 if (hooks_libraries) {
487 parameter_name = "hooks-libraries";
488 HooksLibrariesParser hooks_parser;
489 HooksConfig& libraries = srv_config->getHooksConfig();
490 hooks_parser.parse(libraries, hooks_libraries);
491 libraries.verifyLibraries(hooks_libraries->getPosition());
492 }
493
494 // D2 client configuration.
495 D2ClientConfigPtr d2_client_cfg;
496
497 // Legacy DhcpConfigParser stuff below.
498 ConstElementPtr dhcp_ddns = mutable_cfg->get("dhcp-ddns");
499 if (dhcp_ddns) {
500 parameter_name = "dhcp-ddns";
501 // Apply defaults
504 d2_client_cfg = parser.parse(dhcp_ddns);
505 }
506
507 ConstElementPtr client_classes = mutable_cfg->get("client-classes");
508 if (client_classes) {
509 parameter_name = "client-classes";
511 ClientClassDictionaryPtr dictionary =
512 parser.parse(client_classes, AF_INET);
513 srv_config->setClientClassDictionary(dictionary);
514 }
515
516 // Please move at the end when migration will be finished.
517 ConstElementPtr lease_database = mutable_cfg->get("lease-database");
518 if (lease_database) {
519 parameter_name = "lease-database";
520 db::DbAccessParser parser;
521 std::string access_string;
522 parser.parse(access_string, lease_database);
523 CfgDbAccessPtr cfg_db_access = srv_config->getCfgDbAccess();
524 cfg_db_access->setLeaseDbAccessString(access_string);
525 }
526
527 ConstElementPtr hosts_database = mutable_cfg->get("hosts-database");
528 if (hosts_database) {
529 parameter_name = "hosts-database";
530 db::DbAccessParser parser;
531 std::string access_string;
532 parser.parse(access_string, hosts_database);
533 CfgDbAccessPtr cfg_db_access = srv_config->getCfgDbAccess();
534 cfg_db_access->setHostDbAccessString(access_string);
535 }
536
537 ConstElementPtr hosts_databases = mutable_cfg->get("hosts-databases");
538 if (hosts_databases) {
539 parameter_name = "hosts-databases";
540 CfgDbAccessPtr cfg_db_access = srv_config->getCfgDbAccess();
541 for (auto it : hosts_databases->listValue()) {
542 db::DbAccessParser parser;
543 std::string access_string;
544 parser.parse(access_string, it);
545 cfg_db_access->setHostDbAccessString(access_string);
546 }
547 }
548
549 // Keep relative orders of shared networks and subnets.
550 ConstElementPtr shared_networks = mutable_cfg->get("shared-networks");
551 if (shared_networks) {
552 parameter_name = "shared-networks";
559 CfgSharedNetworks4Ptr cfg = srv_config->getCfgSharedNetworks4();
560 parser.parse(cfg, shared_networks);
561
562 // We also need to put the subnets it contains into normal
563 // subnets list.
564 global_parser.copySubnets4(srv_config->getCfgSubnets4(), cfg);
565 }
566
567 ConstElementPtr subnet4 = mutable_cfg->get("subnet4");
568 if (subnet4) {
569 parameter_name = "subnet4";
570 Subnets4ListConfigParser subnets_parser;
571 // parse() returns number of subnets parsed. We may log it one day.
572 subnets_parser.parse(srv_config, subnet4);
573 }
574
575 ConstElementPtr reservations = mutable_cfg->get("reservations");
576 if (reservations) {
577 parameter_name = "reservations";
578 HostCollection hosts;
580 parser.parse(SUBNET_ID_GLOBAL, reservations, hosts);
581 for (auto h = hosts.begin(); h != hosts.end(); ++h) {
582 srv_config->getCfgHosts()->add(*h);
583 }
584 }
585
586 ConstElementPtr config_control = mutable_cfg->get("config-control");
587 if (config_control) {
588 parameter_name = "config-control";
589 ConfigControlParser parser;
590 ConfigControlInfoPtr config_ctl_info = parser.parse(config_control);
591 CfgMgr::instance().getStagingCfg()->setConfigControlInfo(config_ctl_info);
592 }
593
594 ConstElementPtr compatibility = mutable_cfg->get("compatibility");
595 if (compatibility) {
596 for (auto kv : compatibility->mapValue()) {
597 if (kv.first == "lenient-option-parsing") {
598 CfgMgr::instance().getStagingCfg()->setLenientOptionParsing(
599 kv.second->boolValue());
600 }
601 }
602 }
603
604 // Make parsers grouping.
605 ConfigPair config_pair;
606 const std::map<std::string, ConstElementPtr>& values_map =
607 mutable_cfg->mapValue();
608
609 BOOST_FOREACH(config_pair, values_map) {
610
611 parameter_name = config_pair.first;
612
613 // These are converted to SimpleParser and are handled already above.
614 if ((config_pair.first == "option-def") ||
615 (config_pair.first == "option-data") ||
616 (config_pair.first == "control-socket") ||
617 (config_pair.first == "multi-threading") ||
618 (config_pair.first == "dhcp-queue-control") ||
619 (config_pair.first == "host-reservation-identifiers") ||
620 (config_pair.first == "interfaces-config") ||
621 (config_pair.first == "sanity-checks") ||
622 (config_pair.first == "expired-leases-processing") ||
623 (config_pair.first == "hooks-libraries") ||
624 (config_pair.first == "dhcp-ddns") ||
625 (config_pair.first == "client-classes") ||
626 (config_pair.first == "lease-database") ||
627 (config_pair.first == "hosts-database") ||
628 (config_pair.first == "hosts-databases") ||
629 (config_pair.first == "subnet4") ||
630 (config_pair.first == "shared-networks") ||
631 (config_pair.first == "reservations") ||
632 (config_pair.first == "config-control") ||
633 (config_pair.first == "loggers") ||
634 (config_pair.first == "compatibility")) {
635 continue;
636 }
637
638 // As of Kea 1.6.0 we have two ways of inheriting the global parameters.
639 // The old method is used in JSON configuration parsers when the global
640 // parameters are derived into the subnets and shared networks and are
641 // being treated as explicitly specified. The new way used by the config
642 // backend is the dynamic inheritance whereby each subnet and shared
643 // network uses a callback function to return global parameter if it
644 // is not specified at lower level. This callback uses configured globals.
645 // We deliberately include both default and explicitly specified globals
646 // so as the callback can access the appropriate global values regardless
647 // whether they are set to a default or other value.
648 if ( (config_pair.first == "renew-timer") ||
649 (config_pair.first == "rebind-timer") ||
650 (config_pair.first == "valid-lifetime") ||
651 (config_pair.first == "min-valid-lifetime") ||
652 (config_pair.first == "max-valid-lifetime") ||
653 (config_pair.first == "decline-probation-period") ||
654 (config_pair.first == "dhcp4o6-port") ||
655 (config_pair.first == "echo-client-id") ||
656 (config_pair.first == "match-client-id") ||
657 (config_pair.first == "authoritative") ||
658 (config_pair.first == "next-server") ||
659 (config_pair.first == "server-hostname") ||
660 (config_pair.first == "boot-file-name") ||
661 (config_pair.first == "server-tag") ||
662 (config_pair.first == "reservation-mode") ||
663 (config_pair.first == "reservations-global") ||
664 (config_pair.first == "reservations-in-subnet") ||
665 (config_pair.first == "reservations-out-of-pool") ||
666 (config_pair.first == "calculate-tee-times") ||
667 (config_pair.first == "t1-percent") ||
668 (config_pair.first == "t2-percent") ||
669 (config_pair.first == "cache-threshold") ||
670 (config_pair.first == "cache-max-age") ||
671 (config_pair.first == "hostname-char-set") ||
672 (config_pair.first == "hostname-char-replacement") ||
673 (config_pair.first == "ddns-send-updates") ||
674 (config_pair.first == "ddns-override-no-update") ||
675 (config_pair.first == "ddns-override-client-update") ||
676 (config_pair.first == "ddns-replace-client-name") ||
677 (config_pair.first == "ddns-generated-prefix") ||
678 (config_pair.first == "ddns-qualifying-suffix") ||
679 (config_pair.first == "ddns-update-on-renew") ||
680 (config_pair.first == "ddns-use-conflict-resolution") ||
681 (config_pair.first == "store-extended-info") ||
682 (config_pair.first == "statistic-default-sample-count") ||
683 (config_pair.first == "statistic-default-sample-age") ||
684 (config_pair.first == "early-global-reservations-lookup") ||
685 (config_pair.first == "ip-reservations-unique") ||
686 (config_pair.first == "reservations-lookup-first") ||
687 (config_pair.first == "parked-packet-limit")) {
688 CfgMgr::instance().getStagingCfg()->addConfiguredGlobal(config_pair.first,
689 config_pair.second);
690 continue;
691 }
692
693 // Nothing to configure for the user-context.
694 if (config_pair.first == "user-context") {
695 continue;
696 }
697
698 // If we got here, no code handled this parameter, so we bail out.
700 "unsupported global configuration parameter: " << config_pair.first
701 << " (" << config_pair.second->getPosition() << ")");
702 }
703
704 // Reset parameter name.
705 parameter_name = "<post parsing>";
706
707 // Apply global options in the staging config.
708 global_parser.parse(srv_config, mutable_cfg);
709
710 // This method conducts final sanity checks and tweaks. In particular,
711 // it checks that there is no conflict between plain subnets and those
712 // defined as part of shared networks.
713 global_parser.sanityChecks(srv_config, mutable_cfg);
714
715 // Validate D2 client configuration.
716 if (!d2_client_cfg) {
717 d2_client_cfg.reset(new D2ClientConfig());
718 }
719 d2_client_cfg->validateContents();
720 srv_config->setD2ClientConfig(d2_client_cfg);
721 } catch (const isc::Exception& ex) {
723 .arg(parameter_name).arg(ex.what());
725
726 // An error occurred, so make sure that we restore original data.
727 rollback = true;
728 } catch (...) {
729 // For things like bad_cast in boost::lexical_cast
730 LOG_ERROR(dhcp4_logger, DHCP4_PARSER_EXCEPTION).arg(parameter_name);
731 answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
732 " processing error");
733
734 // An error occurred, so make sure that we restore original data.
735 rollback = true;
736 }
737
738 if (check_only) {
739 rollback = true;
740 if (!answer) {
742 "Configuration seems sane. Control-socket, hook-libraries, and D2 "
743 "configuration were sanity checked, but not applied.");
744 }
745 }
746
747 // So far so good, there was no parsing error so let's commit the
748 // configuration. This will add created subnets and option values into
749 // the server's configuration.
750 // This operation should be exception safe but let's make sure.
751 if (!rollback) {
752 try {
753
754 // Setup the command channel.
756
757 // No need to commit interface names as this is handled by the
758 // CfgMgr::commit() function.
759
760 // Apply the staged D2ClientConfig, used to be done by parser commit
762 cfg = CfgMgr::instance().getStagingCfg()->getD2ClientConfig();
764
765 // This occurs last as if it succeeds, there is no easy way to
766 // revert it. As a result, the failure to commit a subsequent
767 // change causes problems when trying to roll back.
768 HooksManager::prepareUnloadLibraries();
769 static_cast<void>(HooksManager::unloadLibraries());
770 const HooksConfig& libraries =
771 CfgMgr::instance().getStagingCfg()->getHooksConfig();
772 libraries.loadLibraries();
773 } catch (const isc::Exception& ex) {
776
777 // An error occurred, so make sure to restore the original data.
778 rollback = true;
779 } catch (...) {
780 // For things like bad_cast in boost::lexical_cast
782 answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
783 " parsing error");
784
785 // An error occurred, so make sure to restore the original data.
786 rollback = true;
787 }
788 }
789
790 // Moved from the commit block to add the config backend indication.
791 if (!rollback) {
792 try {
793
794 // If there are config backends, fetch and merge into staging config
795 server.getCBControl()->databaseConfigFetch(srv_config,
796 CBControlDHCPv4::FetchMode::FETCH_ALL);
797 } catch (const isc::Exception& ex) {
798 std::ostringstream err;
799 err << "during update from config backend database: " << ex.what();
802
803 // An error occurred, so make sure to restore the original data.
804 rollback = true;
805 } catch (...) {
806 // For things like bad_cast in boost::lexical_cast
807 std::ostringstream err;
808 err << "during update from config backend database: "
809 << "undefined configuration parsing error";
812
813 // An error occurred, so make sure to restore the original data.
814 rollback = true;
815 }
816 }
817
818 // Rollback changes as the configuration parsing failed.
819 if (rollback) {
820 // Revert to original configuration of runtime option definitions
821 // in the libdhcp++.
823 return (answer);
824 }
825
827 .arg(CfgMgr::instance().getStagingCfg()->
828 getConfigSummary(SrvConfig::CFGSEL_ALL4));
829
830 // Everything was fine. Configuration is successful.
831 answer = isc::config::createAnswer(CONTROL_RESULT_SUCCESS, "Configuration successful.");
832 return (answer);
833}
834
835} // namespace dhcp
836} // 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:627
static CommandMgr & instance()
CommandMgr is a singleton class.
Definition: command_mgr.cc:650
void openCommandSocket(const isc::data::ConstElementPtr &socket_info)
Opens control socket with parameters specified in socket_info.
Definition: command_mgr.cc:623
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:76
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:57
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:253
CBControlDHCPv4Ptr getCBControl() const
Returns an object which controls access to the configuration backends.
Definition: dhcp4_srv.h:318
void discardPackets()
Discards parked packets Clears the packet parking lots of all packets.
Definition: dhcp4_srv.cc:4334
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:287
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:233
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:201
static void resetSubnetID()
Resets subnet-id counter to its initial value (1).
Definition: subnet.h:243
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_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
#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.
const isc::log::MessageID DHCP4_RESERVATIONS_LOOKUP_FIRST_ENABLED
boost::shared_ptr< CfgIface > CfgIfacePtr
A pointer to the CfgIface .
Definition: cfg_iface.h:501
const isc::log::MessageID DHCP4_PARSER_COMMIT_EXCEPTION
boost::shared_ptr< SrvConfig > SrvConfigPtr
Non-const pointer to the SrvConfig.
Definition: srv_config.h:1165
const isc::log::MessageID DHCP4_PARSER_FAIL
std::vector< HostPtr > HostCollection
Collection of the Host objects.
Definition: host.h:794
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 > > > > Subnet4SimpleCollection
A simple collection of Subnet4 objects.
Definition: subnet.h:837
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::shared_ptr< ClientClassDictionary > ClientClassDictionaryPtr
Defines a pointer to a ClientClassDictionary.
boost::shared_ptr< CfgSubnets4 > CfgSubnets4Ptr
Non-const pointer.
Definition: cfg_subnets4.h:333
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.
Definition: edns.h:19
Defines the logger used by the top-level component of kea-lfc.