Kea 2.0.1
ctrl_dhcp4_srv.cc
Go to the documentation of this file.
1// Copyright (C) 2014-2021 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
10#include <cc/data.h>
12#include <config/command_mgr.h>
13#include <dhcp/libdhcp++.h>
15#include <dhcp4/dhcp4_log.h>
16#include <dhcp4/dhcp4to6_ipc.h>
21#include <dhcpsrv/cfgmgr.h>
22#include <dhcpsrv/db_type.h>
23#include <dhcpsrv/host_mgr.h>
25#include <hooks/hooks.h>
26#include <hooks/hooks_manager.h>
27#include <stats/stats_mgr.h>
29
30#include <signal.h>
31
32#include <sstream>
33
34using namespace isc::asiolink;
35using namespace isc::config;
36using namespace isc::data;
37using namespace isc::db;
38using namespace isc::dhcp;
39using namespace isc::hooks;
40using namespace isc::stats;
41using namespace isc::util;
42using namespace std;
43namespace ph = std::placeholders;
44
45namespace {
46
48struct CtrlDhcp4Hooks {
49 int hooks_index_dhcp4_srv_configured_;
50
52 CtrlDhcp4Hooks() {
53 hooks_index_dhcp4_srv_configured_ = HooksManager::registerHook("dhcp4_srv_configured");
54 }
55
56};
57
58// Declare a Hooks object. As this is outside any function or method, it
59// will be instantiated (and the constructor run) when the module is loaded.
60// As a result, the hook indexes will be defined before any method in this
61// module is called.
62CtrlDhcp4Hooks Hooks;
63
73void signalHandler(int signo) {
74 // SIGHUP signals a request to reconfigure the server.
75 if (signo == SIGHUP) {
76 ControlledDhcpv4Srv::processCommand("config-reload",
78 } else if ((signo == SIGTERM) || (signo == SIGINT)) {
79 ControlledDhcpv4Srv::processCommand("shutdown",
81 }
82}
83
84}
85
86namespace isc {
87namespace dhcp {
88
89ControlledDhcpv4Srv* ControlledDhcpv4Srv::server_ = NULL;
90
91void
92ControlledDhcpv4Srv::init(const std::string& file_name) {
93 // Keep the call timestamp.
94 start_ = boost::posix_time::second_clock::universal_time();
95
96 // Configure the server using JSON file.
97 ConstElementPtr result = loadConfigFile(file_name);
98
99 int rcode;
100 ConstElementPtr comment = isc::config::parseAnswer(rcode, result);
101 if (rcode != CONTROL_RESULT_SUCCESS) {
102 string reason = comment ? comment->stringValue() :
103 "no details available";
104 isc_throw(isc::BadValue, reason);
105 }
106
107 // We don't need to call openActiveSockets() or startD2() as these
108 // methods are called in processConfig() which is called by
109 // processCommand("config-set", ...)
110
111 // Set signal handlers. When the SIGHUP is received by the process
112 // the server reconfiguration will be triggered. When SIGTERM or
113 // SIGINT will be received, the server will start shutting down.
114 signal_set_.reset(new IOSignalSet(getIOService(), signalHandler));
115
116 signal_set_->add(SIGINT);
117 signal_set_->add(SIGHUP);
118 signal_set_->add(SIGTERM);
119}
120
122 // Nothing to do here. No need to disconnect from anything.
123}
124
126ControlledDhcpv4Srv::loadConfigFile(const std::string& file_name) {
127 // This is a configuration backend implementation that reads the
128 // configuration from a JSON file.
129
132
133 // Basic sanity check: file name must not be empty.
134 try {
135 if (file_name.empty()) {
136 // Basic sanity check: file name must not be empty.
137 isc_throw(isc::BadValue, "JSON configuration file not specified."
138 " Please use -c command line option.");
139 }
140
141 // Read contents of the file and parse it as JSON
142 Parser4Context parser;
143 json = parser.parseFile(file_name, Parser4Context::PARSER_DHCP4);
144 if (!json) {
145 isc_throw(isc::BadValue, "no configuration found");
146 }
147
148 // Let's do sanity check before we call json->get() which
149 // works only for map.
150 if (json->getType() != isc::data::Element::map) {
151 isc_throw(isc::BadValue, "Configuration file is expected to be "
152 "a map, i.e., start with { and end with } and contain "
153 "at least an entry called 'Dhcp4' that itself is a map. "
154 << file_name
155 << " is a valid JSON, but its top element is not a map."
156 " Did you forget to add { } around your configuration?");
157 }
158
159 // Use parsed JSON structures to configure the server
160 result = ControlledDhcpv4Srv::processCommand("config-set", json);
161 if (!result) {
162 // Undetermined status of the configuration. This should never
163 // happen, but as the configureDhcp4Server returns a pointer, it is
164 // theoretically possible that it will return NULL.
165 isc_throw(isc::BadValue, "undefined result of "
166 "processCommand(\"config-set\", json)");
167 }
168
169 // Now check is the returned result is successful (rcode=0) or not
170 // (see @ref isc::config::parseAnswer).
171 int rcode;
172 ConstElementPtr comment = isc::config::parseAnswer(rcode, result);
173 if (rcode != CONTROL_RESULT_SUCCESS) {
174 string reason = comment ? comment->stringValue() :
175 "no details available";
176 isc_throw(isc::BadValue, reason);
177 }
178 } catch (const std::exception& ex) {
179 // If configuration failed at any stage, we drop the staging
180 // configuration and continue to use the previous one.
182
184 .arg(file_name).arg(ex.what());
185 isc_throw(isc::BadValue, "configuration error using file '"
186 << file_name << "': " << ex.what());
187 }
188
190 .arg(MultiThreadingMgr::instance().getMode() ? "yes" : "no")
191 .arg(MultiThreadingMgr::instance().getThreadPoolSize())
192 .arg(MultiThreadingMgr::instance().getPacketQueueSize());
193
194 return (result);
195}
196
198ControlledDhcpv4Srv::commandShutdownHandler(const string&, ConstElementPtr args) {
201 return(createAnswer(CONTROL_RESULT_ERROR, "Shutdown failure."));
202 }
203
204 int exit_value = 0;
205 if (args) {
206 // @todo Should we go ahead and shutdown even if the args are invalid?
207 if (args->getType() != Element::map) {
208 return (createAnswer(CONTROL_RESULT_ERROR, "Argument must be a map"));
209 }
210
211 ConstElementPtr param = args->get("exit-value");
212 if (param) {
213 if (param->getType() != Element::integer) {
215 "parameter 'exit-value' is not an integer"));
216 }
217
218 exit_value = param->intValue();
219 }
220 }
221
223 return (createAnswer(CONTROL_RESULT_SUCCESS, "Shutting down."));
224}
225
227ControlledDhcpv4Srv::commandLibReloadHandler(const string&, ConstElementPtr) {
228 // stop thread pool (if running)
230
231 // Clear the packet queue.
232 MultiThreadingMgr::instance().getThreadPool().reset();
233
234 try {
236 HookLibsCollection loaded = HooksManager::getLibraryInfo();
237 HooksManager::prepareUnloadLibraries();
238 static_cast<void>(HooksManager::unloadLibraries());
239 bool status = HooksManager::loadLibraries(loaded);
240 if (!status) {
241 isc_throw(Unexpected, "Failed to reload hooks libraries.");
242 }
243 } catch (const std::exception& ex) {
245 ConstElementPtr answer = isc::config::createAnswer(1, ex.what());
246 return (answer);
247 }
249 "Hooks libraries successfully reloaded.");
250 return (answer);
251}
252
254ControlledDhcpv4Srv::commandConfigReloadHandler(const string&,
255 ConstElementPtr /*args*/) {
256 // Get configuration file name.
257 std::string file = ControlledDhcpv4Srv::getInstance()->getConfigFile();
258 try {
260 auto result = loadConfigFile(file);
262 return (result);
263 } catch (const std::exception& ex) {
264 // Log the unsuccessful reconfiguration. The reason for failure
265 // should be already logged. Don't rethrow an exception so as
266 // the server keeps working.
268 .arg(file);
270 "Config reload failed: " + string(ex.what())));
271 }
272}
273
275ControlledDhcpv4Srv::commandConfigGetHandler(const string&,
276 ConstElementPtr /*args*/) {
277 ConstElementPtr config = CfgMgr::instance().getCurrentCfg()->toElement();
278
279 return (createAnswer(0, config));
280}
281
283ControlledDhcpv4Srv::commandConfigWriteHandler(const string&,
284 ConstElementPtr args) {
285 string filename;
286
287 if (args) {
288 if (args->getType() != Element::map) {
289 return (createAnswer(CONTROL_RESULT_ERROR, "Argument must be a map"));
290 }
291 ConstElementPtr filename_param = args->get("filename");
292 if (filename_param) {
293 if (filename_param->getType() != Element::string) {
295 "passed parameter 'filename' is not a string"));
296 }
297 filename = filename_param->stringValue();
298 }
299 }
300
301 if (filename.empty()) {
302 // filename parameter was not specified, so let's use whatever we remember
303 // from the command-line
304 filename = getConfigFile();
305 }
306
307 if (filename.empty()) {
308 return (createAnswer(CONTROL_RESULT_ERROR, "Unable to determine filename."
309 "Please specify filename explicitly."));
310 }
311
312 // Ok, it's time to write the file.
313 size_t size = 0;
314 try {
315 ConstElementPtr cfg = CfgMgr::instance().getCurrentCfg()->toElement();
316 size = writeConfigFile(filename, cfg);
317 } catch (const isc::Exception& ex) {
318 return (createAnswer(CONTROL_RESULT_ERROR, string("Error during write-config:")
319 + ex.what()));
320 }
321 if (size == 0) {
322 return (createAnswer(CONTROL_RESULT_ERROR, "Error writing configuration to "
323 + filename));
324 }
325
326 // Ok, it's time to return the successful response.
327 ElementPtr params = Element::createMap();
328 params->set("size", Element::create(static_cast<long long>(size)));
329 params->set("filename", Element::create(filename));
330
331 return (createAnswer(CONTROL_RESULT_SUCCESS, "Configuration written to "
332 + filename + " successful", params));
333}
334
336ControlledDhcpv4Srv::commandConfigSetHandler(const string&,
337 ConstElementPtr args) {
338 const int status_code = CONTROL_RESULT_ERROR;
339 ConstElementPtr dhcp4;
340 string message;
341
342 // Command arguments are expected to be:
343 // { "Dhcp4": { ... } }
344 if (!args) {
345 message = "Missing mandatory 'arguments' parameter.";
346 } else {
347 dhcp4 = args->get("Dhcp4");
348 if (!dhcp4) {
349 message = "Missing mandatory 'Dhcp4' parameter.";
350 } else if (dhcp4->getType() != Element::map) {
351 message = "'Dhcp4' parameter expected to be a map.";
352 }
353 }
354
355 // Check unsupported objects.
356 if (message.empty()) {
357 for (auto obj : args->mapValue()) {
358 const string& obj_name = obj.first;
359 if (obj_name != "Dhcp4") {
361 .arg(obj_name);
362 if (message.empty()) {
363 message = "Unsupported '" + obj_name + "' parameter";
364 } else {
365 message += " (and '" + obj_name + "')";
366 }
367 }
368 }
369 if (!message.empty()) {
370 message += ".";
371 }
372 }
373
374 if (!message.empty()) {
375 // Something is amiss with arguments, return a failure response.
376 ConstElementPtr result = isc::config::createAnswer(status_code,
377 message);
378 return (result);
379 }
380
381 // stop thread pool (if running)
383
384 // disable multi-threading (it will be applied by new configuration)
385 // this must be done in order to properly handle MT to ST transition
386 // when 'multi-threading' structure is missing from new config
387 MultiThreadingMgr::instance().apply(false, 0, 0);
388
389 // We are starting the configuration process so we should remove any
390 // staging configuration that has been created during previous
391 // configuration attempts.
393
394 // Parse the logger configuration explicitly into the staging config.
395 // Note this does not alter the current loggers, they remain in
396 // effect until we apply the logging config below. If no logging
397 // is supplied logging will revert to default logging.
398 Daemon::configureLogger(dhcp4, CfgMgr::instance().getStagingCfg());
399
400 // Let's apply the new logging. We do it early, so we'll be able to print
401 // out what exactly is wrong with the new config in case of problems.
402 CfgMgr::instance().getStagingCfg()->applyLoggingCfg();
403
404 // Now we configure the server proper.
405 ConstElementPtr result = processConfig(dhcp4);
406
407 // If the configuration parsed successfully, apply the new logger
408 // configuration and the commit the new configuration. We apply
409 // the logging first in case there's a configuration failure.
410 int rcode = 0;
411 isc::config::parseAnswer(rcode, result);
412 if (rcode == CONTROL_RESULT_SUCCESS) {
413 CfgMgr::instance().getStagingCfg()->applyLoggingCfg();
414
415 // Use new configuration.
417 } else {
418 // Ok, we applied the logging from the upcoming configuration, but
419 // there were problems with the config. As such, we need to back off
420 // and revert to the previous logging configuration.
421 CfgMgr::instance().getCurrentCfg()->applyLoggingCfg();
422
423 if (CfgMgr::instance().getCurrentCfg()->getSequence() != 0) {
424 // Not initial configuration so someone can believe we reverted
425 // to the previous configuration. It is not the case so be clear
426 // about this.
428 }
429 }
430
431 return (result);
432}
433
435ControlledDhcpv4Srv::commandConfigTestHandler(const string&,
436 ConstElementPtr args) {
437 const int status_code = CONTROL_RESULT_ERROR; // 1 indicates an error
438 ConstElementPtr dhcp4;
439 string message;
440
441 // Command arguments are expected to be:
442 // { "Dhcp4": { ... } }
443 if (!args) {
444 message = "Missing mandatory 'arguments' parameter.";
445 } else {
446 dhcp4 = args->get("Dhcp4");
447 if (!dhcp4) {
448 message = "Missing mandatory 'Dhcp4' parameter.";
449 } else if (dhcp4->getType() != Element::map) {
450 message = "'Dhcp4' parameter expected to be a map.";
451 }
452 }
453
454 // Check unsupported objects.
455 if (message.empty()) {
456 for (auto obj : args->mapValue()) {
457 const string& obj_name = obj.first;
458 if (obj_name != "Dhcp4") {
460 .arg(obj_name);
461 if (message.empty()) {
462 message = "Unsupported '" + obj_name + "' parameter";
463 } else {
464 message += " (and '" + obj_name + "')";
465 }
466 }
467 }
468 if (!message.empty()) {
469 message += ".";
470 }
471 }
472
473 if (!message.empty()) {
474 // Something is amiss with arguments, return a failure response.
475 ConstElementPtr result = isc::config::createAnswer(status_code,
476 message);
477 return (result);
478 }
479
480 // stop thread pool (if running)
482
483 // We are starting the configuration process so we should remove any
484 // staging configuration that has been created during previous
485 // configuration attempts.
487
488 // Now we check the server proper.
489 return (checkConfig(dhcp4));
490}
491
493ControlledDhcpv4Srv::commandDhcpDisableHandler(const std::string&,
494 ConstElementPtr args) {
495 std::ostringstream message;
496 int64_t max_period = 0;
497 std::string origin;
498
499 // If the args map does not contain 'origin' parameter, the default type
500 // will be used (user command).
502
503 // Parse arguments to see if the 'max-period' or 'origin' parameters have
504 // been specified.
505 if (args) {
506 // Arguments must be a map.
507 if (args->getType() != Element::map) {
508 message << "arguments for the 'dhcp-disable' command must be a map";
509
510 } else {
511 ConstElementPtr max_period_element = args->get("max-period");
512 // max-period is optional.
513 if (max_period_element) {
514 // It must be an integer, if specified.
515 if (max_period_element->getType() != Element::integer) {
516 message << "'max-period' argument must be a number";
517
518 } else {
519 // It must be positive integer.
520 max_period = max_period_element->intValue();
521 if (max_period <= 0) {
522 message << "'max-period' must be positive integer";
523 }
524 }
525 }
526 ConstElementPtr origin_element = args->get("origin");
527 // The 'origin' parameter is optional.
528 if (origin_element) {
529 // It must be a string, if specified.
530 if (origin_element->getType() != Element::string) {
531 message << "'origin' argument must be a string";
532
533 } else {
534 origin = origin_element->stringValue();
535 if (origin == "ha-partner") {
537 } else if (origin != "user") {
538 if (origin.empty()) {
539 origin = "(empty string)";
540 }
541 message << "invalid value used for 'origin' parameter: "
542 << origin;
543 }
544 }
545 }
546 }
547 }
548
549 // No error occurred, so let's disable the service.
550 if (message.tellp() == 0) {
551 message << "DHCPv4 service disabled";
552 if (max_period > 0) {
553 message << " for " << max_period << " seconds";
554
555 // The user specified that the DHCP service should resume not
556 // later than in max-period seconds. If the 'dhcp-enable' command
557 // is not sent, the DHCP service will resume automatically.
558 network_state_->delayedEnableAll(static_cast<unsigned>(max_period),
559 type);
560 }
561 network_state_->disableService(type);
562
563 // Success.
564 return (config::createAnswer(CONTROL_RESULT_SUCCESS, message.str()));
565 }
566
567 // Failure.
568 return (config::createAnswer(CONTROL_RESULT_ERROR, message.str()));
569}
570
572ControlledDhcpv4Srv::commandDhcpEnableHandler(const std::string&,
573 ConstElementPtr args) {
574 std::ostringstream message;
575 std::string origin;
576
577 // If the args map does not contain 'origin' parameter, the default type
578 // will be used (user command).
580
581 // Parse arguments to see if the 'origin' parameter has been specified.
582 if (args) {
583 // Arguments must be a map.
584 if (args->getType() != Element::map) {
585 message << "arguments for the 'dhcp-enable' command must be a map";
586
587 } else {
588 ConstElementPtr origin_element = args->get("origin");
589 // The 'origin' parameter is optional.
590 if (origin_element) {
591 // It must be a string, if specified.
592 if (origin_element->getType() != Element::string) {
593 message << "'origin' argument must be a string";
594
595 } else {
596 origin = origin_element->stringValue();
597 if (origin == "ha-partner") {
599 } else if (origin != "user") {
600 if (origin.empty()) {
601 origin = "(empty string)";
602 }
603 message << "invalid value used for 'origin' parameter: "
604 << origin;
605 }
606 }
607 }
608 }
609 }
610
611 // No error occurred, so let's enable the service.
612 if (message.tellp() == 0) {
613 network_state_->enableService(type);
614
615 // Success.
617 "DHCP service successfully enabled"));
618 }
619
620 // Failure.
621 return (config::createAnswer(CONTROL_RESULT_ERROR, message.str()));
622}
623
625ControlledDhcpv4Srv::commandVersionGetHandler(const string&, ConstElementPtr) {
626 ElementPtr extended = Element::create(Dhcpv4Srv::getVersion(true));
627 ElementPtr arguments = Element::createMap();
628 arguments->set("extended", extended);
631 arguments);
632 return (answer);
633}
634
636ControlledDhcpv4Srv::commandBuildReportHandler(const string&,
638 ConstElementPtr answer =
640 return (answer);
641}
642
644ControlledDhcpv4Srv::commandLeasesReclaimHandler(const string&,
645 ConstElementPtr args) {
646 int status_code = CONTROL_RESULT_ERROR;
647 string message;
648
649 // args must be { "remove": <bool> }
650 if (!args) {
651 message = "Missing mandatory 'remove' parameter.";
652 } else {
653 ConstElementPtr remove_name = args->get("remove");
654 if (!remove_name) {
655 message = "Missing mandatory 'remove' parameter.";
656 } else if (remove_name->getType() != Element::boolean) {
657 message = "'remove' parameter expected to be a boolean.";
658 } else {
659 bool remove_lease = remove_name->boolValue();
660 server_->alloc_engine_->reclaimExpiredLeases4(0, 0, remove_lease);
661 status_code = 0;
662 message = "Reclamation of expired leases is complete.";
663 }
664 }
665 ConstElementPtr answer = isc::config::createAnswer(status_code, message);
666 return (answer);
667}
668
670ControlledDhcpv4Srv::commandServerTagGetHandler(const std::string&,
672 const std::string& tag =
673 CfgMgr::instance().getCurrentCfg()->getServerTag();
674 ElementPtr response = Element::createMap();
675 response->set("server-tag", Element::create(tag));
676
677 return (createAnswer(CONTROL_RESULT_SUCCESS, response));
678}
679
681ControlledDhcpv4Srv::commandConfigBackendPullHandler(const std::string&,
683 auto ctl_info = CfgMgr::instance().getCurrentCfg()->getConfigControlInfo();
684 if (!ctl_info) {
685 return (createAnswer(CONTROL_RESULT_EMPTY, "No config backend."));
686 }
687
688 // stop thread pool (if running)
690
691 // Reschedule the periodic CB fetch.
692 if (TimerMgr::instance()->isTimerRegistered("Dhcp4CBFetchTimer")) {
693 TimerMgr::instance()->cancel("Dhcp4CBFetchTimer");
694 TimerMgr::instance()->setup("Dhcp4CBFetchTimer");
695 }
696
697 // Code from cbFetchUpdates.
698 // The configuration to use is the current one because this is called
699 // after the configuration manager commit.
700 try {
701 auto srv_cfg = CfgMgr::instance().getCurrentCfg();
702 auto mode = CBControlDHCPv4::FetchMode::FETCH_UPDATE;
703 server_->getCBControl()->databaseConfigFetch(srv_cfg, mode);
704 } catch (const std::exception& ex) {
706 .arg(ex.what());
708 "On demand configuration update failed: " +
709 string(ex.what())));
710 }
712 "On demand configuration update successful."));
713}
714
716ControlledDhcpv4Srv::commandStatusGetHandler(const string&,
717 ConstElementPtr /*args*/) {
718 ElementPtr status = Element::createMap();
719 status->set("pid", Element::create(static_cast<int>(getpid())));
720
721 auto now = boost::posix_time::second_clock::universal_time();
722 // Sanity check: start_ is always initialized.
723 if (!start_.is_not_a_date_time()) {
724 auto uptime = now - start_;
725 status->set("uptime", Element::create(uptime.total_seconds()));
726 }
727
728 auto last_commit = CfgMgr::instance().getCurrentCfg()->getLastCommitTime();
729 if (!last_commit.is_not_a_date_time()) {
730 auto reload = now - last_commit;
731 status->set("reload", Element::create(reload.total_seconds()));
732 }
733
734 auto& mt_mgr = MultiThreadingMgr::instance();
735 if (mt_mgr.getMode()) {
736 status->set("multi-threading-enabled", Element::create(true));
737 status->set("thread-pool-size", Element::create(static_cast<int32_t>(
738 MultiThreadingMgr::instance().getThreadPoolSize())));
739 status->set("packet-queue-size", Element::create(static_cast<int32_t>(
740 MultiThreadingMgr::instance().getPacketQueueSize())));
741 ElementPtr queue_stats = Element::createList();
742 queue_stats->add(Element::create(mt_mgr.getThreadPool().getQueueStat(10)));
743 queue_stats->add(Element::create(mt_mgr.getThreadPool().getQueueStat(100)));
744 queue_stats->add(Element::create(mt_mgr.getThreadPool().getQueueStat(1000)));
745 status->set("packet-queue-statistics", queue_stats);
746
747 } else {
748 status->set("multi-threading-enabled", Element::create(false));
749 }
750
751 return (createAnswer(0, status));
752}
753
755ControlledDhcpv4Srv::commandStatisticSetMaxSampleCountAllHandler(const string&,
756 ConstElementPtr args) {
757 StatsMgr& stats_mgr = StatsMgr::instance();
759 // Update the default parameter.
760 long max_samples = stats_mgr.getMaxSampleCountDefault();
761 CfgMgr::instance().getCurrentCfg()->addConfiguredGlobal(
762 "statistic-default-sample-count", Element::create(max_samples));
763 return (answer);
764}
765
767ControlledDhcpv4Srv::commandStatisticSetMaxSampleAgeAllHandler(const string&,
768 ConstElementPtr args) {
769 StatsMgr& stats_mgr = StatsMgr::instance();
771 // Update the default parameter.
772 auto duration = stats_mgr.getMaxSampleAgeDefault();
773 long max_age = toSeconds(duration);
774 CfgMgr::instance().getCurrentCfg()->addConfiguredGlobal(
775 "statistic-default-sample-age", Element::create(max_age));
776 return (answer);
777}
778
781 ConstElementPtr args) {
782 string txt = args ? args->str() : "(none)";
783
785 .arg(command).arg(txt);
786
788
789 if (!srv) {
791 "Server object not initialized, so can't process command '" +
792 command + "', arguments: '" + txt + "'.");
793 return (no_srv);
794 }
795
796 try {
797 if (command == "shutdown") {
798 return (srv->commandShutdownHandler(command, args));
799
800 } else if (command == "libreload") {
801 return (srv->commandLibReloadHandler(command, args));
802
803 } else if (command == "config-reload") {
804 return (srv->commandConfigReloadHandler(command, args));
805
806 } else if (command == "config-set") {
807 return (srv->commandConfigSetHandler(command, args));
808
809 } else if (command == "config-get") {
810 return (srv->commandConfigGetHandler(command, args));
811
812 } else if (command == "config-test") {
813 return (srv->commandConfigTestHandler(command, args));
814
815 } else if (command == "dhcp-disable") {
816 return (srv->commandDhcpDisableHandler(command, args));
817
818 } else if (command == "dhcp-enable") {
819 return (srv->commandDhcpEnableHandler(command, args));
820
821 } else if (command == "version-get") {
822 return (srv->commandVersionGetHandler(command, args));
823
824 } else if (command == "build-report") {
825 return (srv->commandBuildReportHandler(command, args));
826
827 } else if (command == "leases-reclaim") {
828 return (srv->commandLeasesReclaimHandler(command, args));
829
830 } else if (command == "config-write") {
831 return (srv->commandConfigWriteHandler(command, args));
832
833 } else if (command == "server-tag-get") {
834 return (srv->commandServerTagGetHandler(command, args));
835
836 } else if (command == "config-backend-pull") {
837 return (srv->commandConfigBackendPullHandler(command, args));
838
839 } else if (command == "status-get") {
840 return (srv->commandStatusGetHandler(command, args));
841 }
842
843 return (isc::config::createAnswer(1, "Unrecognized command:"
844 + command));
845
846 } catch (const isc::Exception& ex) {
847 return (isc::config::createAnswer(1, "Error while processing command '"
848 + command + "':" + ex.what() +
849 ", params: '" + txt + "'"));
850 }
851}
852
856
857 // Single stream instance used in all error clauses
858 std::ostringstream err;
859
860 if (!srv) {
861 err << "Server object not initialized, can't process config.";
862 return (isc::config::createAnswer(1, err.str()));
863 }
864
866 .arg(srv->redactConfig(config)->str());
867
868 ConstElementPtr answer = configureDhcp4Server(*srv, config);
869
870 // Check that configuration was successful. If not, do not reopen sockets
871 // and don't bother with DDNS stuff.
872 try {
873 int rcode = 0;
874 isc::config::parseAnswer(rcode, answer);
875 if (rcode != 0) {
876 return (answer);
877 }
878 } catch (const std::exception& ex) {
879 err << "Failed to process configuration:" << ex.what();
880 return (isc::config::createAnswer(1, err.str()));
881 }
882
883 // Re-open lease and host database with new parameters.
884 try {
886 std::bind(&ControlledDhcpv4Srv::dbLostCallback, srv, ph::_1);
887
889 std::bind(&ControlledDhcpv4Srv::dbRecoveredCallback, srv, ph::_1);
890
892 std::bind(&ControlledDhcpv4Srv::dbFailedCallback, srv, ph::_1);
893
894 CfgDbAccessPtr cfg_db = CfgMgr::instance().getStagingCfg()->getCfgDbAccess();
895 cfg_db->setAppendedParameters("universe=4");
896 cfg_db->createManagers();
897 // Reset counters related to connections as all managers have been recreated.
899 } catch (const std::exception& ex) {
900 err << "Unable to open database: " << ex.what();
901 return (isc::config::createAnswer(1, err.str()));
902 }
903
904 // Server will start DDNS communications if its enabled.
905 try {
906 srv->startD2();
907 } catch (const std::exception& ex) {
908 err << "Error starting DHCP_DDNS client after server reconfiguration: "
909 << ex.what();
910 return (isc::config::createAnswer(1, err.str()));
911 }
912
913 // Setup DHCPv4-over-DHCPv6 IPC
914 try {
916 } catch (const std::exception& ex) {
917 std::ostringstream err;
918 err << "error starting DHCPv4-over-DHCPv6 IPC "
919 " after server reconfiguration: " << ex.what();
920 return (isc::config::createAnswer(1, err.str()));
921 }
922
923 // Configure DHCP packet queueing
924 try {
926 qc = CfgMgr::instance().getStagingCfg()->getDHCPQueueControl();
927 if (IfaceMgr::instance().configureDHCPPacketQueue(AF_INET, qc)) {
929 .arg(IfaceMgr::instance().getPacketQueue4()->getInfoStr());
930 }
931
932 } catch (const std::exception& ex) {
933 err << "Error setting packet queue controls after server reconfiguration: "
934 << ex.what();
935 return (isc::config::createAnswer(1, err.str()));
936 }
937
938 // Configuration may change active interfaces. Therefore, we have to reopen
939 // sockets according to new configuration. It is possible that this
940 // operation will fail for some interfaces but the openSockets function
941 // guards against exceptions and invokes a callback function to
942 // log warnings. Since we allow that this fails for some interfaces there
943 // is no need to rollback configuration if socket fails to open on any
944 // of the interfaces.
945 CfgMgr::instance().getStagingCfg()->getCfgIface()->
946 openSockets(AF_INET, srv->getServerPort(),
948
949 // Install the timers for handling leases reclamation.
950 try {
951 CfgMgr::instance().getStagingCfg()->getCfgExpiration()->
952 setupTimers(&ControlledDhcpv4Srv::reclaimExpiredLeases,
953 &ControlledDhcpv4Srv::deleteExpiredReclaimedLeases,
954 server_);
955
956 } catch (const std::exception& ex) {
957 err << "unable to setup timers for periodically running the"
958 " reclamation of the expired leases: "
959 << ex.what() << ".";
960 return (isc::config::createAnswer(1, err.str()));
961 }
962
963 // Setup config backend polling, if configured for it.
964 auto ctl_info = CfgMgr::instance().getStagingCfg()->getConfigControlInfo();
965 if (ctl_info) {
966 long fetch_time = static_cast<long>(ctl_info->getConfigFetchWaitTime());
967 // Only schedule the CB fetch timer if the fetch wait time is greater
968 // than 0.
969 if (fetch_time > 0) {
970 // When we run unit tests, we want to use milliseconds unit for the
971 // specified interval. Otherwise, we use seconds. Note that using
972 // milliseconds as a unit in unit tests prevents us from waiting 1
973 // second on more before the timer goes off. Instead, we wait one
974 // millisecond which significantly reduces the test time.
975 if (!server_->inTestMode()) {
976 fetch_time = 1000 * fetch_time;
977 }
978
979 boost::shared_ptr<unsigned> failure_count(new unsigned(0));
981 registerTimer("Dhcp4CBFetchTimer",
982 std::bind(&ControlledDhcpv4Srv::cbFetchUpdates,
983 server_, CfgMgr::instance().getStagingCfg(),
984 failure_count),
985 fetch_time,
987 TimerMgr::instance()->setup("Dhcp4CBFetchTimer");
988 }
989 }
990
991 // Finally, we can commit runtime option definitions in libdhcp++. This is
992 // exception free.
994
995 // This hook point notifies hooks libraries that the configuration of the
996 // DHCPv4 server has completed. It provides the hook library with the pointer
997 // to the common IO service object, new server configuration in the JSON
998 // format and with the pointer to the configuration storage where the
999 // parsed configuration is stored.
1000 if (HooksManager::calloutsPresent(Hooks.hooks_index_dhcp4_srv_configured_)) {
1001 CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
1002
1003 callout_handle->setArgument("io_context", srv->getIOService());
1004 callout_handle->setArgument("network_state", srv->getNetworkState());
1005 callout_handle->setArgument("json_config", config);
1006 callout_handle->setArgument("server_config", CfgMgr::instance().getStagingCfg());
1007
1008 HooksManager::callCallouts(Hooks.hooks_index_dhcp4_srv_configured_,
1009 *callout_handle);
1010
1011 // Ignore status code as none of them would have an effect on further
1012 // operation.
1013 }
1014
1015 // Apply multi threading settings.
1016 // @note These settings are applied/updated only if no errors occur while
1017 // applying the new configuration.
1018 // @todo This should be fixed.
1019 try {
1020 CfgMultiThreading::apply(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading());
1021 } catch (const std::exception& ex) {
1022 err << "Error applying multi threading settings: "
1023 << ex.what();
1025 }
1026
1027 return (answer);
1028}
1029
1032
1034 .arg(redactConfig(config)->str());
1035
1037
1038 // Single stream instance used in all error clauses
1039 std::ostringstream err;
1040
1041 if (!srv) {
1042 err << "Server object not initialized, can't process config.";
1043 return (isc::config::createAnswer(1, err.str()));
1044 }
1045
1046 return (configureDhcp4Server(*srv, config, true));
1047}
1048
1049ControlledDhcpv4Srv::ControlledDhcpv4Srv(uint16_t server_port /*= DHCP4_SERVER_PORT*/,
1050 uint16_t client_port /*= 0*/)
1051 : Dhcpv4Srv(server_port, client_port), timer_mgr_(TimerMgr::instance()) {
1052 if (getInstance()) {
1054 "There is another Dhcpv4Srv instance already.");
1055 }
1056 server_ = this; // remember this instance for later use in handlers
1057
1058 // TimerMgr uses IO service to run asynchronous timers.
1059 TimerMgr::instance()->setIOService(getIOService());
1060
1061 // CommandMgr uses IO service to run asynchronous socket operations.
1062 CommandMgr::instance().setIOService(getIOService());
1063
1064 // LeaseMgr uses IO service to run asynchronous timers.
1066
1067 // HostMgr uses IO service to run asynchronous timers.
1069
1070 // These are the commands always supported by the DHCPv4 server.
1071 // Please keep the list in alphabetic order.
1072 CommandMgr::instance().registerCommand("build-report",
1073 std::bind(&ControlledDhcpv4Srv::commandBuildReportHandler, this, ph::_1, ph::_2));
1074
1075 CommandMgr::instance().registerCommand("config-backend-pull",
1076 std::bind(&ControlledDhcpv4Srv::commandConfigBackendPullHandler, this, ph::_1, ph::_2));
1077
1078 CommandMgr::instance().registerCommand("config-get",
1079 std::bind(&ControlledDhcpv4Srv::commandConfigGetHandler, this, ph::_1, ph::_2));
1080
1081 CommandMgr::instance().registerCommand("config-reload",
1082 std::bind(&ControlledDhcpv4Srv::commandConfigReloadHandler, this, ph::_1, ph::_2));
1083
1084 CommandMgr::instance().registerCommand("config-set",
1085 std::bind(&ControlledDhcpv4Srv::commandConfigSetHandler, this, ph::_1, ph::_2));
1086
1087 CommandMgr::instance().registerCommand("config-test",
1088 std::bind(&ControlledDhcpv4Srv::commandConfigTestHandler, this, ph::_1, ph::_2));
1089
1090 CommandMgr::instance().registerCommand("config-write",
1091 std::bind(&ControlledDhcpv4Srv::commandConfigWriteHandler, this, ph::_1, ph::_2));
1092
1093 CommandMgr::instance().registerCommand("dhcp-enable",
1094 std::bind(&ControlledDhcpv4Srv::commandDhcpEnableHandler, this, ph::_1, ph::_2));
1095
1096 CommandMgr::instance().registerCommand("dhcp-disable",
1097 std::bind(&ControlledDhcpv4Srv::commandDhcpDisableHandler, this, ph::_1, ph::_2));
1098
1099 CommandMgr::instance().registerCommand("libreload",
1100 std::bind(&ControlledDhcpv4Srv::commandLibReloadHandler, this, ph::_1, ph::_2));
1101
1102 CommandMgr::instance().registerCommand("leases-reclaim",
1103 std::bind(&ControlledDhcpv4Srv::commandLeasesReclaimHandler, this, ph::_1, ph::_2));
1104
1105 CommandMgr::instance().registerCommand("server-tag-get",
1106 std::bind(&ControlledDhcpv4Srv::commandServerTagGetHandler, this, ph::_1, ph::_2));
1107
1108 CommandMgr::instance().registerCommand("shutdown",
1109 std::bind(&ControlledDhcpv4Srv::commandShutdownHandler, this, ph::_1, ph::_2));
1110
1111 CommandMgr::instance().registerCommand("status-get",
1112 std::bind(&ControlledDhcpv4Srv::commandStatusGetHandler, this, ph::_1, ph::_2));
1113
1114 CommandMgr::instance().registerCommand("version-get",
1115 std::bind(&ControlledDhcpv4Srv::commandVersionGetHandler, this, ph::_1, ph::_2));
1116
1117 // Register statistic related commands
1118 CommandMgr::instance().registerCommand("statistic-get",
1119 std::bind(&StatsMgr::statisticGetHandler, ph::_1, ph::_2));
1120
1121 CommandMgr::instance().registerCommand("statistic-reset",
1122 std::bind(&StatsMgr::statisticResetHandler, ph::_1, ph::_2));
1123
1124 CommandMgr::instance().registerCommand("statistic-remove",
1125 std::bind(&StatsMgr::statisticRemoveHandler, ph::_1, ph::_2));
1126
1127 CommandMgr::instance().registerCommand("statistic-get-all",
1128 std::bind(&StatsMgr::statisticGetAllHandler, ph::_1, ph::_2));
1129
1130 CommandMgr::instance().registerCommand("statistic-reset-all",
1131 std::bind(&StatsMgr::statisticResetAllHandler, ph::_1, ph::_2));
1132
1133 CommandMgr::instance().registerCommand("statistic-remove-all",
1134 std::bind(&StatsMgr::statisticRemoveAllHandler, ph::_1, ph::_2));
1135
1136 CommandMgr::instance().registerCommand("statistic-sample-age-set",
1137 std::bind(&StatsMgr::statisticSetMaxSampleAgeHandler, ph::_1, ph::_2));
1138
1139 CommandMgr::instance().registerCommand("statistic-sample-age-set-all",
1140 std::bind(&ControlledDhcpv4Srv::commandStatisticSetMaxSampleAgeAllHandler, this, ph::_1, ph::_2));
1141
1142 CommandMgr::instance().registerCommand("statistic-sample-count-set",
1143 std::bind(&StatsMgr::statisticSetMaxSampleCountHandler, ph::_1, ph::_2));
1144
1145 CommandMgr::instance().registerCommand("statistic-sample-count-set-all",
1146 std::bind(&ControlledDhcpv4Srv::commandStatisticSetMaxSampleCountAllHandler, this, ph::_1, ph::_2));
1147}
1148
1150 setExitValue(exit_value);
1151 getIOService()->stop(); // Stop ASIO transmissions
1152 shutdown(); // Initiate DHCPv4 shutdown procedure.
1153}
1154
1156 try {
1159 cleanup();
1160
1161 // The closure captures either a shared pointer (memory leak)
1162 // or a raw pointer (pointing to a deleted object).
1166
1167 timer_mgr_->unregisterTimers();
1168
1169 // Close the command socket (if it exists).
1170 CommandMgr::instance().closeCommandSocket();
1171
1172 // Deregister any registered commands (please keep in alphabetic order)
1173 CommandMgr::instance().deregisterCommand("build-report");
1174 CommandMgr::instance().deregisterCommand("config-backend-pull");
1175 CommandMgr::instance().deregisterCommand("config-get");
1176 CommandMgr::instance().deregisterCommand("config-reload");
1177 CommandMgr::instance().deregisterCommand("config-set");
1178 CommandMgr::instance().deregisterCommand("config-test");
1179 CommandMgr::instance().deregisterCommand("config-write");
1180 CommandMgr::instance().deregisterCommand("dhcp-disable");
1181 CommandMgr::instance().deregisterCommand("dhcp-enable");
1182 CommandMgr::instance().deregisterCommand("leases-reclaim");
1183 CommandMgr::instance().deregisterCommand("libreload");
1184 CommandMgr::instance().deregisterCommand("server-tag-get");
1185 CommandMgr::instance().deregisterCommand("shutdown");
1186 CommandMgr::instance().deregisterCommand("statistic-get");
1187 CommandMgr::instance().deregisterCommand("statistic-get-all");
1188 CommandMgr::instance().deregisterCommand("statistic-remove");
1189 CommandMgr::instance().deregisterCommand("statistic-remove-all");
1190 CommandMgr::instance().deregisterCommand("statistic-reset");
1191 CommandMgr::instance().deregisterCommand("statistic-reset-all");
1192 CommandMgr::instance().deregisterCommand("statistic-sample-age-set");
1193 CommandMgr::instance().deregisterCommand("statistic-sample-age-set-all");
1194 CommandMgr::instance().deregisterCommand("statistic-sample-count-set");
1195 CommandMgr::instance().deregisterCommand("statistic-sample-count-set-all");
1196 CommandMgr::instance().deregisterCommand("status-get");
1197 CommandMgr::instance().deregisterCommand("version-get");
1198
1199 // LeaseMgr uses IO service to run asynchronous timers.
1201
1202 // HostMgr uses IO service to run asynchronous timers.
1204 } catch (...) {
1205 // Don't want to throw exceptions from the destructor. The server
1206 // is shutting down anyway.
1207 ;
1208 }
1209
1210 server_ = NULL; // forget this instance. There should be no callback anymore
1211 // at this stage anyway.
1212}
1213
1214void
1215ControlledDhcpv4Srv::reclaimExpiredLeases(const size_t max_leases,
1216 const uint16_t timeout,
1217 const bool remove_lease,
1218 const uint16_t max_unwarned_cycles) {
1219 try {
1220 server_->alloc_engine_->reclaimExpiredLeases4(max_leases, timeout,
1221 remove_lease,
1222 max_unwarned_cycles);
1223 } catch (const std::exception& ex) {
1225 .arg(ex.what());
1226 }
1227 // We're using the ONE_SHOT timer so there is a need to re-schedule it.
1229}
1230
1231void
1232ControlledDhcpv4Srv::deleteExpiredReclaimedLeases(const uint32_t secs) {
1233 server_->alloc_engine_->deleteExpiredReclaimedLeases4(secs);
1234 // We're using the ONE_SHOT timer so there is a need to re-schedule it.
1236}
1237
1238bool
1239ControlledDhcpv4Srv::dbLostCallback(ReconnectCtlPtr db_reconnect_ctl) {
1240 if (!db_reconnect_ctl) {
1241 // This should never happen
1243 return (false);
1244 }
1245
1246 // Disable service until the connection is recovered.
1247 if (db_reconnect_ctl->retriesLeft() == db_reconnect_ctl->maxRetries() &&
1248 db_reconnect_ctl->alterServiceState()) {
1250 }
1251
1253
1254 // If reconnect isn't enabled log it, initiate a shutdown if needed and
1255 // return false.
1256 if (!db_reconnect_ctl->retriesLeft() ||
1257 !db_reconnect_ctl->retryInterval()) {
1259 .arg(db_reconnect_ctl->retriesLeft())
1260 .arg(db_reconnect_ctl->retryInterval());
1261 if (db_reconnect_ctl->exitOnFailure()) {
1262 shutdownServer(EXIT_FAILURE);
1263 }
1264 return (false);
1265 }
1266
1267 return (true);
1268}
1269
1270bool
1271ControlledDhcpv4Srv::dbRecoveredCallback(ReconnectCtlPtr db_reconnect_ctl) {
1272 if (!db_reconnect_ctl) {
1273 // This should never happen
1275 return (false);
1276 }
1277
1278 // Enable service after the connection is recovered.
1279 if (db_reconnect_ctl->alterServiceState()) {
1281 }
1282
1284
1285 db_reconnect_ctl->resetRetries();
1286
1287 return (true);
1288}
1289
1290bool
1291ControlledDhcpv4Srv::dbFailedCallback(ReconnectCtlPtr db_reconnect_ctl) {
1292 if (!db_reconnect_ctl) {
1293 // This should never happen
1295 return (false);
1296 }
1297
1299 .arg(db_reconnect_ctl->maxRetries());
1300
1301 if (db_reconnect_ctl->exitOnFailure()) {
1302 shutdownServer(EXIT_FAILURE);
1303 }
1304
1305 return (true);
1306}
1307
1308void
1309ControlledDhcpv4Srv::cbFetchUpdates(const SrvConfigPtr& srv_cfg,
1310 boost::shared_ptr<unsigned> failure_count) {
1311 // stop thread pool (if running)
1313
1314 try {
1315 // Fetch any configuration backend updates since our last fetch.
1316 server_->getCBControl()->databaseConfigFetch(srv_cfg,
1317 CBControlDHCPv4::FetchMode::FETCH_UPDATE);
1318 (*failure_count) = 0;
1319
1320 } catch (const std::exception& ex) {
1322 .arg(ex.what());
1323
1324 // We allow at most 10 consecutive failures after which we stop
1325 // making further attempts to fetch the configuration updates.
1326 // Let's return without re-scheduling the timer.
1327 if (++(*failure_count) > 10) {
1330 return;
1331 }
1332 }
1333
1334 // Reschedule the timer to fetch new updates or re-try if
1335 // the previous attempt resulted in an error.
1336 if (TimerMgr::instance()->isTimerRegistered("Dhcp4CBFetchTimer")) {
1337 TimerMgr::instance()->setup("Dhcp4CBFetchTimer");
1338 }
1339}
1340
1341} // namespace dhcp
1342} // namespace isc
CtrlAgentHooks Hooks
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
static DbCallback db_recovered_callback_
Optional callback function to invoke if an opened connection recovery succeeded.
static DbCallback db_failed_callback_
Optional callback function to invoke if an opened connection recovery failed.
static DbCallback db_lost_callback_
Optional callback function to invoke if an opened connection is lost.
static const std::string FLUSH_RECLAIMED_TIMER_NAME
Name of the timer for flushing reclaimed leases.
static const std::string RECLAIM_EXPIRED_TIMER_NAME
Name of the timer for reclaiming expired leases.
void rollback()
Removes staging configuration.
Definition: cfgmgr.cc:120
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
void commit()
Commits the staging configuration.
Definition: cfgmgr.cc:90
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition: cfgmgr.cc:161
static void apply(data::ConstElementPtr value)
apply multi threading configuration
Controlled version of the DHCPv4 server.
static isc::data::ConstElementPtr processConfig(isc::data::ConstElementPtr new_config)
Configuration processor.
virtual ~ControlledDhcpv4Srv()
Destructor.
isc::data::ConstElementPtr loadConfigFile(const std::string &file_name)
Configure DHCPv4 server using the configuration file specified.
void cleanup()
Performs cleanup, immediately before termination.
static isc::data::ConstElementPtr processCommand(const std::string &command, isc::data::ConstElementPtr args)
Command processor.
ControlledDhcpv4Srv(uint16_t server_port=DHCP4_SERVER_PORT, uint16_t client_port=0)
Constructor.
void init(const std::string &config_file)
Initializes the server.
static ControlledDhcpv4Srv * getInstance()
Returns pointer to the sole instance of Dhcpv4Srv.
void shutdownServer(int exit_value)
Initiates shutdown procedure for the whole DHCPv4 server.
isc::data::ConstElementPtr checkConfig(isc::data::ConstElementPtr new_config)
Configuration checker.
static Dhcp4to6Ipc & instance()
Returns pointer to the sole instance of Dhcp4to6Ipc.
Definition: dhcp4to6_ipc.cc:32
virtual void open()
Open communication socket.
Definition: dhcp4to6_ipc.cc:37
DHCPv4 server service.
Definition: dhcp4_srv.h:241
void startD2()
Starts DHCP_DDNS client IO if DDNS updates are enabled.
Definition: dhcp4_srv.cc:3952
void shutdown() override
Instructs the server to shut down.
Definition: dhcp4_srv.cc:713
asiolink::IOServicePtr & getIOService()
Returns pointer to the IO service used by the server.
Definition: dhcp4_srv.h:292
boost::shared_ptr< AllocEngine > alloc_engine_
Allocation Engine.
Definition: dhcp4_srv.h:1107
bool inTestMode() const
Checks if the server is running in unit test mode.
Definition: dhcp4_srv.h:287
NetworkStatePtr & getNetworkState()
Returns pointer to the network state used by the server.
Definition: dhcp4_srv.h:297
static std::string getVersion(bool extended)
returns Kea version on stdout and exit.
Definition: dhcp4_srv.cc:3988
bool useBroadcast() const
Return bool value indicating that broadcast flags should be set on sockets.
Definition: dhcp4_srv.h:407
NetworkStatePtr network_state_
Holds information about disabled DHCP service and/or disabled subnet/network scopes.
Definition: dhcp4_srv.h:1114
uint16_t getServerPort() const
Get UDP port on which server should listen.
Definition: dhcp4_srv.h:399
CBControlDHCPv4Ptr getCBControl() const
Returns an object which controls access to the configuration backends.
Definition: dhcp4_srv.h:306
static void setIOService(const isc::asiolink::IOServicePtr &io_service)
Sets IO service to be used by the Host Manager.
Definition: host_mgr.h:638
static void create()
Creates new instance of the HostMgr.
Definition: host_mgr.cc:43
static IfaceMgr & instance()
IfaceMgr is a singleton class.
Definition: iface_mgr.cc:53
static void destroy()
Destroy lease manager.
static void setIOService(const isc::asiolink::IOServicePtr &io_service)
Sets IO service to be used by the Lease Manager.
Definition: lease_mgr.h:753
static void commitRuntimeOptionDefs()
Commits runtime option definitions.
Definition: libdhcp++.cc:240
Origin
Origin of the network state transition.
Definition: network_state.h:84
@ USER_COMMAND
The network state is being altered by a user command.
@ DB_CONNECTION
The network state is being altered by the DB connection recovery mechanics.
@ HA_COMMAND
The network state is being altered by a HA internal command.
Evaluation context, an interface to the expression evaluation.
isc::data::ElementPtr parseFile(const std::string &filename, ParserType parser_type)
Run the parser on the file specified.
@ PARSER_DHCP4
This parser will parse the content as Dhcp4 config wrapped in a map (that's the regular config file)
Manages a pool of asynchronous interval timers.
Definition: timer_mgr.h:62
static const TimerMgrPtr & instance()
Returns pointer to the sole instance of the TimerMgr.
Definition: timer_mgr.cc:449
std::string getConfigFile() const
Returns config file name.
Definition: daemon.cc:105
virtual size_t writeConfigFile(const std::string &config_file, isc::data::ConstElementPtr cfg=isc::data::ConstElementPtr()) const
Writes current configuration to specified file.
Definition: daemon.cc:229
isc::asiolink::IOSignalSetPtr signal_set_
A pointer to the object installing custom signal handlers.
Definition: daemon.h:257
boost::posix_time::ptime start_
Timestamp of the start of the daemon.
Definition: daemon.h:263
void setExitValue(int value)
Sets the exit value.
Definition: daemon.h:227
isc::data::ConstElementPtr redactConfig(isc::data::ConstElementPtr const &config)
Redact a configuration.
Definition: daemon.cc:257
Statistics Manager class.
RAII class creating a critical section.
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.
Defines the Dhcp4o6Ipc class.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
isc::data::ConstElementPtr statisticSetMaxSampleCountAllHandler(const isc::data::ConstElementPtr &params)
Handles statistic-sample-count-set-all command.
isc::data::ConstElementPtr statisticSetMaxSampleAgeAllHandler(const isc::data::ConstElementPtr &params)
Handles statistic-sample-age-set-all command.
uint32_t getMaxSampleCountDefault() const
Get default count limit.
const StatsDuration & getMaxSampleAgeDefault() const
Get default duration limit.
#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_FATAL(LOGGER, MESSAGE)
Macro to conveniently test fatal output and log it.
Definition: macros.h:38
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
const int CONTROL_RESULT_EMPTY
Status code indicating that the specified command was completed correctly, but failed to produce any ...
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
ConstElementPtr createAnswer(const int status_code, const std::string &text, const ConstElementPtr &arg)
ConstElementPtr parseAnswer(int &rcode, const ConstElementPtr &msg)
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
boost::shared_ptr< ReconnectCtl > ReconnectCtlPtr
Pointer to an instance of ReconnectCtl.
std::string getConfigReport()
Definition: cfgrpt.cc:20
const isc::log::MessageID DHCP4_NOT_RUNNING
const isc::log::MessageID DHCP4_DYNAMIC_RECONFIGURATION_FAIL
const isc::log::MessageID DHCP4_CONFIG_RECEIVED
const isc::log::MessageID DHCP4_DYNAMIC_RECONFIGURATION_SUCCESS
boost::shared_ptr< CfgDbAccess > CfgDbAccessPtr
A pointer to the CfgDbAccess.
const isc::log::MessageID DHCP4_DB_RECONNECT_NO_DB_CTL
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_CB_PERIODIC_FETCH_UPDATES_RETRIES_EXHAUSTED
const isc::log::MessageID DHCP4_CONFIG_PACKET_QUEUE
boost::shared_ptr< SrvConfig > SrvConfigPtr
Non-const pointer to the SrvConfig.
Definition: srv_config.h:1044
const isc::log::MessageID DHCP4_CB_ON_DEMAND_FETCH_UPDATES_FAIL
const isc::log::MessageID DHCP4_CONFIG_LOAD_FAIL
const int DBG_DHCP4_COMMAND
Debug level used to log receiving commands.
Definition: dhcp4_log.h:30
const isc::log::MessageID DHCP4_HOOKS_LIBS_RELOAD_FAIL
const isc::log::MessageID DHCP4_DB_RECONNECT_DISABLED
const isc::log::MessageID DHCP4_CONFIG_UNRECOVERABLE_ERROR
const isc::log::MessageID DHCP4_DB_RECONNECT_SUCCEEDED
const isc::log::MessageID DHCP4_COMMAND_RECEIVED
const isc::log::MessageID DHCP4_MULTI_THREADING_INFO
isc::log::Logger dhcp4_logger(DHCP4_APP_LOGGER_NAME)
Base logger for DHCPv4 server.
Definition: dhcp4_log.h:90
const isc::log::MessageID DHCP4_DB_RECONNECT_FAILED
const isc::log::MessageID DHCP4_DYNAMIC_RECONFIGURATION
const isc::log::MessageID DHCP4_RECLAIM_EXPIRED_LEASES_FAIL
const isc::log::MessageID DHCP4_CONFIG_UNSUPPORTED_OBJECT
const isc::log::MessageID DHCP4_CB_PERIODIC_FETCH_UPDATES_FAIL
const isc::log::MessageID DHCP4_DB_RECONNECT_LOST_CONNECTION
std::vector< HookLibInfo > HookLibsCollection
A storage for information about hook libraries.
Definition: libinfo.h:31
boost::shared_ptr< CalloutHandle > CalloutHandlePtr
A shared pointer to a CalloutHandle object.
long toSeconds(const StatsDuration &dur)
Returns the number of seconds in a duration.
Definition: observation.h:45
Definition: edns.h:19
Defines the logger used by the top-level component of kea-lfc.