Kea 3.1.0
lease_query_callouts.cc
Go to the documentation of this file.
1// Copyright (C) 2020-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
12#include <hooks/hooks.h>
13#include <dhcpsrv/cfgmgr.h>
14#include <lease_query_log.h>
16#include <blq_service.h>
17#include <process/daemon.h>
18#include <stats/stats_mgr.h>
19
20#include <string>
21#include <vector>
22
23using namespace isc;
24using namespace isc::asiolink;
25using namespace isc::lease_query;
26using namespace isc::data;
27using namespace isc::db;
28using namespace isc::dhcp;
29using namespace isc::hooks;
30using namespace isc::log;
31using namespace isc::process;
32using namespace isc::stats;
33using namespace std;
34
35namespace {
41ConstElementPtr getConfig(LibraryHandle& handle) {
42 const std::vector<std::string> names = handle.getParameterNames();
44
45 for (auto const& name : names) {
46 ConstElementPtr value = handle.getParameter(name);
47 if (value) {
48 config->set(name, value);
49 }
50 }
51
52 // Note checkKeywords() will throw DhcpConfigError if there is a problem.
54 return (config);
55}
56
63int extended_info4_upgrade(CalloutHandle& handle) {
64 return (LeaseQueryImpl4::upgradeHandler(handle));
65}
66
73int extended_info6_upgrade(CalloutHandle& handle) {
74 return (LeaseQueryImpl6::upgradeHandler(handle));
75}
76} // end of anonymous namespace
77
78extern "C" {
79
103 if (status == CalloutHandle::NEXT_STEP_DROP) {
104 return (0);
105 }
106
107 // Get the received message.
108 Pkt4Ptr query;
109 handle.getArgument("query4", query);
110 try {
111 // If it's not already unpacked, unpack it
113 query->unpack();
114 }
115 } catch (const std::exception& ex) {
118 .arg(query->getRemoteAddr().toText())
119 .arg(query->getLocalAddr().toText())
120 .arg(query->getIface())
121 .arg(ex.what());
122 // Increase the statistics of parse failures and dropped packets.
123 StatsMgr::instance().addValue("pkt4-parse-failed",
124 static_cast<int64_t>(1));
125 StatsMgr::instance().addValue("pkt4-receive-drop",
126 static_cast<int64_t>(1));
128 return (0);
129 }
130
131 // Not a lease query, so return without handling it.
132 // Make sure status is SKIP so it doesn't get unpacked again.
133 if (query->getType() != DHCPLEASEQUERY) {
135 return (0);
136 }
137
140 StatsMgr::instance().addValue("pkt4-lease-query-received", static_cast<int64_t>(1));
141
142 try {
144 } catch (const std::exception& ex) {
145 // Failed to parse the packet.
149 .arg(ex.what());
150
151 StatsMgr::instance().addValue("pkt4-receive-drop",
152 static_cast<int64_t>(1));
154 return (0);
155 }
156
157 // We always set status to DROP as the query has been handled.
159 return (0);
160}
161
185 if (status == CalloutHandle::NEXT_STEP_DROP) {
186 return (0);
187 }
188
189 // Get the received message.
190 Pkt6Ptr query;
191 handle.getArgument("query6", query);
192
193 try {
194 // If it's not already unpacked, unpack it.
196 query->unpack();
197 }
198 } catch (const std::exception& ex) {
201 .arg(query->getRemoteAddr().toText())
202 .arg(query->getLocalAddr().toText())
203 .arg(query->getIface())
204 .arg(ex.what());
205 // Increase the statistics of parse failures and dropped packets.
206 StatsMgr::instance().addValue("pkt6-parse-failed",
207 static_cast<int64_t>(1));
208 StatsMgr::instance().addValue("pkt6-receive-drop",
209 static_cast<int64_t>(1));
211 return (0);
212 }
213
214 // Not a lease query, so return without handling it.
215 // Make sure status is SKIP so it doesn't get unpacked again.
216 if (query->getType() != DHCPV6_LEASEQUERY) {
218 return (0);
219 }
220
223 StatsMgr::instance().addValue("pkt6-lease-query-received", static_cast<int64_t>(1));
224
225 try {
227 } catch (const std::exception& ex) {
228 // Log that we failed to process the packet.
232 .arg(ex.what());
233 }
234
235 // We always set status to DROP as the query has been handled.
237 return (0);
238}
239
245int load(LibraryHandle& handle) {
246 try {
247
248 // Make the hook library not loadable by d2 or ca.
249 uint16_t family = CfgMgr::instance().getFamily();
250 const std::string& proc_name = Daemon::getProcName();
251 if (family == AF_INET) {
252 if (proc_name != "kea-dhcp4") {
253 isc_throw(isc::Unexpected, "Bad process name: " << proc_name
254 << ", expected kea-dhcp4");
255 }
256
257 StatsMgr::instance().setValue("pkt4-lease-query-received",
258 static_cast<int64_t>(0));
259 StatsMgr::instance().setValue("pkt4-lease-query-response-unknown-sent",
260 static_cast<int64_t>(0));
261 StatsMgr::instance().setValue("pkt4-lease-query-response-unassigned-sent",
262 static_cast<int64_t>(0));
263 StatsMgr::instance().setValue("pkt4-lease-query-response-active-sent",
264 static_cast<int64_t>(0));
265 handle.registerCommandCallout("extended-info4-upgrade",
266 extended_info4_upgrade);
267 } else {
268 if (proc_name != "kea-dhcp6") {
269 isc_throw(isc::Unexpected, "Bad process name: " << proc_name
270 << ", expected kea-dhcp6");
271 }
272
273 StatsMgr::instance().setValue("pkt6-lease-query-received",
274 static_cast<int64_t>(0));
275 StatsMgr::instance().setValue("pkt6-lease-query-reply-sent",
276 static_cast<int64_t>(0));
277 handle.registerCommandCallout("extended-info6-upgrade",
278 extended_info6_upgrade);
279 }
280
281 ConstElementPtr config = getConfig(handle);
284 } catch (const std::exception& ex) {
286 .arg(ex.what());
289 return (1);
290 }
291
293 return (0);
294}
295
301int unload() {
302 // Helps current running works to terminate.
304
306
307 // Stop and Destroy the BulkLeaseQueryService instance.
309
310 // Destroy the LeaseQueryImpl instance.
312
313 // Remove lease-query stats.
314 if (CfgMgr::instance().getFamily() == AF_INET) {
315 StatsMgr::instance().del("pkt4-lease-query-received");
316 StatsMgr::instance().del("pkt4-lease-query-response-unknown-sent");
317 StatsMgr::instance().del("pkt4-lease-query-response-unassigned-sent");
318 StatsMgr::instance().del("pkt4-lease-query-response-active-sent");
319 } else {
320 StatsMgr::instance().del("pkt6-lease-query-received");
321 StatsMgr::instance().del("pkt6-lease-query-reply-sent");
322 }
323
325 return (0);
326}
327
339
349 // Only repopulate the list if CB updated subnets.
350 AuditEntryCollectionPtr audit_entries;
351 handle.getArgument("audit_entries", audit_entries);
352
353 auto const& object_type_idx = audit_entries->get<AuditEntryObjectTypeTag>();
354 auto range = object_type_idx.equal_range("dhcp6_subnet");
355 if (std::distance(range.first, range.second)) {
356 try {
358 const LeaseQueryImpl6& impl6 = dynamic_cast<const LeaseQueryImpl6&>
360 LeaseQueryImpl6& impl = const_cast<LeaseQueryImpl6&>(impl6);
361 impl.populatePrefixLengthList(cfg);
362 } catch (const std::exception& ex) {
363 const string error("Error: populatePrefixLengthList() failed");
364 handle.setArgument("error", ex.what());
365 return (1);
366 }
367 }
368
369 return (0);
370}
371
379 try {
380 SrvConfigPtr cfg;
381 handle.getArgument("server_config", cfg);
382 const LeaseQueryImpl6& impl6 = dynamic_cast<const LeaseQueryImpl6&>
384 LeaseQueryImpl6& impl = const_cast<LeaseQueryImpl6&>(impl6);
385 impl.populatePrefixLengthList(cfg);
386 } catch (const std::exception& ex) {
388 const string error("Error: populatePrefixLengthList() failed");
389 handle.setArgument("error", ex.what());
390 return (1);
391 }
392
395 return (0);
396}
397
402 return (1);
403}
404
405} // end extern "C"
CalloutNextStep
Specifies allowed next steps.
@ NEXT_STEP_DROP
drop the packet
@ NEXT_STEP_SKIP
skip the next processing step
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:304
A generic exception that is thrown when an unexpected error condition occurs.
static void checkKeywords(const SimpleKeywords &keywords, isc::data::ConstElementPtr scope)
Checks acceptable keywords with their expected type.
uint16_t getFamily() const
Returns address family.
Definition cfgmgr.h:246
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:29
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition cfgmgr.cc:116
Per-packet callout handle.
@ NEXT_STEP_DROP
drop the packet
CalloutNextStep getStatus() const
Returns the next processing step.
void setStatus(const CalloutNextStep next)
Sets the next processing step.
void getArgument(const std::string &name, T &value) const
Get argument.
void setArgument(const std::string &name, T value)
Set argument.
isc::data::ConstElementPtr getParameter(const std::string &name)
Returns configuration parameter for the library.
std::vector< std::string > getParameterNames()
Returns names of configuration parameters for the library.
void registerCommandCallout(const std::string &command_name, CalloutPtr callout)
Register control command handler.
static void reset()
Reset the sole instance of BulkLeaseQueryService.
static void doStartListener()
Start the listener.
static int upgradeHandler(hooks::CalloutHandle &handle)
Upgrade extended information.
static std::string leaseQueryLabel(const dhcp::Pkt4Ptr &packet)
Convenience method for generating per packet logging info.
Provides configuration and control flow for processing queries.
static std::string leaseQueryLabel(const dhcp::Pkt6Ptr &packet)
Convenience method for generating per packet logging info.
static int upgradeHandler(hooks::CalloutHandle &handle)
Upgrade extended information.
static void createImpl(uint16_t family, isc::data::ConstElementPtr config)
Creates the LeaseQueryImpl singleton.
static LeaseQueryImpl & getMutableImpl()
Fetch the LeaseQueryImpl singleton.
static const LeaseQueryImpl & getImpl()
Fetch the LeaseQueryImpl singleton.
static void destroyImpl()
Destroy the LeaseQueryImpl singleton.
virtual void processQuery(isc::dhcp::PktPtr base_query) const =0
Processes a single client Lease Query.
static bool terminated_
Terminated flag.
static const isc::data::SimpleKeywords LEASE_QUERY_KEYWORDS
Keywords for Lease Query configuration.
isc::asiolink::IOServicePtr getIOService()
Get the hook I/O service.
static std::string getProcName()
returns the process name This value is used as when forming the default PID file name
Definition daemon.cc:151
static StatsMgr & instance()
Statistics Manager accessor method.
@ DHCPV6_LEASEQUERY
Definition dhcp6.h:222
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
bool del(const std::string &name)
Removes specified statistic.
void setValue(const std::string &name, const int64_t value)
Records absolute integer observation.
void addValue(const std::string &name, const int64_t value)
Records incremental integer observation.
int dhcp4_srv_configured(CalloutHandle &)
dhcp4_srv_configured callout implementation.
int multi_threading_compatible()
This function is called to retrieve the multi-threading compatibility.
int unload()
This function is called when the library is unloaded.
int dhcp6_srv_configured(CalloutHandle &handle)
dhcp6_srv_configured callout implementation.
int cb6_updated(CalloutHandle &handle)
This callout is called at the "cb6_updated" hook.
int buffer4_receive(CalloutHandle &handle)
This callout is called at the "buffer4_receive" hook.
int buffer6_receive(CalloutHandle &handle)
This callout is called at the "buffer6_receive" hook.
int load(LibraryHandle &handle)
This function is called when the library is loaded.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition macros.h:32
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition macros.h:20
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition macros.h:14
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:29
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
@ error
Definition db_log.h:118
boost::shared_ptr< AuditEntryCollection > AuditEntryCollectionPtr
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Definition pkt4.h:555
boost::shared_ptr< SrvConfig > SrvConfigPtr
Non-const pointer to the SrvConfig.
@ DHCPLEASEQUERY
Definition dhcp4.h:244
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
Definition pkt6.h:31
const isc::log::MessageID LEASE_QUERY_UNLOAD_OK
const isc::log::MessageID DHCP4_LEASE_QUERY_RECEIVED
const isc::log::MessageID LEASE_QUERY_LOAD_OK
const isc::log::MessageID LEASE_QUERY_LOAD_FAILED
const isc::log::MessageID DHCP6_LEASE_QUERY_PACKET_UNPACK_FAILED
const isc::log::MessageID DHCP4_LEASE_QUERY_PROCESS_FAILED
const isc::log::MessageID DHCP4_LEASE_QUERY_PACKET_UNPACK_FAILED
const isc::log::MessageID DHCP6_LEASE_QUERY_PROCESS_FAILED
isc::log::Logger lease_query_logger("lease-query-hooks")
const isc::log::MessageID DHCP6_LEASE_QUERY_RECEIVED
const int DBGLVL_TRACE_BASIC
Trace basic operations.
Defines the logger used by the top-level component of kea-lfc.
Tag used to access index by object type.