Kea: ctrl_dhcp4_srv.cc Source File

| Kea 2.2.0

ctrl_dhcp4_srv.cc
Go to the documentation of this file.
1// Copyright (C) 2014-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
9#include <cc/command_interpreter.h>
10#include <cc/data.h>
11#include <cfgrpt/config_report.h>
12#include <config/command_mgr.h>
13#include <dhcp/libdhcp++.h>
14#include <dhcp4/ctrl_dhcp4_srv.h>
15#include <dhcp4/dhcp4_log.h>
16#include <dhcp4/dhcp4to6_ipc.h>
17#include <dhcp4/json_config_parser.h>
18#include <dhcp4/parser_context.h>
19#include <dhcpsrv/cfg_db_access.h>
20#include <dhcpsrv/cfg_multi_threading.h>
21#include <dhcpsrv/cfgmgr.h>
22#include <dhcpsrv/db_type.h>
23#include <dhcpsrv/host_mgr.h>
24#include <dhcpsrv/lease_mgr_factory.h>
25#include <hooks/hooks.h>
26#include <hooks/hooks_manager.h>
27#include <stats/stats_mgr.h>
28#include <util/multi_threading_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",
77 ConstElementPtr());
78 } else if ((signo == SIGTERM) || (signo == SIGINT)) {
79 ControlledDhcpv4Srv::processCommand("shutdown",
80 ConstElementPtr());
81 }
82}
83
84}
85
86namespace isc {
87namespace dhcp {
88
89 ControlledDhcpv4Srv* 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
121 void ControlledDhcpv4Srv::cleanup() {
122 // Nothing to do here. No need to disconnect from anything.
123}
124
125 ConstElementPtr
126ControlledDhcpv4Srv::loadConfigFile(const std::string& file_name) {
127 // This is a configuration backend implementation that reads the
128 // configuration from a JSON file.
129
130 isc::data::ConstElementPtr json;
131 isc::data::ConstElementPtr result;
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.
181 CfgMgr::instance().rollback();
182
183 LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_LOAD_FAIL)
184 .arg(file_name).arg(ex.what());
185 isc_throw(isc::BadValue, "configuration error using file '"
186 << file_name << "': " << ex.what());
187 }
188
189 LOG_WARN(dhcp4_logger, DHCP4_MULTI_THREADING_INFO)
190 .arg(MultiThreadingMgr::instance().getMode() ? "yes" : "no")
191 .arg(MultiThreadingMgr::instance().getThreadPoolSize())
192 .arg(MultiThreadingMgr::instance().getPacketQueueSize());
193
194 return (result);
195}
196
197 ConstElementPtr
198ControlledDhcpv4Srv::commandShutdownHandler(const string&, ConstElementPtr args) {
199 if (!ControlledDhcpv4Srv::getInstance()) {
200 LOG_WARN(dhcp4_logger, DHCP4_NOT_RUNNING);
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) {
214 return (createAnswer(CONTROL_RESULT_ERROR,
215 "parameter 'exit-value' is not an integer"));
216 }
217
218 exit_value = param->intValue();
219 }
220 }
221
222 ControlledDhcpv4Srv::getInstance()->shutdownServer(exit_value);
223 return (createAnswer(CONTROL_RESULT_SUCCESS, "Shutting down."));
224}
225
226 ConstElementPtr
227ControlledDhcpv4Srv::commandLibReloadHandler(const string&, ConstElementPtr) {
228 // stop thread pool (if running)
229 MultiThreadingCriticalSection cs;
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) {
244 LOG_ERROR(dhcp4_logger, DHCP4_HOOKS_LIBS_RELOAD_FAIL);
245 ConstElementPtr answer = isc::config::createAnswer(1, ex.what());
246 return (answer);
247 }
248 ConstElementPtr answer = isc::config::createAnswer(0,
249 "Hooks libraries successfully reloaded.");
250 return (answer);
251}
252
253 ConstElementPtr
254ControlledDhcpv4Srv::commandConfigReloadHandler(const string&,
255 ConstElementPtr /*args*/) {
256 // Get configuration file name.
257 std::string file = ControlledDhcpv4Srv::getInstance()->getConfigFile();
258 try {
259 LOG_INFO(dhcp4_logger, DHCP4_DYNAMIC_RECONFIGURATION).arg(file);
260 auto result = loadConfigFile(file);
261 LOG_INFO(dhcp4_logger, DHCP4_DYNAMIC_RECONFIGURATION_SUCCESS).arg(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.
267 LOG_FATAL(dhcp4_logger, DHCP4_DYNAMIC_RECONFIGURATION_FAIL)
268 .arg(file);
269 return (createAnswer(CONTROL_RESULT_ERROR,
270 "Config reload failed: " + string(ex.what())));
271 }
272}
273
274 ConstElementPtr
275ControlledDhcpv4Srv::commandConfigGetHandler(const string&,
276 ConstElementPtr /*args*/) {
277 ConstElementPtr config = CfgMgr::instance().getCurrentCfg()->toElement();
278
279 return (createAnswer(0, config));
280}
281
282 ConstElementPtr
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) {
294 return (createAnswer(CONTROL_RESULT_ERROR,
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
335 ConstElementPtr
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") {
360 LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_UNSUPPORTED_OBJECT)
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)
382 MultiThreadingCriticalSection cs;
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.
392 CfgMgr::instance().rollback();
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.
416 CfgMgr::instance().commit();
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.
427 LOG_FATAL(dhcp4_logger, DHCP4_CONFIG_UNRECOVERABLE_ERROR);
428 }
429 }
430
431 return (result);
432}
433
434 ConstElementPtr
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") {
459 LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_UNSUPPORTED_OBJECT)
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)
481 MultiThreadingCriticalSection cs;
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.
486 CfgMgr::instance().rollback();
487
488 // Now we check the server proper.
489 return (checkConfig(dhcp4));
490}
491
492 ConstElementPtr
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).
501 NetworkState::Origin type = NetworkState::Origin::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") {
536 type = NetworkState::Origin::HA_COMMAND;
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
571 ConstElementPtr
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).
579 NetworkState::Origin type = NetworkState::Origin::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") {
598 type = NetworkState::Origin::HA_COMMAND;
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.
616 return (config::createAnswer(CONTROL_RESULT_SUCCESS,
617 "DHCP service successfully enabled"));
618 }
619
620 // Failure.
621 return (config::createAnswer(CONTROL_RESULT_ERROR, message.str()));
622}
623
624 ConstElementPtr
625ControlledDhcpv4Srv::commandVersionGetHandler(const string&, ConstElementPtr) {
626 ElementPtr extended = Element::create(Dhcpv4Srv::getVersion(true));
627 ElementPtr arguments = Element::createMap();
628 arguments->set("extended", extended);
629 ConstElementPtr answer = isc::config::createAnswer(0,
630 Dhcpv4Srv::getVersion(false),
631 arguments);
632 return (answer);
633}
634
635 ConstElementPtr
636ControlledDhcpv4Srv::commandBuildReportHandler(const string&,
637 ConstElementPtr) {
638 ConstElementPtr answer =
639 isc::config::createAnswer(0, isc::detail::getConfigReport());
640 return (answer);
641}
642
643 ConstElementPtr
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
669 ConstElementPtr
670ControlledDhcpv4Srv::commandServerTagGetHandler(const std::string&,
671 ConstElementPtr) {
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
680 ConstElementPtr
681ControlledDhcpv4Srv::commandConfigBackendPullHandler(const std::string&,
682 ConstElementPtr) {
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)
689 MultiThreadingCriticalSection cs;
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) {
705 LOG_ERROR(dhcp4_logger, DHCP4_CB_ON_DEMAND_FETCH_UPDATES_FAIL)
706 .arg(ex.what());
707 return (createAnswer(CONTROL_RESULT_ERROR,
708 "On demand configuration update failed: " +
709 string(ex.what())));
710 }
711 return (createAnswer(CONTROL_RESULT_SUCCESS,
712 "On demand configuration update successful."));
713}
714
715 ConstElementPtr
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 // Iterate through the interfaces and get all the errors.
752 ElementPtr socket_errors(Element::createList());
753 for (IfacePtr const& interface : IfaceMgr::instance().getIfaces()) {
754 for (std::string const& error : interface->getErrors()) {
755 socket_errors->add(Element::create(error));
756 }
757 }
758
759 // Abstract the information from all sockets into a single status.
760 ElementPtr sockets(Element::createMap());
761 if (socket_errors->empty()) {
762 sockets->set("status", Element::create("ready"));
763 } else {
764 ReconnectCtlPtr const reconnect_ctl(
765 CfgMgr::instance().getCurrentCfg()->getCfgIface()->getReconnectCtl());
766 if (reconnect_ctl && reconnect_ctl->retriesLeft()) {
767 sockets->set("status", Element::create("retrying"));
768 } else {
769 sockets->set("status", Element::create("failed"));
770 }
771 sockets->set("errors", socket_errors);
772 }
773 status->set("sockets", sockets);
774
775 return (createAnswer(0, status));
776}
777
778 ConstElementPtr
779ControlledDhcpv4Srv::commandStatisticSetMaxSampleCountAllHandler(const string&,
780 ConstElementPtr args) {
781 StatsMgr& stats_mgr = StatsMgr::instance();
782 ConstElementPtr answer = stats_mgr.statisticSetMaxSampleCountAllHandler(args);
783 // Update the default parameter.
784 long max_samples = stats_mgr.getMaxSampleCountDefault();
785 CfgMgr::instance().getCurrentCfg()->addConfiguredGlobal(
786 "statistic-default-sample-count", Element::create(max_samples));
787 return (answer);
788}
789
790 ConstElementPtr
791ControlledDhcpv4Srv::commandStatisticSetMaxSampleAgeAllHandler(const string&,
792 ConstElementPtr args) {
793 StatsMgr& stats_mgr = StatsMgr::instance();
794 ConstElementPtr answer = stats_mgr.statisticSetMaxSampleAgeAllHandler(args);
795 // Update the default parameter.
796 auto duration = stats_mgr.getMaxSampleAgeDefault();
797 long max_age = toSeconds(duration);
798 CfgMgr::instance().getCurrentCfg()->addConfiguredGlobal(
799 "statistic-default-sample-age", Element::create(max_age));
800 return (answer);
801}
802
803 ConstElementPtr
804ControlledDhcpv4Srv::processCommand(const string& command,
805 ConstElementPtr args) {
806 string txt = args ? args->str() : "(none)";
807
808 LOG_DEBUG(dhcp4_logger, DBG_DHCP4_COMMAND, DHCP4_COMMAND_RECEIVED)
809 .arg(command).arg(txt);
810
811 ControlledDhcpv4Srv* srv = ControlledDhcpv4Srv::getInstance();
812
813 if (!srv) {
814 ConstElementPtr no_srv = isc::config::createAnswer(1,
815 "Server object not initialized, so can't process command '" +
816 command + "', arguments: '" + txt + "'.");
817 return (no_srv);
818 }
819
820 try {
821 if (command == "shutdown") {
822 return (srv->commandShutdownHandler(command, args));
823
824 } else if (command == "libreload") {
825 return (srv->commandLibReloadHandler(command, args));
826
827 } else if (command == "config-reload") {
828 return (srv->commandConfigReloadHandler(command, args));
829
830 } else if (command == "config-set") {
831 return (srv->commandConfigSetHandler(command, args));
832
833 } else if (command == "config-get") {
834 return (srv->commandConfigGetHandler(command, args));
835
836 } else if (command == "config-test") {
837 return (srv->commandConfigTestHandler(command, args));
838
839 } else if (command == "dhcp-disable") {
840 return (srv->commandDhcpDisableHandler(command, args));
841
842 } else if (command == "dhcp-enable") {
843 return (srv->commandDhcpEnableHandler(command, args));
844
845 } else if (command == "version-get") {
846 return (srv->commandVersionGetHandler(command, args));
847
848 } else if (command == "build-report") {
849 return (srv->commandBuildReportHandler(command, args));
850
851 } else if (command == "leases-reclaim") {
852 return (srv->commandLeasesReclaimHandler(command, args));
853
854 } else if (command == "config-write") {
855 return (srv->commandConfigWriteHandler(command, args));
856
857 } else if (command == "server-tag-get") {
858 return (srv->commandServerTagGetHandler(command, args));
859
860 } else if (command == "config-backend-pull") {
861 return (srv->commandConfigBackendPullHandler(command, args));
862
863 } else if (command == "status-get") {
864 return (srv->commandStatusGetHandler(command, args));
865 }
866
867 return (isc::config::createAnswer(1, "Unrecognized command:"
868 + command));
869
870 } catch (const isc::Exception& ex) {
871 return (isc::config::createAnswer(1, "Error while processing command '"
872 + command + "':" + ex.what() +
873 ", params: '" + txt + "'"));
874 }
875}
876
877 isc::data::ConstElementPtr
878ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
879 ControlledDhcpv4Srv* srv = ControlledDhcpv4Srv::getInstance();
880
881 // Single stream instance used in all error clauses
882 std::ostringstream err;
883
884 if (!srv) {
885 err << "Server object not initialized, can't process config.";
886 return (isc::config::createAnswer(1, err.str()));
887 }
888
889 LOG_DEBUG(dhcp4_logger, DBG_DHCP4_COMMAND, DHCP4_CONFIG_RECEIVED)
890 .arg(srv->redactConfig(config)->str());
891
892 ConstElementPtr answer = configureDhcp4Server(*srv, config);
893
894 // Check that configuration was successful. If not, do not reopen sockets
895 // and don't bother with DDNS stuff.
896 try {
897 int rcode = 0;
898 isc::config::parseAnswer(rcode, answer);
899 if (rcode != 0) {
900 return (answer);
901 }
902 } catch (const std::exception& ex) {
903 err << "Failed to process configuration:" << ex.what();
904 return (isc::config::createAnswer(1, err.str()));
905 }
906
907 // Re-open lease and host database with new parameters.
908 try {
909 DatabaseConnection::db_lost_callback_ =
910 std::bind(&ControlledDhcpv4Srv::dbLostCallback, srv, ph::_1);
911
912 DatabaseConnection::db_recovered_callback_ =
913 std::bind(&ControlledDhcpv4Srv::dbRecoveredCallback, srv, ph::_1);
914
915 DatabaseConnection::db_failed_callback_ =
916 std::bind(&ControlledDhcpv4Srv::dbFailedCallback, srv, ph::_1);
917
918 CfgDbAccessPtr cfg_db = CfgMgr::instance().getStagingCfg()->getCfgDbAccess();
919 cfg_db->setAppendedParameters("universe=4");
920 cfg_db->createManagers();
921 // Reset counters related to connections as all managers have been recreated.
922 srv->getNetworkState()->reset(NetworkState::Origin::DB_CONNECTION);
923 } catch (const std::exception& ex) {
924 err << "Unable to open database: " << ex.what();
925 return (isc::config::createAnswer(1, err.str()));
926 }
927
928 // Server will start DDNS communications if its enabled.
929 try {
930 srv->startD2();
931 } catch (const std::exception& ex) {
932 err << "Error starting DHCP_DDNS client after server reconfiguration: "
933 << ex.what();
934 return (isc::config::createAnswer(1, err.str()));
935 }
936
937 // Setup DHCPv4-over-DHCPv6 IPC
938 try {
939 Dhcp4to6Ipc::instance().open();
940 } catch (const std::exception& ex) {
941 err << "error starting DHCPv4-over-DHCPv6 IPC "
942 " after server reconfiguration: " << ex.what();
943 return (isc::config::createAnswer(1, err.str()));
944 }
945
946 // Configure DHCP packet queueing
947 try {
948 data::ConstElementPtr qc;
949 qc = CfgMgr::instance().getStagingCfg()->getDHCPQueueControl();
950 if (IfaceMgr::instance().configureDHCPPacketQueue(AF_INET, qc)) {
951 LOG_INFO(dhcp4_logger, DHCP4_CONFIG_PACKET_QUEUE)
952 .arg(IfaceMgr::instance().getPacketQueue4()->getInfoStr());
953 }
954
955 } catch (const std::exception& ex) {
956 err << "Error setting packet queue controls after server reconfiguration: "
957 << ex.what();
958 return (isc::config::createAnswer(1, err.str()));
959 }
960
961 // Configure a callback to shut down the server when the bind socket
962 // attempts exceeded.
963 CfgIface::open_sockets_failed_callback_ =
964 std::bind(&ControlledDhcpv4Srv::openSocketsFailedCallback, srv, ph::_1);
965
966 // Configuration may change active interfaces. Therefore, we have to reopen
967 // sockets according to new configuration. It is possible that this
968 // operation will fail for some interfaces but the openSockets function
969 // guards against exceptions and invokes a callback function to
970 // log warnings. Since we allow that this fails for some interfaces there
971 // is no need to rollback configuration if socket fails to open on any
972 // of the interfaces.
973 CfgMgr::instance().getStagingCfg()->getCfgIface()->
974 openSockets(AF_INET, srv->getServerPort(),
975 getInstance()->useBroadcast());
976
977 // Install the timers for handling leases reclamation.
978 try {
979 CfgMgr::instance().getStagingCfg()->getCfgExpiration()->
980 setupTimers(&ControlledDhcpv4Srv::reclaimExpiredLeases,
981 &ControlledDhcpv4Srv::deleteExpiredReclaimedLeases,
982 server_);
983
984 } catch (const std::exception& ex) {
985 err << "unable to setup timers for periodically running the"
986 " reclamation of the expired leases: "
987 << ex.what() << ".";
988 return (isc::config::createAnswer(1, err.str()));
989 }
990
991 // Setup config backend polling, if configured for it.
992 auto ctl_info = CfgMgr::instance().getStagingCfg()->getConfigControlInfo();
993 if (ctl_info) {
994 long fetch_time = static_cast<long>(ctl_info->getConfigFetchWaitTime());
995 // Only schedule the CB fetch timer if the fetch wait time is greater
996 // than 0.
997 if (fetch_time > 0) {
998 // When we run unit tests, we want to use milliseconds unit for the
999 // specified interval. Otherwise, we use seconds. Note that using
1000 // milliseconds as a unit in unit tests prevents us from waiting 1
1001 // second on more before the timer goes off. Instead, we wait one
1002 // millisecond which significantly reduces the test time.
1003 if (!server_->inTestMode()) {
1004 fetch_time = 1000 * fetch_time;
1005 }
1006
1007 boost::shared_ptr<unsigned> failure_count(new unsigned(0));
1008 TimerMgr::instance()->
1009 registerTimer("Dhcp4CBFetchTimer",
1010 std::bind(&ControlledDhcpv4Srv::cbFetchUpdates,
1011 server_, CfgMgr::instance().getStagingCfg(),
1012 failure_count),
1013 fetch_time,
1014 asiolink::IntervalTimer::ONE_SHOT);
1015 TimerMgr::instance()->setup("Dhcp4CBFetchTimer");
1016 }
1017 }
1018
1019 // Finally, we can commit runtime option definitions in libdhcp++. This is
1020 // exception free.
1021 LibDHCP::commitRuntimeOptionDefs();
1022
1023 // This hook point notifies hooks libraries that the configuration of the
1024 // DHCPv4 server has completed. It provides the hook library with the pointer
1025 // to the common IO service object, new server configuration in the JSON
1026 // format and with the pointer to the configuration storage where the
1027 // parsed configuration is stored.
1028 if (HooksManager::calloutsPresent(Hooks.hooks_index_dhcp4_srv_configured_)) {
1029 CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
1030
1031 callout_handle->setArgument("io_context", srv->getIOService());
1032 callout_handle->setArgument("network_state", srv->getNetworkState());
1033 callout_handle->setArgument("json_config", config);
1034 callout_handle->setArgument("server_config", CfgMgr::instance().getStagingCfg());
1035
1036 HooksManager::callCallouts(Hooks.hooks_index_dhcp4_srv_configured_,
1037 *callout_handle);
1038
1039 // If next step is DROP, report a configuration error.
1040 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
1041 string error;
1042 try {
1043 callout_handle->getArgument("error", error);
1044 } catch (NoSuchArgument const& ex) {
1045 error = "unknown error";
1046 }
1047 return (isc::config::createAnswer(CONTROL_RESULT_ERROR, error));
1048 }
1049 }
1050
1051 // Apply multi threading settings.
1052 // @note These settings are applied/updated only if no errors occur while
1053 // applying the new configuration.
1054 // @todo This should be fixed.
1055 try {
1056 CfgMultiThreading::apply(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading());
1057 } catch (const std::exception& ex) {
1058 err << "Error applying multi threading settings: "
1059 << ex.what();
1060 return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
1061 }
1062
1063 return (answer);
1064}
1065
1066 isc::data::ConstElementPtr
1067ControlledDhcpv4Srv::checkConfig(isc::data::ConstElementPtr config) {
1068
1069 LOG_DEBUG(dhcp4_logger, DBG_DHCP4_COMMAND, DHCP4_CONFIG_RECEIVED)
1070 .arg(redactConfig(config)->str());
1071
1072 ControlledDhcpv4Srv* srv = ControlledDhcpv4Srv::getInstance();
1073
1074 // Single stream instance used in all error clauses
1075 std::ostringstream err;
1076
1077 if (!srv) {
1078 err << "Server object not initialized, can't process config.";
1079 return (isc::config::createAnswer(1, err.str()));
1080 }
1081
1082 return (configureDhcp4Server(*srv, config, true));
1083}
1084
1085ControlledDhcpv4Srv::ControlledDhcpv4Srv(uint16_t server_port /*= DHCP4_SERVER_PORT*/,
1086 uint16_t client_port /*= 0*/)
1087 : Dhcpv4Srv(server_port, client_port), timer_mgr_(TimerMgr::instance()) {
1088 if (getInstance()) {
1089 isc_throw(InvalidOperation,
1090 "There is another Dhcpv4Srv instance already.");
1091 }
1092 server_ = this; // remember this instance for later use in handlers
1093
1094 // TimerMgr uses IO service to run asynchronous timers.
1095 TimerMgr::instance()->setIOService(getIOService());
1096
1097 // CommandMgr uses IO service to run asynchronous socket operations.
1098 CommandMgr::instance().setIOService(getIOService());
1099
1100 // LeaseMgr uses IO service to run asynchronous timers.
1101 LeaseMgr::setIOService(getIOService());
1102
1103 // HostMgr uses IO service to run asynchronous timers.
1104 HostMgr::setIOService(getIOService());
1105
1106 // These are the commands always supported by the DHCPv4 server.
1107 // Please keep the list in alphabetic order.
1108 CommandMgr::instance().registerCommand("build-report",
1109 std::bind(&ControlledDhcpv4Srv::commandBuildReportHandler, this, ph::_1, ph::_2));
1110
1111 CommandMgr::instance().registerCommand("config-backend-pull",
1112 std::bind(&ControlledDhcpv4Srv::commandConfigBackendPullHandler, this, ph::_1, ph::_2));
1113
1114 CommandMgr::instance().registerCommand("config-get",
1115 std::bind(&ControlledDhcpv4Srv::commandConfigGetHandler, this, ph::_1, ph::_2));
1116
1117 CommandMgr::instance().registerCommand("config-reload",
1118 std::bind(&ControlledDhcpv4Srv::commandConfigReloadHandler, this, ph::_1, ph::_2));
1119
1120 CommandMgr::instance().registerCommand("config-set",
1121 std::bind(&ControlledDhcpv4Srv::commandConfigSetHandler, this, ph::_1, ph::_2));
1122
1123 CommandMgr::instance().registerCommand("config-test",
1124 std::bind(&ControlledDhcpv4Srv::commandConfigTestHandler, this, ph::_1, ph::_2));
1125
1126 CommandMgr::instance().registerCommand("config-write",
1127 std::bind(&ControlledDhcpv4Srv::commandConfigWriteHandler, this, ph::_1, ph::_2));
1128
1129 CommandMgr::instance().registerCommand("dhcp-enable",
1130 std::bind(&ControlledDhcpv4Srv::commandDhcpEnableHandler, this, ph::_1, ph::_2));
1131
1132 CommandMgr::instance().registerCommand("dhcp-disable",
1133 std::bind(&ControlledDhcpv4Srv::commandDhcpDisableHandler, this, ph::_1, ph::_2));
1134
1135 CommandMgr::instance().registerCommand("libreload",
1136 std::bind(&ControlledDhcpv4Srv::commandLibReloadHandler, this, ph::_1, ph::_2));
1137
1138 CommandMgr::instance().registerCommand("leases-reclaim",
1139 std::bind(&ControlledDhcpv4Srv::commandLeasesReclaimHandler, this, ph::_1, ph::_2));
1140
1141 CommandMgr::instance().registerCommand("server-tag-get",
1142 std::bind(&ControlledDhcpv4Srv::commandServerTagGetHandler, this, ph::_1, ph::_2));
1143
1144 CommandMgr::instance().registerCommand("shutdown",
1145 std::bind(&ControlledDhcpv4Srv::commandShutdownHandler, this, ph::_1, ph::_2));
1146
1147 CommandMgr::instance().registerCommand("status-get",
1148 std::bind(&ControlledDhcpv4Srv::commandStatusGetHandler, this, ph::_1, ph::_2));
1149
1150 CommandMgr::instance().registerCommand("version-get",
1151 std::bind(&ControlledDhcpv4Srv::commandVersionGetHandler, this, ph::_1, ph::_2));
1152
1153 // Register statistic related commands
1154 CommandMgr::instance().registerCommand("statistic-get",
1155 std::bind(&StatsMgr::statisticGetHandler, ph::_1, ph::_2));
1156
1157 CommandMgr::instance().registerCommand("statistic-reset",
1158 std::bind(&StatsMgr::statisticResetHandler, ph::_1, ph::_2));
1159
1160 CommandMgr::instance().registerCommand("statistic-remove",
1161 std::bind(&StatsMgr::statisticRemoveHandler, ph::_1, ph::_2));
1162
1163 CommandMgr::instance().registerCommand("statistic-get-all",
1164 std::bind(&StatsMgr::statisticGetAllHandler, ph::_1, ph::_2));
1165
1166 CommandMgr::instance().registerCommand("statistic-reset-all",
1167 std::bind(&StatsMgr::statisticResetAllHandler, ph::_1, ph::_2));
1168
1169 CommandMgr::instance().registerCommand("statistic-remove-all",
1170 std::bind(&StatsMgr::statisticRemoveAllHandler, ph::_1, ph::_2));
1171
1172 CommandMgr::instance().registerCommand("statistic-sample-age-set",
1173 std::bind(&StatsMgr::statisticSetMaxSampleAgeHandler, ph::_1, ph::_2));
1174
1175 CommandMgr::instance().registerCommand("statistic-sample-age-set-all",
1176 std::bind(&ControlledDhcpv4Srv::commandStatisticSetMaxSampleAgeAllHandler, this, ph::_1, ph::_2));
1177
1178 CommandMgr::instance().registerCommand("statistic-sample-count-set",
1179 std::bind(&StatsMgr::statisticSetMaxSampleCountHandler, ph::_1, ph::_2));
1180
1181 CommandMgr::instance().registerCommand("statistic-sample-count-set-all",
1182 std::bind(&ControlledDhcpv4Srv::commandStatisticSetMaxSampleCountAllHandler, this, ph::_1, ph::_2));
1183}
1184
1185 void ControlledDhcpv4Srv::shutdownServer(int exit_value) {
1186 setExitValue(exit_value);
1187 getIOService()->stop(); // Stop ASIO transmissions
1188 shutdown(); // Initiate DHCPv4 shutdown procedure.
1189}
1190
1191ControlledDhcpv4Srv::~ControlledDhcpv4Srv() {
1192 try {
1193 LeaseMgrFactory::destroy();
1194 HostMgr::create();
1195 cleanup();
1196
1197 // The closure captures either a shared pointer (memory leak)
1198 // or a raw pointer (pointing to a deleted object).
1199 DatabaseConnection::db_lost_callback_ = 0;
1200 DatabaseConnection::db_recovered_callback_ = 0;
1201 DatabaseConnection::db_failed_callback_ = 0;
1202
1203 timer_mgr_->unregisterTimers();
1204
1205 // Close the command socket (if it exists).
1206 CommandMgr::instance().closeCommandSocket();
1207
1208 // Deregister any registered commands (please keep in alphabetic order)
1209 CommandMgr::instance().deregisterCommand("build-report");
1210 CommandMgr::instance().deregisterCommand("config-backend-pull");
1211 CommandMgr::instance().deregisterCommand("config-get");
1212 CommandMgr::instance().deregisterCommand("config-reload");
1213 CommandMgr::instance().deregisterCommand("config-set");
1214 CommandMgr::instance().deregisterCommand("config-test");
1215 CommandMgr::instance().deregisterCommand("config-write");
1216 CommandMgr::instance().deregisterCommand("dhcp-disable");
1217 CommandMgr::instance().deregisterCommand("dhcp-enable");
1218 CommandMgr::instance().deregisterCommand("leases-reclaim");
1219 CommandMgr::instance().deregisterCommand("libreload");
1220 CommandMgr::instance().deregisterCommand("server-tag-get");
1221 CommandMgr::instance().deregisterCommand("shutdown");
1222 CommandMgr::instance().deregisterCommand("statistic-get");
1223 CommandMgr::instance().deregisterCommand("statistic-get-all");
1224 CommandMgr::instance().deregisterCommand("statistic-remove");
1225 CommandMgr::instance().deregisterCommand("statistic-remove-all");
1226 CommandMgr::instance().deregisterCommand("statistic-reset");
1227 CommandMgr::instance().deregisterCommand("statistic-reset-all");
1228 CommandMgr::instance().deregisterCommand("statistic-sample-age-set");
1229 CommandMgr::instance().deregisterCommand("statistic-sample-age-set-all");
1230 CommandMgr::instance().deregisterCommand("statistic-sample-count-set");
1231 CommandMgr::instance().deregisterCommand("statistic-sample-count-set-all");
1232 CommandMgr::instance().deregisterCommand("status-get");
1233 CommandMgr::instance().deregisterCommand("version-get");
1234
1235 // LeaseMgr uses IO service to run asynchronous timers.
1236 LeaseMgr::setIOService(IOServicePtr());
1237
1238 // HostMgr uses IO service to run asynchronous timers.
1239 HostMgr::setIOService(IOServicePtr());
1240 } catch (...) {
1241 // Don't want to throw exceptions from the destructor. The server
1242 // is shutting down anyway.
1243 ;
1244 }
1245
1246 server_ = NULL; // forget this instance. There should be no callback anymore
1247 // at this stage anyway.
1248}
1249
1250void
1251ControlledDhcpv4Srv::reclaimExpiredLeases(const size_t max_leases,
1252 const uint16_t timeout,
1253 const bool remove_lease,
1254 const uint16_t max_unwarned_cycles) {
1255 try {
1256 server_->alloc_engine_->reclaimExpiredLeases4(max_leases, timeout,
1257 remove_lease,
1258 max_unwarned_cycles);
1259 } catch (const std::exception& ex) {
1260 LOG_ERROR(dhcp4_logger, DHCP4_RECLAIM_EXPIRED_LEASES_FAIL)
1261 .arg(ex.what());
1262 }
1263 // We're using the ONE_SHOT timer so there is a need to re-schedule it.
1264 TimerMgr::instance()->setup(CfgExpiration::RECLAIM_EXPIRED_TIMER_NAME);
1265}
1266
1267void
1268ControlledDhcpv4Srv::deleteExpiredReclaimedLeases(const uint32_t secs) {
1269 server_->alloc_engine_->deleteExpiredReclaimedLeases4(secs);
1270 // We're using the ONE_SHOT timer so there is a need to re-schedule it.
1271 TimerMgr::instance()->setup(CfgExpiration::FLUSH_RECLAIMED_TIMER_NAME);
1272}
1273
1274bool
1275ControlledDhcpv4Srv::dbLostCallback(ReconnectCtlPtr db_reconnect_ctl) {
1276 if (!db_reconnect_ctl) {
1277 // This should never happen
1278 LOG_ERROR(dhcp4_logger, DHCP4_DB_RECONNECT_NO_DB_CTL);
1279 return (false);
1280 }
1281
1282 // Disable service until the connection is recovered.
1283 if (db_reconnect_ctl->retriesLeft() == db_reconnect_ctl->maxRetries() &&
1284 db_reconnect_ctl->alterServiceState()) {
1285 network_state_->disableService(NetworkState::Origin::DB_CONNECTION);
1286 }
1287
1288 LOG_INFO(dhcp4_logger, DHCP4_DB_RECONNECT_LOST_CONNECTION);
1289
1290 // If reconnect isn't enabled log it, initiate a shutdown if needed and
1291 // return false.
1292 if (!db_reconnect_ctl->retriesLeft() ||
1293 !db_reconnect_ctl->retryInterval()) {
1294 LOG_INFO(dhcp4_logger, DHCP4_DB_RECONNECT_DISABLED)
1295 .arg(db_reconnect_ctl->retriesLeft())
1296 .arg(db_reconnect_ctl->retryInterval());
1297 if (db_reconnect_ctl->exitOnFailure()) {
1298 shutdownServer(EXIT_FAILURE);
1299 }
1300 return (false);
1301 }
1302
1303 return (true);
1304}
1305
1306bool
1307ControlledDhcpv4Srv::dbRecoveredCallback(ReconnectCtlPtr db_reconnect_ctl) {
1308 if (!db_reconnect_ctl) {
1309 // This should never happen
1310 LOG_ERROR(dhcp4_logger, DHCP4_DB_RECONNECT_NO_DB_CTL);
1311 return (false);
1312 }
1313
1314 // Enable service after the connection is recovered.
1315 if (db_reconnect_ctl->alterServiceState()) {
1316 network_state_->enableService(NetworkState::Origin::DB_CONNECTION);
1317 }
1318
1319 LOG_INFO(dhcp4_logger, DHCP4_DB_RECONNECT_SUCCEEDED);
1320
1321 db_reconnect_ctl->resetRetries();
1322
1323 return (true);
1324}
1325
1326bool
1327ControlledDhcpv4Srv::dbFailedCallback(ReconnectCtlPtr db_reconnect_ctl) {
1328 if (!db_reconnect_ctl) {
1329 // This should never happen
1330 LOG_ERROR(dhcp4_logger, DHCP4_DB_RECONNECT_NO_DB_CTL);
1331 return (false);
1332 }
1333
1334 LOG_INFO(dhcp4_logger, DHCP4_DB_RECONNECT_FAILED)
1335 .arg(db_reconnect_ctl->maxRetries());
1336
1337 if (db_reconnect_ctl->exitOnFailure()) {
1338 shutdownServer(EXIT_FAILURE);
1339 }
1340
1341 return (true);
1342}
1343
1344void
1345ControlledDhcpv4Srv::openSocketsFailedCallback(ReconnectCtlPtr reconnect_ctl) {
1346 if (!reconnect_ctl) {
1347 // This should never happen
1348 LOG_ERROR(dhcp4_logger, DHCP4_OPEN_SOCKETS_NO_RECONNECT_CTL);
1349 return;
1350 }
1351
1352 LOG_INFO(dhcp4_logger, DHCP4_OPEN_SOCKETS_FAILED)
1353 .arg(reconnect_ctl->maxRetries());
1354
1355 if (reconnect_ctl->exitOnFailure()) {
1356 shutdownServer(EXIT_FAILURE);
1357 }
1358}
1359
1360void
1361ControlledDhcpv4Srv::cbFetchUpdates(const SrvConfigPtr& srv_cfg,
1362 boost::shared_ptr<unsigned> failure_count) {
1363 // stop thread pool (if running)
1364 MultiThreadingCriticalSection cs;
1365
1366 try {
1367 // Fetch any configuration backend updates since our last fetch.
1368 server_->getCBControl()->databaseConfigFetch(srv_cfg,
1369 CBControlDHCPv4::FetchMode::FETCH_UPDATE);
1370 (*failure_count) = 0;
1371
1372 } catch (const std::exception& ex) {
1373 LOG_ERROR(dhcp4_logger, DHCP4_CB_PERIODIC_FETCH_UPDATES_FAIL)
1374 .arg(ex.what());
1375
1376 // We allow at most 10 consecutive failures after which we stop
1377 // making further attempts to fetch the configuration updates.
1378 // Let's return without re-scheduling the timer.
1379 if (++(*failure_count) > 10) {
1380 LOG_ERROR(dhcp4_logger,
1381 DHCP4_CB_PERIODIC_FETCH_UPDATES_RETRIES_EXHAUSTED);
1382 return;
1383 }
1384 }
1385
1386 // Reschedule the timer to fetch new updates or re-try if
1387 // the previous attempt resulted in an error.
1388 if (TimerMgr::instance()->isTimerRegistered("Dhcp4CBFetchTimer")) {
1389 TimerMgr::instance()->setup("Dhcp4CBFetchTimer");
1390 }
1391}
1392
1393} // namespace dhcp
1394} // namespace isc
Hooks
CtrlAgentHooks Hooks
Definition: ca_response_creator.cc:47
cfg_db_access.h
cfg_multi_threading.h
cfgmgr.h
isc::BadValue
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Definition: exceptions/exceptions.h:132
isc::Exception
This is a base class for exceptions thrown from the DNS library module.
Definition: exceptions/exceptions.h:23
isc::Exception::what
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
Definition: exceptions/exceptions.cc:32
isc::InvalidOperation
A generic exception that is thrown if a function is called in a prohibited way.
Definition: exceptions/exceptions.h:143
isc::asiolink::IOSignalSet
Implements an asynchronous "signal" for IOService driven processing.
Definition: io_service_signal.h:26
isc::asiolink::IntervalTimer::ONE_SHOT
@ ONE_SHOT
Definition: interval_timer.h:63
isc::data::Element::create
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition: data.cc:241
isc::data::Element::map
@ map
Definition: data.h:155
isc::data::Element::integer
@ integer
Definition: data.h:155
isc::data::Element::boolean
@ boolean
Definition: data.h:155
isc::data::Element::string
@ string
Definition: data.h:155
isc::data::Element::createMap
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition: data.cc:291
isc::data::Element::createList
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition: data.cc:286
isc::db::DatabaseConnection::db_recovered_callback_
static DbCallback db_recovered_callback_
Optional callback function to invoke if an opened connection recovery succeeded.
Definition: database_connection.h:215
isc::db::DatabaseConnection::db_failed_callback_
static DbCallback db_failed_callback_
Optional callback function to invoke if an opened connection recovery failed.
Definition: database_connection.h:219
isc::db::DatabaseConnection::db_lost_callback_
static DbCallback db_lost_callback_
Optional callback function to invoke if an opened connection is lost.
Definition: database_connection.h:211
isc::dhcp::CfgExpiration::FLUSH_RECLAIMED_TIMER_NAME
static const std::string FLUSH_RECLAIMED_TIMER_NAME
Name of the timer for flushing reclaimed leases.
Definition: cfg_expiration.h:117
isc::dhcp::CfgExpiration::RECLAIM_EXPIRED_TIMER_NAME
static const std::string RECLAIM_EXPIRED_TIMER_NAME
Name of the timer for reclaiming expired leases.
Definition: cfg_expiration.h:114
isc::dhcp::CfgIface::open_sockets_failed_callback_
static OpenSocketsFailedCallback open_sockets_failed_callback_
Optional callback function to invoke if all retries of the opening sockets fail.
Definition: cfg_iface.h:361
isc::dhcp::CfgMgr::rollback
void rollback()
Removes staging configuration.
Definition: cfgmgr.cc:120
isc::dhcp::CfgMgr::instance
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
isc::dhcp::CfgMgr::getStagingCfg
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition: cfgmgr.cc:167
isc::dhcp::CfgMgr::commit
void commit()
Commits the staging configuration.
Definition: cfgmgr.cc:90
isc::dhcp::CfgMgr::getCurrentCfg
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition: cfgmgr.cc:161
isc::dhcp::CfgMultiThreading::apply
static void apply(data::ConstElementPtr value)
apply multi threading configuration
Definition: cfg_multi_threading.cc:21
isc::dhcp::ControlledDhcpv4Srv
Controlled version of the DHCPv4 server.
Definition: ctrl_dhcp4_srv.h:25
isc::dhcp::ControlledDhcpv4Srv::processConfig
static isc::data::ConstElementPtr processConfig(isc::data::ConstElementPtr new_config)
Configuration processor.
Definition: ctrl_dhcp4_srv.cc:878
isc::dhcp::ControlledDhcpv4Srv::~ControlledDhcpv4Srv
virtual ~ControlledDhcpv4Srv()
Destructor.
Definition: ctrl_dhcp4_srv.cc:1191
isc::dhcp::ControlledDhcpv4Srv::loadConfigFile
isc::data::ConstElementPtr loadConfigFile(const std::string &file_name)
Configure DHCPv4 server using the configuration file specified.
Definition: ctrl_dhcp4_srv.cc:126
isc::dhcp::ControlledDhcpv4Srv::cleanup
void cleanup()
Performs cleanup, immediately before termination.
Definition: ctrl_dhcp4_srv.cc:121
isc::dhcp::ControlledDhcpv4Srv::processCommand
static isc::data::ConstElementPtr processCommand(const std::string &command, isc::data::ConstElementPtr args)
Command processor.
Definition: ctrl_dhcp4_srv.cc:804
isc::dhcp::ControlledDhcpv4Srv::ControlledDhcpv4Srv
ControlledDhcpv4Srv(uint16_t server_port=DHCP4_SERVER_PORT, uint16_t client_port=0)
Constructor.
Definition: ctrl_dhcp4_srv.cc:1085
isc::dhcp::ControlledDhcpv4Srv::init
void init(const std::string &config_file)
Initializes the server.
Definition: ctrl_dhcp4_srv.cc:92
isc::dhcp::ControlledDhcpv4Srv::getInstance
static ControlledDhcpv4Srv * getInstance()
Returns pointer to the sole instance of Dhcpv4Srv.
Definition: ctrl_dhcp4_srv.h:127
isc::dhcp::ControlledDhcpv4Srv::shutdownServer
void shutdownServer(int exit_value)
Initiates shutdown procedure for the whole DHCPv4 server.
Definition: ctrl_dhcp4_srv.cc:1185
isc::dhcp::ControlledDhcpv4Srv::checkConfig
isc::data::ConstElementPtr checkConfig(isc::data::ConstElementPtr new_config)
Configuration checker.
Definition: ctrl_dhcp4_srv.cc:1067
isc::dhcp::Dhcp4to6Ipc::instance
static Dhcp4to6Ipc & instance()
Returns pointer to the sole instance of Dhcp4to6Ipc.
Definition: dhcp4to6_ipc.cc:32
isc::dhcp::Dhcp4to6Ipc::open
virtual void open()
Open communication socket.
Definition: dhcp4to6_ipc.cc:37
isc::dhcp::Dhcpv4Srv
DHCPv4 server service.
Definition: dhcp4_srv.h:253
isc::dhcp::Dhcpv4Srv::startD2
void startD2()
Starts DHCP_DDNS client IO if DDNS updates are enabled.
Definition: dhcp4_srv.cc:4171
isc::dhcp::Dhcpv4Srv::shutdown
void shutdown() override
Instructs the server to shut down.
Definition: dhcp4_srv.cc:729
isc::dhcp::Dhcpv4Srv::getIOService
asiolink::IOServicePtr & getIOService()
Returns pointer to the IO service used by the server.
Definition: dhcp4_srv.h:304
isc::dhcp::Dhcpv4Srv::alloc_engine_
boost::shared_ptr< AllocEngine > alloc_engine_
Allocation Engine.
Definition: dhcp4_srv.h:1131
isc::dhcp::Dhcpv4Srv::inTestMode
bool inTestMode() const
Checks if the server is running in unit test mode.
Definition: dhcp4_srv.h:299
isc::dhcp::Dhcpv4Srv::getNetworkState
NetworkStatePtr & getNetworkState()
Returns pointer to the network state used by the server.
Definition: dhcp4_srv.h:309
isc::dhcp::Dhcpv4Srv::getVersion
static std::string getVersion(bool extended)
returns Kea version on stdout and exit.
Definition: dhcp4_srv.cc:4207
isc::dhcp::Dhcpv4Srv::useBroadcast
bool useBroadcast() const
Return bool value indicating that broadcast flags should be set on sockets.
Definition: dhcp4_srv.h:419
isc::dhcp::Dhcpv4Srv::network_state_
NetworkStatePtr network_state_
Holds information about disabled DHCP service and/or disabled subnet/network scopes.
Definition: dhcp4_srv.h:1138
isc::dhcp::Dhcpv4Srv::getServerPort
uint16_t getServerPort() const
Get UDP port on which server should listen.
Definition: dhcp4_srv.h:411
isc::dhcp::Dhcpv4Srv::getCBControl
CBControlDHCPv4Ptr getCBControl() const
Returns an object which controls access to the configuration backends.
Definition: dhcp4_srv.h:318
isc::dhcp::HostMgr::setIOService
static void setIOService(const isc::asiolink::IOServicePtr &io_service)
Sets IO service to be used by the Host Manager.
Definition: host_mgr.h:638
isc::dhcp::HostMgr::create
static void create()
Creates new instance of the HostMgr.
Definition: host_mgr.cc:43
isc::dhcp::IfaceMgr::instance
static IfaceMgr & instance()
IfaceMgr is a singleton class.
Definition: iface_mgr.cc:53
isc::dhcp::LeaseMgrFactory::destroy
static void destroy()
Destroy lease manager.
Definition: lease_mgr_factory.cc:94
isc::dhcp::LeaseMgr::setIOService
static void setIOService(const isc::asiolink::IOServicePtr &io_service)
Sets IO service to be used by the Lease Manager.
Definition: lease_mgr.h:786
isc::dhcp::LibDHCP::commitRuntimeOptionDefs
static void commitRuntimeOptionDefs()
Commits runtime option definitions.
Definition: libdhcp++.cc:238
isc::dhcp::NetworkState::Origin
Origin
Origin of the network state transition.
Definition: network_state.h:84
isc::dhcp::NetworkState::Origin::USER_COMMAND
@ USER_COMMAND
The network state is being altered by a user command.
isc::dhcp::NetworkState::Origin::DB_CONNECTION
@ DB_CONNECTION
The network state is being altered by the DB connection recovery mechanics.
isc::dhcp::NetworkState::Origin::HA_COMMAND
@ HA_COMMAND
The network state is being altered by a HA internal command.
isc::dhcp::Parser4Context
Evaluation context, an interface to the expression evaluation.
Definition: dhcp4/parser_context.h:36
isc::dhcp::Parser4Context::parseFile
isc::data::ElementPtr parseFile(const std::string &filename, ParserType parser_type)
Run the parser on the file specified.
Definition: dhcp4/parser_context.cc:37
isc::dhcp::Parser4Context::PARSER_DHCP4
@ PARSER_DHCP4
This parser will parse the content as Dhcp4 config wrapped in a map (that's the regular config file)
Definition: dhcp4/parser_context.h:55
isc::dhcp::TimerMgr
Manages a pool of asynchronous interval timers.
Definition: timer_mgr.h:62
isc::dhcp::TimerMgr::instance
static const TimerMgrPtr & instance()
Returns pointer to the sole instance of the TimerMgr.
Definition: timer_mgr.cc:449
isc::hooks::NoSuchArgument
No such argument.
Definition: callout_handle.h:31
isc::process::Daemon::getConfigFile
std::string getConfigFile() const
Returns config file name.
Definition: daemon.cc:105
isc::process::Daemon::writeConfigFile
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::process::Daemon::signal_set_
isc::asiolink::IOSignalSetPtr signal_set_
A pointer to the object installing custom signal handlers.
Definition: daemon.h:257
isc::process::Daemon::start_
boost::posix_time::ptime start_
Timestamp of the start of the daemon.
Definition: daemon.h:263
isc::process::Daemon::setExitValue
void setExitValue(int value)
Sets the exit value.
Definition: daemon.h:227
isc::process::Daemon::redactConfig
isc::data::ConstElementPtr redactConfig(isc::data::ConstElementPtr const &config)
Redact a configuration.
Definition: daemon.cc:257
isc::stats::StatsMgr
Statistics Manager class.
Definition: lib/stats/stats_mgr.h:63
isc::util::MultiThreadingCriticalSection
RAII class creating a critical section.
Definition: multi_threading_mgr.h:355
command_interpreter.h
This file contains several functions and constants that are used for handling commands and responses ...
command_mgr.h
config_report.h
ctrl_dhcp4_srv.h
data.h
db_type.h
json_config_parser.h
parser_context.h
dhcp4_log.h
Contains declarations for loggers used by the DHCPv4 server component.
dhcp4to6_ipc.h
Defines the Dhcp4o6Ipc class.
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition: exceptions/exceptions.h:210
isc::stats::StatsMgr::statisticSetMaxSampleCountAllHandler
isc::data::ConstElementPtr statisticSetMaxSampleCountAllHandler(const isc::data::ConstElementPtr &params)
Handles statistic-sample-count-set-all command.
Definition: lib/stats/stats_mgr.cc:563
isc::stats::StatsMgr::statisticSetMaxSampleAgeAllHandler
isc::data::ConstElementPtr statisticSetMaxSampleAgeAllHandler(const isc::data::ConstElementPtr &params)
Handles statistic-sample-age-set-all command.
Definition: lib/stats/stats_mgr.cc:542
isc::stats::StatsMgr::getMaxSampleCountDefault
uint32_t getMaxSampleCountDefault() const
Get default count limit.
Definition: lib/stats/stats_mgr.cc:285
isc::stats::StatsMgr::getMaxSampleAgeDefault
const StatsDuration & getMaxSampleAgeDefault() const
Get default duration limit.
Definition: lib/stats/stats_mgr.cc:270
hooks.h
hooks_manager.h
host_mgr.h
lease_mgr_factory.h
stats_mgr.h
libdhcp++.h
LOG_ERROR
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
LOG_INFO
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
LOG_WARN
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
LOG_FATAL
#define LOG_FATAL(LOGGER, MESSAGE)
Macro to conveniently test fatal output and log it.
Definition: macros.h:38
LOG_DEBUG
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
multi_threading_mgr.h
isc::asiolink
Definition: addr_utilities.cc:170
isc::asiolink::IOServicePtr
boost::shared_ptr< IOService > IOServicePtr
Defines a smart pointer to an IOService instance.
Definition: io_service.h:110
isc::config
Definition: command_interpreter.cc:23
isc::config::CONTROL_RESULT_EMPTY
const int CONTROL_RESULT_EMPTY
Status code indicating that the specified command was completed correctly, but failed to produce any ...
Definition: command_interpreter.h:53
isc::config::CONTROL_RESULT_ERROR
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
Definition: command_interpreter.h:45
isc::config::createAnswer
ConstElementPtr createAnswer(const int status_code, const std::string &text, const ConstElementPtr &arg)
Definition: command_interpreter.cc:34
isc::config::parseAnswer
ConstElementPtr parseAnswer(int &rcode, const ConstElementPtr &msg)
Definition: command_interpreter.cc:69
isc::config::CONTROL_RESULT_SUCCESS
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
Definition: command_interpreter.h:42
isc::data
Definition: base_stamped_element.cc:12
isc::data::ConstElementPtr
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
isc::data::ElementPtr
boost::shared_ptr< Element > ElementPtr
Definition: data.h:24
isc::db
Definition: audit_entry.cc:14
isc::db::error
@ error
Definition: db_log.h:115
isc::detail::getConfigReport
std::string getConfigReport()
Definition: cfgrpt.cc:20
isc::dhcp
Definition: dhcp4/client_handler.cc:20
isc::dhcp::DHCP4_NOT_RUNNING
const isc::log::MessageID DHCP4_NOT_RUNNING
Definition: dhcp4_messages.h:95
isc::dhcp::DHCP4_DYNAMIC_RECONFIGURATION_FAIL
const isc::log::MessageID DHCP4_DYNAMIC_RECONFIGURATION_FAIL
Definition: dhcp4_messages.h:66
isc::dhcp::DHCP4_CONFIG_RECEIVED
const isc::log::MessageID DHCP4_CONFIG_RECEIVED
Definition: dhcp4_messages.h:38
isc::dhcp::DHCP4_DYNAMIC_RECONFIGURATION_SUCCESS
const isc::log::MessageID DHCP4_DYNAMIC_RECONFIGURATION_SUCCESS
Definition: dhcp4_messages.h:67
isc::dhcp::CfgDbAccessPtr
boost::shared_ptr< CfgDbAccess > CfgDbAccessPtr
A pointer to the CfgDbAccess.
Definition: cfg_db_access.h:130
isc::dhcp::IfacePtr
boost::shared_ptr< Iface > IfacePtr
Type definition for the pointer to an Iface object.
Definition: iface_mgr.h:487
isc::dhcp::configureDhcp4Server
isc::data::ConstElementPtr configureDhcp4Server(Dhcpv4Srv &server, isc::data::ConstElementPtr config_set, bool check_only)
Configure DHCPv4 server (Dhcpv4Srv) with a set of configuration values.
Definition: dhcp4/json_config_parser.cc:324
isc::dhcp::DHCP4_DB_RECONNECT_NO_DB_CTL
const isc::log::MessageID DHCP4_DB_RECONNECT_NO_DB_CTL
Definition: dhcp4_messages.h:47
isc::dhcp::DHCP4_CB_PERIODIC_FETCH_UPDATES_RETRIES_EXHAUSTED
const isc::log::MessageID DHCP4_CB_PERIODIC_FETCH_UPDATES_RETRIES_EXHAUSTED
Definition: dhcp4_messages.h:19
isc::dhcp::DHCP4_CONFIG_PACKET_QUEUE
const isc::log::MessageID DHCP4_CONFIG_PACKET_QUEUE
Definition: dhcp4_messages.h:37
isc::dhcp::SrvConfigPtr
boost::shared_ptr< SrvConfig > SrvConfigPtr
Non-const pointer to the SrvConfig.
Definition: srv_config.h:1165
isc::dhcp::DHCP4_CB_ON_DEMAND_FETCH_UPDATES_FAIL
const isc::log::MessageID DHCP4_CB_ON_DEMAND_FETCH_UPDATES_FAIL
Definition: dhcp4_messages.h:17
isc::dhcp::DHCP4_CONFIG_LOAD_FAIL
const isc::log::MessageID DHCP4_CONFIG_LOAD_FAIL
Definition: dhcp4_messages.h:34
isc::dhcp::DBG_DHCP4_COMMAND
const int DBG_DHCP4_COMMAND
Debug level used to log receiving commands.
Definition: dhcp4_log.h:30
isc::dhcp::DHCP4_HOOKS_LIBS_RELOAD_FAIL
const isc::log::MessageID DHCP4_HOOKS_LIBS_RELOAD_FAIL
Definition: dhcp4_messages.h:72
isc::dhcp::DHCP4_DB_RECONNECT_DISABLED
const isc::log::MessageID DHCP4_DB_RECONNECT_DISABLED
Definition: dhcp4_messages.h:44
isc::dhcp::DHCP4_CONFIG_UNRECOVERABLE_ERROR
const isc::log::MessageID DHCP4_CONFIG_UNRECOVERABLE_ERROR
Definition: dhcp4_messages.h:41
isc::dhcp::DHCP4_DB_RECONNECT_SUCCEEDED
const isc::log::MessageID DHCP4_DB_RECONNECT_SUCCEEDED
Definition: dhcp4_messages.h:48
isc::dhcp::DHCP4_COMMAND_RECEIVED
const isc::log::MessageID DHCP4_COMMAND_RECEIVED
Definition: dhcp4_messages.h:31
isc::dhcp::DHCP4_MULTI_THREADING_INFO
const isc::log::MessageID DHCP4_MULTI_THREADING_INFO
Definition: dhcp4_messages.h:93
isc::dhcp::DHCP4_OPEN_SOCKETS_NO_RECONNECT_CTL
const isc::log::MessageID DHCP4_OPEN_SOCKETS_NO_RECONNECT_CTL
Definition: dhcp4_messages.h:101
isc::dhcp::dhcp4_logger
isc::log::Logger dhcp4_logger(DHCP4_APP_LOGGER_NAME)
Base logger for DHCPv4 server.
Definition: dhcp4_log.h:90
isc::dhcp::DHCP4_DB_RECONNECT_FAILED
const isc::log::MessageID DHCP4_DB_RECONNECT_FAILED
Definition: dhcp4_messages.h:45
isc::dhcp::DHCP4_OPEN_SOCKETS_FAILED
const isc::log::MessageID DHCP4_OPEN_SOCKETS_FAILED
Definition: dhcp4_messages.h:100
isc::dhcp::DHCP4_DYNAMIC_RECONFIGURATION
const isc::log::MessageID DHCP4_DYNAMIC_RECONFIGURATION
Definition: dhcp4_messages.h:65
isc::dhcp::DHCP4_RECLAIM_EXPIRED_LEASES_FAIL
const isc::log::MessageID DHCP4_RECLAIM_EXPIRED_LEASES_FAIL
Definition: dhcp4_messages.h:137
isc::dhcp::DHCP4_CONFIG_UNSUPPORTED_OBJECT
const isc::log::MessageID DHCP4_CONFIG_UNSUPPORTED_OBJECT
Definition: dhcp4_messages.h:42
isc::dhcp::DHCP4_CB_PERIODIC_FETCH_UPDATES_FAIL
const isc::log::MessageID DHCP4_CB_PERIODIC_FETCH_UPDATES_FAIL
Definition: dhcp4_messages.h:18
isc::dhcp::DHCP4_DB_RECONNECT_LOST_CONNECTION
const isc::log::MessageID DHCP4_DB_RECONNECT_LOST_CONNECTION
Definition: dhcp4_messages.h:46
isc::hooks
Definition: callout_handle.cc:21
isc::hooks::HookLibsCollection
std::vector< HookLibInfo > HookLibsCollection
A storage for information about hook libraries.
Definition: libinfo.h:31
isc::hooks::CalloutHandlePtr
boost::shared_ptr< CalloutHandle > CalloutHandlePtr
A shared pointer to a CalloutHandle object.
Definition: callout_handle.h:437
isc::stats
Definition: context.cc:18
isc::stats::toSeconds
long toSeconds(const StatsDuration &dur)
Returns the number of seconds in a duration.
Definition: observation.h:45
isc::util
Definition: edns.h:19
isc::util::ReconnectCtlPtr
boost::shared_ptr< ReconnectCtl > ReconnectCtlPtr
Pointer to an instance of ReconnectCtl.
Definition: reconnect_ctl.h:138
isc
Defines the logger used by the top-level component of kea-lfc.
Definition: agent_parser.cc:143