Kea: daemon.cc Source File

| Kea 3.2.0-git

daemon.cc
Go to the documentation of this file.
1// Copyright (C) 2014-2026 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 <cstdlib>
10
11#include <cc/data.h>
12#include <process/daemon.h>
13#include <process/log_parser.h>
14#include <exceptions/exceptions.h>
15#include <log/logger_name.h>
16#include <log/logger_support.h>
17#include <process/config_base.h>
18#include <process/redact_config.h>
19#include <util/filesystem.h>
20
21#include <functional>
22#include <sstream>
23#include <fstream>
24
25#include <errno.h>
26
27using namespace isc::data;
28using namespace isc::util;
29using namespace isc::util::file;
30
35namespace isc {
36namespace process {
37
38bool Daemon::verbose_ = false;
39
40std::string Daemon::proc_name_("");
41
42std::string Daemon::default_logger_name_("kea");
43
44Daemon::Daemon()
45 : signal_set_(), config_file_(""),
46 pid_file_dir_(PIDFILE_DIR), pid_file_(), am_file_author_(false),
47 exit_value_(EXIT_SUCCESS) {
48
49 // The pid_file_dir can be overridden via environment variable
50 // This is primarily intended to simplify testing
51 const char* const env = getenv("KEA_PIDFILE_DIR");
52 if (env) {
53 pid_file_dir_ = env;
54 }
55}
56
57Daemon::~Daemon() {
58 if (pid_file_ && am_file_author_) {
59 pid_file_->deleteFile();
60 }
61}
62
63 void Daemon::cleanup() {
64}
65
66 void Daemon::shutdown() {
67}
68
69 void Daemon::configureLogger(const ConstElementPtr& log_config,
70 const ConfigPtr& storage) {
71
72 if (log_config) {
73 ConstElementPtr loggers = log_config->get("loggers");
74 if (loggers) {
75 LogConfigParser parser(storage);
76 parser.parseConfiguration(loggers, verbose_);
77 }
78 }
79}
80
81void
82Daemon::setVerbose(bool verbose) {
83 verbose_ = verbose;
84}
85
86bool
87Daemon::getVerbose() {
88 return (verbose_);
89}
90
91 void Daemon::loggerInit(const char* name, bool verbose) {
92
93 setenv("KEA_LOGGER_DESTINATION", "stdout", 0);
94
95 // Initialize logger system
96 isc::log::initLogger(name, isc::log::DEBUG, isc::log::MAX_DEBUG_LEVEL, 0);
97
98 // Apply default configuration (log INFO or DEBUG to stdout)
99 isc::log::setDefaultLoggingOutput(verbose);
100}
101
102std::string Daemon::getVersion(bool /*extended*/) {
103 isc_throw(isc::NotImplemented, "Daemon::getVersion() called");
104}
105
106std::string
107Daemon::getConfigFile() const {
108 return (config_file_);
109}
110
111void
112Daemon::setConfigFile(const std::string& config_file) {
113 config_file_ = config_file;
114}
115
116void
117Daemon::checkConfigFile() const {
118 if (config_file_.empty()) {
119 isc_throw(isc::BadValue, "config file name is not set");
120 }
121
122 // Create Path instance from the config_file_ pathname, and
123 // check the file name component.
124 Path file(config_file_);
125 if (file.stem().empty()) {
126 isc_throw(isc::BadValue, "config file:" << config_file_
127 << " is missing file name");
128 }
129}
130
131void
132Daemon::checkWriteConfigFile(std::string& file) {
133 Path path(file);
134 // from checkConfigFile().
135 if (path.stem().empty()) {
136 isc_throw(isc::BadValue, "config file:" << file
137 << " is missing file name");
138 }
139 Path current(config_file_);
140 if (current.parentDirectory() == path.parentDirectory()) {
141 // Same parent directories!
142 return;
143 }
144 if (path.parentDirectory().empty()) {
145 // Note the current parent directory can't be empty here.
146 file = current.parentDirectory() + file;
147 return;
148 }
149 isc_throw(isc::BadValue, "file " << file << " must be in the same "
150 << "directory as the config file (" << config_file_ << ")");
151}
152
153std::string
154Daemon::getProcName() {
155 return (proc_name_);
156}
157
158void
159Daemon::setProcName(const std::string& proc_name) {
160 proc_name_ = proc_name;
161}
162
163std::string
164Daemon::getPIDFileDir() const {
165 return(pid_file_dir_);
166}
167
168void
169Daemon::setPIDFileDir(const std::string& pid_file_dir) {
170 pid_file_dir_ = pid_file_dir;
171}
172
173std::string
174Daemon::getPIDFileName() const {
175 if (pid_file_) {
176 return (pid_file_->getFilename());
177 }
178
179 return ("");
180}
181
182std::string
183Daemon::getPIDLockName() const {
184 if (pid_file_) {
185 return (pid_file_->getLockname());
186 }
187
188 return ("");
189}
190
191void
192Daemon::setPIDFileName(const std::string& pid_file_name) {
193 if (pid_file_) {
194 isc_throw(isc::InvalidOperation, "Daemon::setConfigFile"
195 " file name already set to:" << pid_file_->getFilename());
196 }
197
198 if (pid_file_name.empty()) {
199 isc_throw(isc::BadValue, "Daemon::setPIDFileName"
200 " file name may not be empty");
201 }
202
203 pid_file_.reset(new PIDFile(pid_file_name));
204}
205
206std::string
207Daemon::makePIDFileName() const {
208 if (config_file_.empty()) {
209 isc_throw(isc::InvalidOperation,
210 "Daemon::makePIDFileName config file name is not set");
211 }
212
213 // Create Path instance from the config_file_ pathname, so we can
214 // extract the fname component.
215 Path file(config_file_);
216 if (file.stem().empty()) {
217 isc_throw(isc::BadValue, "Daemon::makePIDFileName config file:"
218 << config_file_ << " is missing file name");
219 }
220
221 if (proc_name_.empty()) {
222 isc_throw(isc::InvalidOperation,
223 "Daemon::makePIDFileName process name is not set");
224 }
225
226 // Make the pathname for the PID file from the runtime directory,
227 // configuration name and process name.
228 std::ostringstream stream;
229 stream << pid_file_dir_ << "/" << file.stem()
230 << "." << proc_name_ << ".pid";
231
232 return(stream.str());
233};
234
235void
236Daemon::createPIDFile(int pid) {
237 // If pid_file_ hasn't been instantiated explicitly, then do so
238 // using the default name.
239 if (!pid_file_) {
240 setPIDFileName(makePIDFileName());
241 }
242
243 // Acquire a lock for check and write operations.
244 PIDLock pid_lock(getPIDLockName());
245 if (!pid_lock.isLocked()) {
246 isc_throw(DaemonPIDExists, "Daemon::createPIDFile: can't lock, "
247 "PID lock file: " << getPIDLockName());
248 }
249
250 // If we find a pre-existing file containing a live PID we bail.
251 int chk_pid = pid_file_->check();
252 if (chk_pid > 0) {
253 isc_throw(DaemonPIDExists, "Daemon::createPIDFile: PID: " << chk_pid
254 << " exists, PID file: " << getPIDFileName());
255 }
256
257 if (pid == 0) {
258 // Write the PID of the current process
259 pid_file_->write();
260 } else {
261 // Write the PID we were given
262 pid_file_->write(pid);
263 }
264
265 am_file_author_ = true;
266}
267
268size_t
269Daemon::writeConfigFile(const std::string& config_file,
270 ConstElementPtr cfg) const {
271 if (!cfg) {
272 isc_throw(Unexpected, "Can't write configuration: conversion to JSON failed");
273 }
274
275 std::ofstream out(config_file, std::ios::trunc);
276 if (!out.good()) {
277 isc_throw(Unexpected, "Unable to open file " + config_file + " for writing");
278 }
279
280 // Write the actual content using pretty printing.
281 prettyPrint(cfg, out);
282
283 size_t bytes = static_cast<size_t>(out.tellp());
284
285 out.close();
286
287 return (bytes);
288}
289
290std::list<std::list<std::string>>
291Daemon::jsonPathsToRedact() const {
292 static std::list<std::list<std::string>> const list;
293 return list;
294}
295
296 isc::data::ConstElementPtr
297Daemon::redactConfig(isc::data::ConstElementPtr const& config) {
298 isc::data::ConstElementPtr result(config);
299 for (std::list<std::string>& json_path : jsonPathsToRedact()) {
300 result = isc::process::redactConfig(result, json_path);
301 }
302 return result;
303}
304
305} // namespace process
306} // namespace isc
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::InvalidOperation
A generic exception that is thrown if a function is called in a prohibited way.
Definition exceptions/exceptions.h:143
isc::NotImplemented
A generic exception that is thrown when a function is not implemented.
Definition exceptions/exceptions.h:166
isc::Unexpected
A generic exception that is thrown when an unexpected error condition occurs.
Definition exceptions/exceptions.h:153
isc::process::DaemonPIDExists
Exception thrown when the PID file points to a live PID.
Definition daemon.h:25
isc::process::Daemon::getConfigFile
std::string getConfigFile() const
Returns config file name.
Definition daemon.cc:107
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:269
isc::process::Daemon::getVersion
static std::string getVersion(bool extended)
returns Kea version on stdout and exits.
Definition daemon.cc:102
isc::process::Daemon::setVerbose
static void setVerbose(const bool verbose)
Sets or clears verbose mode.
Definition daemon.cc:82
isc::process::Daemon::getPIDFileName
std::string getPIDFileName() const
Returns the current PID file name.
Definition daemon.cc:174
isc::process::Daemon::jsonPathsToRedact
virtual std::list< std::list< std::string > > jsonPathsToRedact() const
Return a list of all paths that contain passwords or secrets.
Definition daemon.cc:291
isc::process::Daemon::Daemon
Daemon()
Default constructor.
Definition daemon.cc:44
isc::process::Daemon::shutdown
virtual void shutdown()
Initiates shutdown procedure for the whole server.
Definition daemon.cc:66
isc::process::Daemon::getPIDFileDir
std::string getPIDFileDir() const
Returns the directory used when forming default PID file name.
Definition daemon.cc:164
isc::process::Daemon::~Daemon
virtual ~Daemon()
Destructor.
Definition daemon.cc:57
isc::process::Daemon::signal_set_
isc::asiolink::IOSignalSetPtr signal_set_
A pointer to the object installing custom signal handlers.
Definition daemon.h:272
isc::process::Daemon::configureLogger
static void configureLogger(const isc::data::ConstElementPtr &log_config, const isc::process::ConfigPtr &storage)
Configures logger.
Definition daemon.cc:69
isc::process::Daemon::getVerbose
static bool getVerbose()
Returns if running in verbose mode.
Definition daemon.cc:87
isc::process::Daemon::loggerInit
static void loggerInit(const char *log_name, bool verbose)
Initializes logger.
Definition daemon.cc:91
isc::process::Daemon::checkWriteConfigFile
void checkWriteConfigFile(std::string &file)
Checks the to-be-written configuration file name.
Definition daemon.cc:132
isc::process::Daemon::getProcName
static std::string getProcName()
returns the process name This value is used as when forming the default PID file name
Definition daemon.cc:154
isc::process::Daemon::cleanup
virtual void cleanup()
Performs final deconfiguration.
Definition daemon.cc:63
isc::process::Daemon::redactConfig
isc::data::ConstElementPtr redactConfig(isc::data::ConstElementPtr const &config)
Redact a configuration.
Definition daemon.cc:297
isc::process::Daemon::checkConfigFile
void checkConfigFile() const
Checks the configuration file name.
Definition daemon.cc:117
isc::process::Daemon::setPIDFileName
void setPIDFileName(const std::string &pid_file_name)
Sets PID file name.
Definition daemon.cc:192
isc::process::Daemon::setProcName
static void setProcName(const std::string &proc_name)
Sets the process name.
Definition daemon.cc:159
isc::process::Daemon::createPIDFile
void createPIDFile(int pid=0)
Creates the PID file.
Definition daemon.cc:236
isc::process::Daemon::setPIDFileDir
void setPIDFileDir(const std::string &pid_file_dir)
Sets the PID file directory.
Definition daemon.cc:169
isc::process::Daemon::getPIDLockName
std::string getPIDLockName() const
Returns the current PID lock file name.
Definition daemon.cc:183
isc::process::Daemon::makePIDFileName
std::string makePIDFileName() const
Manufacture the pid file name.
Definition daemon.cc:207
isc::process::Daemon::setConfigFile
void setConfigFile(const std::string &config_file)
Sets the configuration file name.
Definition daemon.cc:112
isc::process::LogConfigParser
Configures log4cplus by translating Kea configuration structures.
Definition log_parser.h:43
isc::process::LogConfigParser::parseConfiguration
void parseConfiguration(const isc::data::ConstElementPtr &log_config, bool verbose=false)
Parses specified configuration.
Definition log_parser.cc:38
isc::util::PIDFile
Class to help with processing PID files.
Definition pid_file.h:40
isc::util::PIDLock
RAII device to handle a lock file to avoid race conditions.
Definition pid_file.h:115
isc::util::PIDLock::isLocked
bool isLocked()
Return the lock status.
Definition pid_file.h:131
config_base.h
daemon.h
data.h
exceptions.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition exceptions/exceptions.h:210
filesystem.h
log_parser.h
logger_name.h
logger_support.h
Logging initialization functions.
isc::config
Definition command_interpreter.cc:23
isc::data
Definition base_stamped_element.cc:12
isc::data::prettyPrint
void prettyPrint(ConstElementPtr element, std::ostream &out, unsigned indent, unsigned step)
Pretty prints the data into stream.
Definition data.cc:1747
isc::data::ConstElementPtr
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:30
isc::log::initLogger
void initLogger(const string &root, isc::log::Severity severity, int dbglevel, const char *file, bool buffer)
Run-time initialization.
Definition logger_support.cc:45
isc::log::MAX_DEBUG_LEVEL
const int MAX_DEBUG_LEVEL
Definition logger_level.h:36
isc::log::setDefaultLoggingOutput
void setDefaultLoggingOutput(bool verbose)
Reset root logger characteristics.
Definition logger_support.cc:54
isc::log::DEBUG
@ DEBUG
Definition logger_level.h:25
isc::process
Definition cb_ctl_base.h:22
isc::process::redactConfig
ConstElementPtr redactConfig(ConstElementPtr const &element, list< string > const &json_path, string obscure, unsigned max_nesting_depth)
Redact a configuration.
Definition redact_config.cc:98
isc::process::ConfigPtr
boost::shared_ptr< ConfigBase > ConfigPtr
Non-const pointer to the ConfigBase.
Definition config_base.h:176
isc::util::file
Definition filesystem.cc:29
isc::util
Definition time_utils.cc:43
isc
Defines the logger used by the top-level component of kea-lfc.
Definition check_exists_add.cc:18
redact_config.h
isc::util::file::Path
Paths on a filesystem.
Definition filesystem.h:126
isc::util::file::Path::parentDirectory
std::string parentDirectory() const
Get the parent directory.
Definition filesystem.cc:171
isc::util::file::Path::stem
std::string stem() const
Get the base name of the file without the extension.
Definition filesystem.cc:176