Kea: legal_log_mgr_factory.cc Source File

| Kea 3.0.3-git

legal_log_mgr_factory.cc
Go to the documentation of this file.
1// Copyright (C) 2025 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 <legal_log_mgr_factory.h>
10#include <dhcpsrv/dhcpsrv_log.h>
11
12using namespace isc::db;
13using namespace std;
14
15namespace isc {
16namespace dhcp {
17
18 isc::asiolink::IOServicePtr LegalLogMgrFactory::io_service_;
19map<string, pair<LegalLogMgrFactory::Factory, LegalLogMgrFactory::DBVersion>> LegalLogMgrFactory::map_;
20 LegalLogMgrPool LegalLogMgrFactory::pool_;
21
22bool
23LegalLogMgrFactory::registerBackendFactory(const string& db_type,
24 const Factory& factory,
25 bool no_log,
26 DBVersion db_version) {
27 if (map_.count(db_type)) {
28 return (false);
29 }
30
31 static auto default_db_version = []() -> string {
32 return (string());
33 };
34
35 if (!db_version) {
36 db_version = default_db_version;
37 }
38
39 map_.insert(pair<string, pair<Factory, DBVersion>>(db_type, pair<Factory, DBVersion>(factory, db_version)));
40
41 // We are dealing here with static logger initialization fiasco.
42 // registerFactory may be called from constructors of static global
43 // objects for built in backends. The logging is not initialized yet,
44 // so the LOG_DEBUG would throw.
45 if (!no_log) {
46 LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_FORENSIC_BACKEND_REGISTER)
47 .arg(db_type);
48 }
49 return (true);
50}
51
52bool
53LegalLogMgrFactory::unregisterBackendFactory(const string& db_type, bool no_log) {
54 // Look for it.
55 auto index = map_.find(db_type);
56
57 // If it's there remove it
58 if (index != map_.end()) {
59 map_.erase(index);
60 delAllBackends(db_type);
61 if (!no_log) {
62 LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE,
63 DHCPSRV_FORENSIC_BACKEND_DEREGISTER)
64 .arg(db_type);
65 }
66 return (true);
67 }
68 return (false);
69}
70
71void
72LegalLogMgrFactory::addBackend(DatabaseConnection::ParameterMap& parameters, ManagerID id) {
73 // Get the database type to locate a factory function.
74 auto it = parameters.find("type");
75 if (it == parameters.end()) {
76 isc_throw(InvalidParameter, "Forensic log backend specification lacks the "
77 "'type' keyword");
78 }
79
80 string db_type = it->second;
81 auto index = map_.find(db_type);
82
83 // No match?
84 if (index == map_.end()) {
85 if ((db_type == "mysql") || (db_type == "postgresql")) {
86 string libdhcp(db_type == "postgresql" ? "pgsql" : db_type);
87 isc_throw(InvalidType, "The Kea server has not been compiled with "
88 "support for configuration database type: " << db_type
89 << ". Did you forget to use -D "
90 << db_type << "=enabled during setup or to load libdhcp_"
91 << libdhcp << " hook library?");
92 }
93 isc_throw(InvalidType, "The type of the forensic log backend: '" <<
94 db_type << "' is not supported");
95 }
96
97 // Call the factory and push the pointer on sources.
98 auto backend = index->second.first(parameters);
99 if (!backend) {
100 isc_throw(Unexpected, "Forensic log backend " << db_type <<
101 " factory returned NULL");
102 }
103
104 // Add the parameters and an empty instance in case retry on startup is configured.
105 pool_[id] = pair<DatabaseConnection::ParameterMap, LegalLogMgrPtr>(parameters, LegalLogMgrPtr());
106
107 backend->open();
108
109 // Apply extra parameters.
110 if (parameters.find("request-parser-format") != parameters.end()) {
111 backend->setRequestFormatExpression(parameters["request-parser-format"]);
112 }
113 if (parameters.find("response-parser-format") != parameters.end()) {
114 backend->setResponseFormatExpression(parameters["response-parser-format"]);
115 }
116 if (parameters.find("timestamp-format") != parameters.end()) {
117 backend->setTimestampFormat(parameters["timestamp-format"]);
118 }
119
120 // Backend instance created successfully.
121 pool_[id] = pair<DatabaseConnection::ParameterMap, LegalLogMgrPtr>(parameters, backend);
122}
123
124void
125LegalLogMgrFactory::delAllBackends() {
126 pool_.clear();
127}
128
129void
130 LegalLogMgrFactory::delAllBackends(const std::string& db_type) {
131 auto it = pool_.begin();
132
133 while (it != pool_.end()) {
134 if (it->second.second && it->second.second->getType() == db_type) {
135 it = pool_.erase(it);
136 } else {
137 ++it;
138 }
139 }
140}
141
142 LegalLogMgrPtr&
143LegalLogMgrFactory::instance(ManagerID id) {
144 auto it = pool_.find(id);
145 if (it != pool_.end()) {
146 return (it->second.second);
147 }
148 // Usually the unit tests do not create the instances using LegalLogMgrFactory::addBackend or by
149 // calling parseConfig or parseDatabase or parseFile, so an empty instance must be returned when
150 // calling LegalLogMgrFactory::instance() - this function returns a reference, so it can not be
151 // created on the stack, it must be stored as a static variable.
152 static LegalLogMgrPtr backend;
153 if (!id) {
154 DatabaseConnection::ParameterMap parameters;
155 pool_[id] = pair<DatabaseConnection::ParameterMap, LegalLogMgrPtr>(parameters, backend);
156 return (pool_[id].second);
157 }
158 return (backend);
159}
160
161void
162LegalLogMgrFactory::setParameters(DatabaseConnection::ParameterMap parameters, ManagerID id) {
163 // Call LegalLogMgrFactory::instance first so that unit tests can have access to the empty
164 // entry in the pool.
165 LegalLogMgrFactory::instance(id);
166 auto it = pool_.find(id);
167 if (it != pool_.end()) {
168 it->second.first = parameters;
169 return;
170 }
171}
172
173 DatabaseConnection::ParameterMap
174LegalLogMgrFactory::getParameters(ManagerID id) {
175 auto it = pool_.find(id);
176 if (it != pool_.end()) {
177 return (it->second.first);
178 }
179 return (DatabaseConnection::ParameterMap());
180}
181
182bool
183LegalLogMgrFactory::delBackend(const string& db_type,
184 DatabaseConnection::ParameterMap& parameters,
185 bool if_unusable) {
186 bool deleted = false;
187 if (if_unusable) {
188 deleted = true;
189 }
190
191 for (auto it = pool_.begin(); it != pool_.end(); ++it) {
192 if (!it->second.second || it->second.second->getType() != db_type || it->second.first != parameters) {
193 continue;
194 }
195 if (if_unusable && (!(it->second.second->isUnusable()))) {
196 deleted = false;
197 continue;
198 }
199 it->second.second = LegalLogMgrPtr();
200 return (true);
201 }
202 return (deleted);
203}
204
205bool
206 LegalLogMgrFactory::delBackend(ManagerID id,
207 bool if_unusable) {
208 bool deleted = false;
209 if (if_unusable) {
210 deleted = true;
211 }
212
213 auto it = pool_.find(id);
214 if (it != pool_.end()) {
215 if (if_unusable && it->second.second && !it->second.second->isUnusable()) {
216 return (false);
217 }
218 it->second.second = LegalLogMgrPtr();
219 return (true);
220 }
221 return (deleted);
222}
223
224bool
225LegalLogMgrFactory::registeredFactory(const string& db_type) {
226 auto index = map_.find(db_type);
227 return (index != map_.end());
228}
229
230void
231LegalLogMgrFactory::logRegistered() {
232 stringstream txt;
233
234 for (auto const& x : map_) {
235 if (!txt.str().empty()) {
236 txt << " ";
237 }
238 txt << x.first;
239 }
240
241 LOG_INFO(dhcpsrv_logger, DHCPSRV_FORENSIC_BACKENDS_REGISTERED)
242 .arg(txt.str());
243}
244
245list<string>
246LegalLogMgrFactory::getDBVersions() {
247 list<string> result;
248 for (auto const& x : map_) {
249 auto version = x.second.second();
250 if (!version.empty()) {
251 result.push_back(version);
252 }
253 }
254
255 return (result);
256}
257
258bool
259LegalLogMgrFactory::haveInstance(std::string type) {
260 for (auto const& backend : pool_) {
261 if (backend.second.second && backend.second.second->getType() == type) {
262 return (true);
263 }
264 }
265 return (false);
266}
267
268} // end of namespace isc::dhcp
269} // end of namespace isc
270
isc::InvalidParameter
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
Definition exceptions/exceptions.h:124
isc::Unexpected
A generic exception that is thrown when an unexpected error condition occurs.
Definition exceptions/exceptions.h:153
isc::db::DatabaseConnection::ParameterMap
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Definition database_connection.h:137
isc::db::InvalidType
Invalid type exception.
Definition database_connection.h:62
isc::dhcp::LegalLogMgrFactory::map_
static std::map< std::string, std::pair< LegalLogMgrFactory::Factory, LegalLogMgrFactory::DBVersion > > map_
A map holding registered backend factory functions.
Definition legal_log_mgr_factory.h:195
isc::dhcp::LegalLogMgrFactory::unregisterBackendFactory
static bool unregisterBackendFactory(const std::string &db_type, bool no_log=false)
Unregisters the backend factory function for a given backend type.
Definition legal_log_mgr_factory.cc:53
isc::dhcp::LegalLogMgrFactory::addBackend
static void addBackend(db::DatabaseConnection::ParameterMap &parameters, ManagerID id=0)
Create an instance of a forensic log backend.
Definition legal_log_mgr_factory.cc:72
isc::dhcp::LegalLogMgrFactory::delAllBackends
static void delAllBackends()
Removes all backends from the pool.
Definition legal_log_mgr_factory.cc:125
isc::dhcp::LegalLogMgrFactory::registerBackendFactory
static bool registerBackendFactory(const std::string &db_type, const Factory &factory, bool no_log=false, DBVersion db_version=DBVersion())
Registers new backend factory function for a given backend type.
Definition legal_log_mgr_factory.cc:23
isc::dhcp::LegalLogMgrFactory::pool_
static LegalLogMgrPool pool_
Pointer to the forensic log backends pool.
Definition legal_log_mgr_factory.h:198
isc::dhcp::LegalLogMgrFactory::getParameters
static isc::db::DatabaseConnection::ParameterMap getParameters(ManagerID id=0)
Gets the forensic backend manager parameters.
Definition legal_log_mgr_factory.cc:174
isc::dhcp::LegalLogMgrFactory::logRegistered
static void logRegistered()
Logs out all registered backends.
Definition legal_log_mgr_factory.cc:231
isc::dhcp::LegalLogMgrFactory::delBackend
static bool delBackend(const std::string &db_type, db::DatabaseConnection::ParameterMap &parameters, bool if_unusable=false)
Delete a forensic backend manager.
Definition legal_log_mgr_factory.cc:183
isc::dhcp::LegalLogMgrFactory::registeredFactory
static bool registeredFactory(const std::string &db_type)
Check if a backend store factory was registered.
Definition legal_log_mgr_factory.cc:225
isc::dhcp::LegalLogMgrFactory::instance
static LegalLogMgrPtr & instance(ManagerID id=0)
Returns the forensic backend manager with specified ID.
Definition legal_log_mgr_factory.cc:143
isc::dhcp::LegalLogMgrFactory::getDBVersions
static std::list< std::string > getDBVersions()
Return extended version info for registered backends.
Definition legal_log_mgr_factory.cc:246
isc::dhcp::LegalLogMgrFactory::haveInstance
static bool haveInstance(std::string type)
Returns true is respective backend store is present, false otherwise.
Definition legal_log_mgr_factory.cc:259
isc::dhcp::LegalLogMgrFactory::setParameters
static void setParameters(isc::db::DatabaseConnection::ParameterMap parameters, ManagerID id=0)
Sets the forensic backend manager parameters.
Definition legal_log_mgr_factory.cc:162
isc::dhcp::LegalLogMgrFactory::io_service_
static isc::asiolink::IOServicePtr io_service_
The hook I/O service.
Definition legal_log_mgr_factory.h:192
version
int version()
returns Kea hooks version.
Definition d2/gss_tsig/version.cc:13
dhcpsrv_log.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition exceptions/exceptions.h:210
legal_log_mgr_factory.h
LOG_INFO
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition macros.h:20
LOG_DEBUG
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition macros.h:14
isc::asiolink::IOServicePtr
boost::shared_ptr< IOService > IOServicePtr
Defines a smart pointer to an IOService instance.
Definition io_service.h:28
isc::db
Definition audit_entry.cc:14
isc::dhcp
Definition dhcp4/client_handler.cc:20
isc::dhcp::dhcpsrv_logger
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition dhcpsrv_log.h:56
isc::dhcp::DHCPSRV_FORENSIC_BACKEND_REGISTER
const isc::log::MessageID DHCPSRV_FORENSIC_BACKEND_REGISTER
Definition dhcpsrv_messages.h:67
isc::dhcp::DHCPSRV_FORENSIC_BACKENDS_REGISTERED
const isc::log::MessageID DHCPSRV_FORENSIC_BACKENDS_REGISTERED
Definition dhcpsrv_messages.h:65
isc::dhcp::LegalLogMgrPtr
boost::shared_ptr< LegalLogMgr > LegalLogMgrPtr
Defines a smart pointer to a LegalLogMgr.
Definition legal_log_mgr.h:36
isc::dhcp::DHCPSRV_FORENSIC_BACKEND_DEREGISTER
const isc::log::MessageID DHCPSRV_FORENSIC_BACKEND_DEREGISTER
Definition dhcpsrv_messages.h:66
isc::dhcp::LegalLogMgrPool
std::map< ManagerID, std::pair< isc::db::DatabaseConnection::ParameterMap, LegalLogMgrPtr > > LegalLogMgrPool
LegalLogMgr pool.
Definition legal_log_mgr.h:387
isc::dhcp::ManagerID
uint64_t ManagerID
Manger ID used by hook libraries to retrieve respective LegalLogMgr instance.
Definition legal_log_mgr.h:384
isc::dhcp::DHCPSRV_DBG_TRACE
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
Definition dhcpsrv_log.h:26
isc
Defines the logger used by the top-level component of kea-lfc.
Definition agent_parser.cc:148