Kea 3.3.3
ping_check_callouts.cc
Go to the documentation of this file.
1// Copyright (C) 2023-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
11#include <dhcpsrv/cfgmgr.h>
12#include <hooks/hooks.h>
14#include <process/daemon.h>
15
16#include <string>
17
18#include <ping_check_log.h>
19
20namespace isc {
21namespace ping_check {
22
25
26} // end of namespace ping_check
27} // end of namespace isc
28
29using namespace isc;
30using namespace isc::asiolink;
31using namespace isc::log;
32using namespace isc::data;
33using namespace isc::db;
34using namespace isc::dhcp;
35using namespace isc::ping_check;
36using namespace isc::hooks;
37using namespace isc::process;
38using namespace std;
39
40// Functions accessed by the hooks framework use C linkage to avoid the name
41// mangling that accompanies use of the C++ compiler as well as to avoid
42// issues related to namespaces.
43extern "C" {
44
49 try {
50 SrvConfigPtr server_config;
51 handle.getArgument("server_config", server_config);
52 mgr->updateSubnetConfig(server_config);
53
54 NetworkStatePtr network_state;
55 handle.getArgument("network_state", network_state);
56
57 // Schedule a start of the services. This ensures we begin after
58 // the dust has settled and Kea MT mode has been firmly established.
59 mgr->startService(network_state);
61 } catch (const std::exception& ex) {
63 .arg(ex.what());
64
66 ostringstream os;
67 os << "Error: " << ex.what();
68 string error(os.str());
69 handle.setArgument("error", error);
70 return (1);
71 }
72
73 return (0);
74}
75
87 AuditEntryCollectionPtr audit_entries;
88 handle.getArgument("audit_entries", audit_entries);
89
90 auto const& object_type_idx = audit_entries->get<AuditEntryObjectTypeTag>();
91 auto range = object_type_idx.equal_range("dhcp4_subnet");
92 if (std::distance(range.first, range.second)) {
93 try {
94 // Server config has been committed, so use the current configuration.
95 mgr->updateSubnetConfig(CfgMgr::instance().getCurrentCfg());
96 } catch (const std::exception& ex) {
98 .arg(ex.what());
99 return (1);
100 }
101 }
102
103 return (0);
104}
105
111 if (status == CalloutHandle::NEXT_STEP_DROP ||
113 return (0);
114 }
115
116 Pkt4Ptr query4;
117 Lease4Ptr lease4;
118 ParkingLotHandlePtr parking_lot;
119 try {
120 // Get all arguments available for the leases4_committed hook point.
121 // If any of these arguments is not available this is a programmatic
122 // error. An exception will be thrown which will be caught by the
123 // caller and logged.
124 handle.getArgument("query4", query4);
125
126 Lease4CollectionPtr leases4;
127 handle.getArgument("leases4", leases4);
128
129 uint32_t offer_lifetime;
130 handle.getArgument("offer_lifetime", offer_lifetime);
131
132 Lease4Ptr old_lease;
133 handle.getArgument("old_lease", old_lease);
134
135 ConstHostPtr host;
136 handle.getArgument("host", host);
137
138 if (query4->getType() != DHCPDISCOVER) {
139 isc_throw(InvalidOperation, "query4 is not a DHCPDISCOVER");
140 }
141
142 if (!leases4) {
143 isc_throw(InvalidOperation, "leases4 is null");
144 }
145
146 if (!leases4->empty()) {
147 lease4 = (*leases4)[0];
148 }
149
150 if (!lease4) {
151 // lease has been reused or there is no address available to check.
154 return (0);
155 }
156
157 // Fetch the parking lot. If it's empty the server is not employing
158 // parking, which is fine.
159 // Create a reference to the parked packet. This signals that we have a
160 // stake in unparking it.
161 parking_lot = handle.getParkingLotHandlePtr();
162 if (parking_lot) {
163 parking_lot->reference(query4);
164 }
165
166 // Get configuration based on the lease's subnet.
167 auto const& config = mgr->getScopedConfig(lease4);
168
169 // Call shouldPing() to determine if we should ping check or not.
170 // - status == PARK - ping check it
171 // - status == CONTINUE - check not needed, release DHCPOFFER to client
172 // - status == DROP - duplicate check, drop the duplicate DHCPOFFER
173 status = mgr->shouldPing(lease4, query4, old_lease, host, config);
174 handle.setStatus(status);
175 if (status == CalloutHandle::NEXT_STEP_PARK) {
176 mgr->startPing(lease4, query4, parking_lot, config);
177 } else {
178 // Dereference the parked packet. This releases our stake in it.
179 if (parking_lot) {
180 parking_lot->dereference(query4);
181 }
182 }
183
184 } catch (const std::exception& ex) {
186 .arg(query4 ? query4->getLabel() : "<no query>")
187 .arg(lease4 ? lease4->addr_.toText() : "<no lease>")
188 .arg(ex.what());
189 // Make sure we dereference.
190 if (parking_lot) {
191 parking_lot->dereference(query4);
192 }
193
194 return (1);
195 }
196
197 return (0);
198}
199
204int load(LibraryHandle& handle) {
205 try {
206 // Make the hook library only loadable by kea-dhcp4.
207 const string& proc_name = Daemon::getProcName();
208 if (proc_name != "kea-dhcp4") {
209 isc_throw(isc::Unexpected, "Bad process name: " << proc_name
210 << ", expected kea-dhcp4");
211 }
212
213 // Instantiate the manager singleton.
214 mgr.reset(new PingCheckMgr());
215
216 // Configure the manager using the hook library's parameters.
217 ConstElementPtr json = handle.getParameters();
218 mgr->configure(json);
219 } catch (const exception& ex) {
221 .arg(ex.what());
222 return (1);
223 }
224
226 return (0);
227}
228
232int unload() {
233 if (mgr) {
235 mgr.reset();
236 }
238 return (0);
239}
240
245 return (1);
246}
247
248} // end extern "C"
CalloutNextStep
Specifies allowed next steps.
@ NEXT_STEP_PARK
park the packet
@ NEXT_STEP_DROP
drop the packet
@ NEXT_STEP_SKIP
skip the next processing step
A generic exception that is thrown if a function is called in a prohibited way.
A generic exception that is thrown when an unexpected error condition occurs.
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:29
Per-packet callout handle.
@ NEXT_STEP_DROP
drop the packet
ParkingLotHandlePtr getParkingLotHandlePtr() const
Returns pointer to the parking lot handle for this hook point.
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 getParameters()
Get configuration parameter common code.
static std::string getProcName()
returns the process name This value is used as when forming the default PID file name
Definition daemon.cc:156
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#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:30
@ error
Definition db_log.h:127
boost::shared_ptr< AuditEntryCollection > AuditEntryCollectionPtr
boost::shared_ptr< Lease4Collection > Lease4CollectionPtr
A shared pointer to the collection of IPv4 leases.
Definition lease.h:551
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Definition pkt4.h:556
boost::shared_ptr< SrvConfig > SrvConfigPtr
Non-const pointer to the SrvConfig.
boost::shared_ptr< NetworkState > NetworkStatePtr
Pointer to the NetworkState object.
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
Definition host.h:843
@ DHCPDISCOVER
Definition dhcp4.h:235
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition lease.h:343
boost::shared_ptr< ParkingLotHandle > ParkingLotHandlePtr
Pointer to the parking lot handle.
const int DBGLVL_TRACE_DETAIL
Trace detailed operations.
PingCheckMgrPtr mgr
PingCheckMgr singleton.
isc::log::Logger ping_check_logger("ping-check-hooks")
boost::shared_ptr< PingCheckMgr > PingCheckMgrPtr
Defines a shared pointer to a PingCheckMgr.
Defines the logger used by the top-level component of kea-lfc.
int dhcp4_srv_configured(CalloutHandle &handle)
dhcp4_srv_configured implementation.
int multi_threading_compatible()
This function is called to retrieve the multi-threading compatibility.
int lease4_offer(CalloutHandle &handle)
lease4_offer callout implementation.
int unload()
This function is called when the library is unloaded.
int cb4_updated(CalloutHandle &handle)
cb4_updated callout implementation.
int load(LibraryHandle &handle)
This function is called when the library is loaded.
const isc::log::MessageID PING_CHECK_LOAD_ERROR
const isc::log::MessageID PING_CHECK_LEASE4_OFFER_FAILED
const isc::log::MessageID PING_CHECK_NO_LEASE_OR_LEASE_REUSED
const isc::log::MessageID PING_CHECK_DHCP4_SRV_CONFIGURED_FAILED
const isc::log::MessageID PING_CHECK_CB4_UPDATE_FAILED
const isc::log::MessageID PING_CHECK_UNLOAD
const isc::log::MessageID PING_CHECK_LOAD_OK
Tag used to access index by object type.