Kea 2.7.7
ha_callouts.cc
Go to the documentation of this file.
1// Copyright (C) 2017-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// Functions accessed by the hooks framework use C linkage to avoid the name
8// mangling that accompanies use of the C++ compiler as well as to avoid
9// issues related to namespaces.
10
11#include <config.h>
12
13#include <ha_impl.h>
14#include <ha_log.h>
15#include <asiolink/io_service.h>
18#include <dhcpsrv/cfgmgr.h>
21#include <hooks/hooks.h>
22#include <process/daemon.h>
23
24#include <sstream>
25#include <string>
26
27namespace isc {
28namespace ha {
29
31
32} // end of namespace isc::ha
33} // end of namespace isc
34
35using namespace isc::asiolink;
36using namespace isc::config;
37using namespace isc::data;
38using namespace isc::dhcp;
39using namespace isc::ha;
40using namespace isc::hooks;
41using namespace isc::process;
42using namespace std;
43
44extern "C" {
45
50 try {
51 isc::dhcp::NetworkStatePtr network_state;
52 handle.getArgument("network_state", network_state);
53 impl->startServices(network_state, HAServerType::DHCPv4);
55
56 } catch (const std::exception& ex) {
58 .arg(ex.what());
60 ostringstream os;
61 os << "Error: " << ex.what();
62 string error(os.str());
63 handle.setArgument("error", error);
64 return (1);
65 }
66 return (0);
67}
68
74 if (status == CalloutHandle::NEXT_STEP_DROP) {
75 return (0);
76 }
77
78 try {
79 impl->buffer4Receive(handle);
80
81 } catch (const std::exception& ex) {
83 .arg(ex.what());
84 return (1);
85 }
86
87 return (0);
88}
89
95 if (status == CalloutHandle::NEXT_STEP_DROP) {
96 return (0);
97 }
98
99 try {
100 impl->subnet4Select(handle);
101
102 } catch (const std::exception& ex) {
104 .arg(ex.what());
105 return (1);
106 }
107
108 return (0);
109}
110
111
117 if (status == CalloutHandle::NEXT_STEP_DROP ||
119 return (0);
120 }
121
122 try {
123 impl->leases4Committed(handle);
124
125 } catch (const std::exception& ex) {
127 .arg(ex.what());
128 return (1);
129 }
130
131 return (0);
132}
133
139 if (status == CalloutHandle::NEXT_STEP_DROP ||
141 return (0);
142 }
143
144 try {
145 impl->lease4ServerDecline(handle);
146 } catch (const std::exception& ex) {
148 .arg(ex.what());
149 return (1);
150 }
151
152 return (0);
153}
154
160 if (status == CalloutHandle::NEXT_STEP_SKIP) {
161 return (0);
162 }
163
164 try {
165 impl->lease4Expire(handle);
166 } catch (const std::exception& ex) {
168 .arg(ex.what());
169 return (1);
170 }
171
172 return (0);
173}
174
179 try {
180 isc::dhcp::NetworkStatePtr network_state;
181 handle.getArgument("network_state", network_state);
182 impl->startServices(network_state, HAServerType::DHCPv6);
184
185 } catch (const std::exception& ex) {
187 .arg(ex.what());
189 ostringstream os;
190 os << "Error: " << ex.what();
191 string error(os.str());
192 handle.setArgument("error", error);
193 return (1);
194 }
195 return (0);
196}
197
203 if (status == CalloutHandle::NEXT_STEP_DROP ||
205 return (0);
206 }
207
208 try {
209 impl->buffer6Receive(handle);
210
211 } catch (const std::exception& ex) {
213 .arg(ex.what());
214 return (1);
215 }
216
217 return (0);
218}
219
225 if (status == CalloutHandle::NEXT_STEP_DROP) {
226 return (0);
227 }
228
229 try {
230 impl->subnet6Select(handle);
231
232 } catch (const std::exception& ex) {
234 .arg(ex.what());
235 return (1);
236 }
237
238 return (0);
239}
240
246 if (status == CalloutHandle::NEXT_STEP_DROP ||
248 return (0);
249 }
250
251 try {
252 impl->leases6Committed(handle);
253
254 } catch (const std::exception& ex) {
256 .arg(ex.what());
257 return (1);
258 }
259
260 return (0);
261}
262
268 if (status == CalloutHandle::NEXT_STEP_SKIP) {
269 return (0);
270 }
271
272 try {
273 impl->lease6Expire(handle);
274 } catch (const std::exception& ex) {
276 .arg(ex.what());
277 return (1);
278 }
279
280 return (0);
281}
282
287 try {
288 impl->commandProcessed(handle);
289
290 } catch (const std::exception& ex) {
292 .arg(ex.what());
293 return (1);
294 }
295
296 return (0);
297}
298
301 try {
302 impl->heartbeatHandler(handle);
303
304 } catch (const std::exception& ex) {
306 .arg(ex.what());
307 return (1);
308 }
309
310 return (0);
311}
312
315 try {
316 impl->synchronizeHandler(handle);
317
318 } catch (const std::exception& ex) {
320 .arg(ex.what());
321 }
322
323 return (0);
324}
325
328 try {
329 impl->scopesHandler(handle);
330
331 } catch (const std::exception& ex) {
333 .arg(ex.what());
334 }
335
336 return (0);
337}
338
341 try {
342 impl->continueHandler(handle);
343
344 } catch (const std::exception& ex) {
346 .arg(ex.what());
347 }
348
349 return (0);
350}
351
354 try {
355 impl->maintenanceNotifyHandler(handle);
356
357 } catch (const std::exception& ex) {
359 .arg(ex.what());
360 }
361
362 return (0);
363}
364
367 try {
368 impl->maintenanceStartHandler(handle);
369
370 } catch (const std::exception& ex) {
372 .arg(ex.what());
373 }
374
375 return (0);
376}
377
380 try {
381 impl->maintenanceCancelHandler(handle);
382
383 } catch (const std::exception& ex) {
385 .arg(ex.what());
386 }
387
388 return (0);
389}
390
393 try {
394 impl->haResetHandler(handle);
395
396 } catch (const std::exception& ex) {
398 .arg(ex.what());
399 }
400
401 return (0);
402}
403
406 try {
407 impl->syncCompleteNotifyHandler(handle);
408 } catch (const std::exception& ex) {
410 .arg(ex.what());
411 }
412
413 return (0);
414}
415
420int load(LibraryHandle& handle) {
421 ConstElementPtr config = handle.getParameter("high-availability");
422 if (!config) {
424 return (1);
425 }
426
427 try {
428 // Make the hook library not loadable by d2 or ca.
429 uint16_t family = CfgMgr::instance().getFamily();
430 const std::string& proc_name = Daemon::getProcName();
431 if (family == AF_INET) {
432 if (proc_name != "kea-dhcp4") {
433 isc_throw(isc::Unexpected, "Bad process name: " << proc_name
434 << ", expected kea-dhcp4");
435 }
436 } else {
437 if (proc_name != "kea-dhcp6") {
438 isc_throw(isc::Unexpected, "Bad process name: " << proc_name
439 << ", expected kea-dhcp6");
440 }
441 }
442
443 impl = boost::make_shared<HAImpl>();
444 impl->configure(config);
445
446 handle.registerCommandCallout("ha-heartbeat", heartbeat_command);
447 handle.registerCommandCallout("ha-sync", sync_command);
448 handle.registerCommandCallout("ha-scopes", scopes_command);
449 handle.registerCommandCallout("ha-continue", continue_command);
450 handle.registerCommandCallout("ha-maintenance-notify", maintenance_notify_command);
451 handle.registerCommandCallout("ha-maintenance-start", maintenance_start_command);
452 handle.registerCommandCallout("ha-maintenance-cancel", maintenance_cancel_command);
453 handle.registerCommandCallout("ha-reset", ha_reset_command);
454 handle.registerCommandCallout("ha-sync-complete-notify", sync_complete_notify_command);
455
456 } catch (const std::exception& ex) {
458 .arg(ex.what());
459 return (CONTROL_RESULT_ERROR);
460 }
461
463 return (0);
464}
465
469int unload() {
470 if (impl) {
472 impl.reset();
473 }
475 return (0);
476}
477
482 return (1);
483}
484
485} // end extern "C"
A generic exception that is thrown when an unexpected error condition occurs.
uint16_t getFamily() const
Returns address family.
Definition cfgmgr.h:235
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:28
Per-packet callout handle.
CalloutNextStep
Specifies allowed next steps.
@ NEXT_STEP_DROP
drop the packet
@ NEXT_STEP_SKIP
skip the next processing step
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.
void registerCommandCallout(const std::string &command_name, CalloutPtr callout)
Register control command handler.
static std::string getProcName()
returns the process name This value is used as when forming the default PID file name
Definition daemon.cc:129
This file contains several functions and constants that are used for handling commands and responses ...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
int lease4_server_decline(CalloutHandle &handle)
lease4_server_decline callout implementation.
int subnet4_select(CalloutHandle &handle)
subnet4_select callout implementation.
int maintenance_cancel_command(CalloutHandle &handle)
ha-maintenance-cancel command handler implementation.
int dhcp4_srv_configured(CalloutHandle &handle)
dhcp4_srv_configured callout implementation.
int leases6_committed(CalloutHandle &handle)
leases6_committed callout implementation.
int sync_complete_notify_command(CalloutHandle &handle)
ha-sync-complete-notify command handler implementation.
int scopes_command(CalloutHandle &handle)
ha-scopes command handler implementation.
int heartbeat_command(CalloutHandle &handle)
Heartbeat command handler implementation.
int command_processed(CalloutHandle &handle)
command_processed callout implementation.
int leases4_committed(CalloutHandle &handle)
leases4_committed callout implementation.
int multi_threading_compatible()
This function is called to retrieve the multi-threading compatibility.
int maintenance_notify_command(CalloutHandle &handle)
ha-maintenance-notify command handler implementation.
int subnet6_select(CalloutHandle &handle)
subnet6_select callout implementation.
int unload()
This function is called when the library is unloaded.
int dhcp6_srv_configured(CalloutHandle &handle)
dhcp6_srv_configured callout implementation.
int lease6_expire(CalloutHandle &handle)
lease6_expire callout implementation.
int lease4_expire(CalloutHandle &handle)
lease4_expire callout implementation.
int buffer4_receive(CalloutHandle &handle)
buffer4_receive callout implementation.
int continue_command(CalloutHandle &handle)
ha-continue command handler implementation.
int ha_reset_command(CalloutHandle &handle)
ha-reset command handler implementation.
int maintenance_start_command(CalloutHandle &handle)
ha-maintenance-start command handler implementation.
int buffer6_receive(CalloutHandle &handle)
buffer6_receive callout implementation.
int sync_command(CalloutHandle &handle)
ha-sync command handler implementation.
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
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:29
@ error
Definition db_log.h:118
boost::shared_ptr< NetworkState > NetworkStatePtr
Pointer to the NetworkState object.
const isc::log::MessageID HA_BUFFER4_RECEIVE_FAILED
Definition ha_messages.h:11
boost::shared_ptr< HAImpl > HAImplPtr
Pointer to the High Availability hooks library implementation.
Definition ha_impl.h:289
const isc::log::MessageID HA_LEASE4_EXPIRE_FAILED
Definition ha_messages.h:53
const isc::log::MessageID HA_DEINIT_OK
Definition ha_messages.h:37
const isc::log::MessageID HA_COMMAND_PROCESSED_FAILED
Definition ha_messages.h:19
const isc::log::MessageID HA_LEASES4_COMMITTED_FAILED
Definition ha_messages.h:60
const isc::log::MessageID HA_CONTINUE_HANDLER_FAILED
Definition ha_messages.h:36
const isc::log::MessageID HA_MAINTENANCE_CANCEL_HANDLER_FAILED
Definition ha_messages.h:92
const isc::log::MessageID HA_HEARTBEAT_HANDLER_FAILED
Definition ha_messages.h:46
isc::log::Logger ha_logger("ha-hooks")
Definition ha_log.h:17
const isc::log::MessageID HA_RESET_HANDLER_FAILED
const isc::log::MessageID HA_DHCP6_START_SERVICE_FAILED
Definition ha_messages.h:39
const isc::log::MessageID HA_MAINTENANCE_START_HANDLER_FAILED
const isc::log::MessageID HA_BUFFER6_RECEIVE_FAILED
Definition ha_messages.h:15
const isc::log::MessageID HA_SYNC_COMPLETE_NOTIFY_HANDLER_FAILED
const isc::log::MessageID HA_SUBNET6_SELECT_FAILED
HAImplPtr impl
const isc::log::MessageID HA_LEASE4_SERVER_DECLINE_FAILED
Definition ha_messages.h:56
const isc::log::MessageID HA_INIT_OK
Definition ha_messages.h:49
const isc::log::MessageID HA_LEASE6_EXPIRE_FAILED
Definition ha_messages.h:57
const isc::log::MessageID HA_SUBNET4_SELECT_FAILED
const isc::log::MessageID HA_MISSING_CONFIGURATION
const isc::log::MessageID HA_LEASES6_COMMITTED_FAILED
Definition ha_messages.h:63
const isc::log::MessageID HA_DHCP4_START_SERVICE_FAILED
Definition ha_messages.h:38
const isc::log::MessageID HA_CONFIGURATION_FAILED
Definition ha_messages.h:25
const isc::log::MessageID HA_MAINTENANCE_NOTIFY_HANDLER_FAILED
Definition ha_messages.h:97
const isc::log::MessageID HA_SYNC_HANDLER_FAILED
const isc::log::MessageID HA_SCOPES_HANDLER_FAILED
Defines the logger used by the top-level component of kea-lfc.