Kea 3.0.2-git
ping_check_callouts.cc
Go to the documentation of this file.
1// Copyright (C) 2023-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
11#include <dhcpsrv/cfgmgr.h>
12#include <ping_check_log.h>
13#include <ping_check_mgr.h>
14#include <hooks/hooks.h>
15#include <process/daemon.h>
16#include <string>
17
18namespace isc {
19namespace ping_check {
20
23
24} // end of namespace ping_check
25} // end of namespace isc
26
27using namespace isc;
28using namespace isc::asiolink;
29using namespace isc::log;
30using namespace isc::data;
31using namespace isc::db;
32using namespace isc::dhcp;
33using namespace isc::ping_check;
34using namespace isc::hooks;
35using namespace isc::process;
36using namespace std;
37
38// Functions accessed by the hooks framework use C linkage to avoid the name
39// mangling that accompanies use of the C++ compiler as well as to avoid
40// issues related to namespaces.
41extern "C" {
42
47 try {
48 SrvConfigPtr server_config;
49 handle.getArgument("server_config", server_config);
50 mgr->updateSubnetConfig(server_config);
51
52 NetworkStatePtr network_state;
53 handle.getArgument("network_state", network_state);
54
55 // Schedule a start of the services. This ensures we begin after
56 // the dust has settled and Kea MT mode has been firmly established.
57 mgr->startService(network_state);
59 } catch (const std::exception& ex) {
61 .arg(ex.what());
62
64 ostringstream os;
65 os << "Error: " << ex.what();
66 string error(os.str());
67 handle.setArgument("error", error);
68 return (1);
69 }
70
71 return (0);
72}
73
85 AuditEntryCollectionPtr audit_entries;
86 handle.getArgument("audit_entries", audit_entries);
87
88 auto const& object_type_idx = audit_entries->get<AuditEntryObjectTypeTag>();
89 auto range = object_type_idx.equal_range("dhcp4_subnet");
90 if (std::distance(range.first, range.second)) {
91 try {
92 // Server config has been committed, so use the current configuration.
93 mgr->updateSubnetConfig(CfgMgr::instance().getCurrentCfg());
94 } catch (const std::exception& ex) {
96 .arg(ex.what());
97 return (1);
98 }
99 }
100
101 return (0);
102}
103
109 if (status == CalloutHandle::NEXT_STEP_DROP ||
111 return (0);
112 }
113
114 Pkt4Ptr query4;
115 Lease4Ptr lease4;
116 ParkingLotHandlePtr parking_lot;
117 try {
118 // Get all arguments available for the leases4_committed hook point.
119 // If any of these arguments is not available this is a programmatic
120 // error. An exception will be thrown which will be caught by the
121 // caller and logged.
122 handle.getArgument("query4", query4);
123
124 Lease4CollectionPtr leases4;
125 handle.getArgument("leases4", leases4);
126
127 uint32_t offer_lifetime;
128 handle.getArgument("offer_lifetime", offer_lifetime);
129
130 Lease4Ptr old_lease;
131 handle.getArgument("old_lease", old_lease);
132
133 ConstHostPtr host;
134 handle.getArgument("host", host);
135
136 if (query4->getType() != DHCPDISCOVER) {
137 isc_throw(InvalidOperation, "query4 is not a DHCPDISCOVER");
138 }
139
140 if (!leases4) {
141 isc_throw(InvalidOperation, "leases4 is null");
142 }
143
144 if (!leases4->empty()) {
145 lease4 = (*leases4)[0];
146 }
147
148 if (!lease4) {
149 // lease has been reused or there is no address available to check.
152 return (0);
153 }
154
155 // Fetch the parking lot. If it's empty the server is not employing
156 // parking, which is fine.
157 // Create a reference to the parked packet. This signals that we have a
158 // stake in unparking it.
159 parking_lot = handle.getParkingLotHandlePtr();
160 if (parking_lot) {
161 parking_lot->reference(query4);
162 }
163
164 // Get configuration based on the lease's subnet.
165 auto const& config = mgr->getScopedConfig(lease4);
166
167 // Call shouldPing() to determine if we should ping check or not.
168 // - status == PARK - ping check it
169 // - status == CONTINUE - check not needed, release DHCPOFFER to client
170 // - status == DROP - duplicate check, drop the duplicate DHCPOFFER
171 status = mgr->shouldPing(lease4, query4, old_lease, host, config);
172 handle.setStatus(status);
173 if (status == CalloutHandle::NEXT_STEP_PARK) {
174 mgr->startPing(lease4, query4, parking_lot, config);
175 } else {
176 // Dereference the parked packet. This releases our stake in it.
177 if (parking_lot) {
178 parking_lot->dereference(query4);
179 }
180 }
181
182 } catch (const std::exception& ex) {
184 .arg(query4 ? query4->getLabel() : "<no query>")
185 .arg(lease4 ? lease4->addr_.toText() : "<no lease>")
186 .arg(ex.what());
187 // Make sure we dereference.
188 if (parking_lot) {
189 parking_lot->dereference(query4);
190 }
191
192 return (1);
193 }
194
195 return (0);
196}
197
202int load(LibraryHandle& handle) {
203 try {
204 // Make the hook library only loadable by kea-dhcp4.
205 const string& proc_name = Daemon::getProcName();
206 if (proc_name != "kea-dhcp4") {
207 isc_throw(isc::Unexpected, "Bad process name: " << proc_name
208 << ", expected kea-dhcp4");
209 }
210
211 // Instantiate the manager singleton.
212 mgr.reset(new PingCheckMgr());
213
214 // Configure the manager using the hook library's parameters.
215 ConstElementPtr json = handle.getParameters();
216 mgr->configure(json);
217 } catch (const exception& ex) {
219 .arg(ex.what());
220 return (1);
221 }
222
224 return (0);
225}
226
230int unload() {
231 if (mgr) {
233 mgr.reset();
234 }
236 return (0);
237}
238
243 return (1);
244}
245
246} // 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:151
#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:29
@ error
Definition db_log.h:118
boost::shared_ptr< AuditEntryCollection > AuditEntryCollectionPtr
boost::shared_ptr< Lease4Collection > Lease4CollectionPtr
A shared pointer to the collection of IPv4 leases.
Definition lease.h:523
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.
boost::shared_ptr< NetworkState > NetworkStatePtr
Pointer to the NetworkState object.
@ DHCPDISCOVER
Definition dhcp4.h:235
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
Definition host.h:840
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition lease.h:315
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.