Kea 3.3.3
run_script_callouts.cc
Go to the documentation of this file.
1// Copyright (C) 2021-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
12#include <dhcp/option6_ia.h>
13#include <dhcp/pkt4.h>
14#include <dhcp/pkt6.h>
15#include <dhcpsrv/cfgmgr.h>
16#include <dhcpsrv/lease.h>
17#include <dhcpsrv/subnet.h>
18#include <hooks/hooks.h>
19#include <process/daemon.h>
21
22#include <string>
23
24#include <run_script_log.h>
25
26namespace isc {
27namespace run_script {
28
30
31} // namespace run_script
32} // namespace isc
33
34using namespace isc;
35using namespace isc::asiolink;
36using namespace isc::data;
37using namespace isc::dhcp;
38using namespace isc::hooks;
39using namespace isc::process;
40using namespace isc::run_script;
41using namespace isc::util;
42using namespace std;
43
44// Functions accessed by the hooks framework use C linkage to avoid the name
45// mangling that accompanies use of the C++ compiler as well as to avoid
46// issues related to namespaces.
47extern "C" {
48
53int load(LibraryHandle& handle) {
54 try {
55 // Make the hook library not loadable by d2.
56 uint16_t family = CfgMgr::instance().getFamily();
57 const string& proc_name = Daemon::getProcName();
58 if (family == AF_INET) {
59 if (proc_name != "kea-dhcp4") {
60 isc_throw(isc::Unexpected, "Bad process name: " << proc_name
61 << ", expected kea-dhcp4");
62 }
63 } else {
64 if (proc_name != "kea-dhcp6") {
65 isc_throw(isc::Unexpected, "Bad process name: " << proc_name
66 << ", expected kea-dhcp6");
67 }
68 }
69
70 impl.reset(new RunScriptImpl());
71 impl->configure(handle);
72 } catch (const exception& ex) {
74 .arg(ex.what());
75 return (1);
76 }
77
79 return (0);
80}
81
85int unload() {
86 impl.reset();
88 return (0);
89}
90
97 if (status == CalloutHandle::NEXT_STEP_DROP ||
99 return (0);
100 }
101 ProcessEnvVars vars;
102 Pkt4Ptr pkt4;
103 handle.getArgument("query4", pkt4);
104 RunScriptImpl::extractPkt4(vars, pkt4, "QUERY4");
105 ConstSubnet4Ptr subnet4;
106 handle.getArgument("subnet4", subnet4);
107 RunScriptImpl::extractSubnet4(vars, subnet4, "SUBNET4");
108 ClientIdPtr clientid;
109 handle.getArgument("clientid", clientid);
110 RunScriptImpl::extractClientId(vars, clientid, "PKT4_CLIENT_ID");
111 HWAddrPtr hwaddr;
112 handle.getArgument("hwaddr", hwaddr);
113 RunScriptImpl::extractHWAddr(vars, hwaddr, "PKT4_HWADDR");
114 Lease4Ptr lease4;
115 handle.getArgument("lease4", lease4);
116 RunScriptImpl::extractLease4(vars, lease4, "LEASE4");
117 ProcessArgs args;
118 args.push_back("lease4_renew");
119 impl->runScript(args, vars);
120 return (0);
121}
122
129 if (status == CalloutHandle::NEXT_STEP_DROP ||
131 return (0);
132 }
133 ProcessEnvVars vars;
134 Lease4Ptr lease4;
135 handle.getArgument("lease4", lease4);
136 RunScriptImpl::extractLease4(vars, lease4, "LEASE4");
137 bool remove_lease;
138 handle.getArgument("remove_lease", remove_lease);
139 RunScriptImpl::extractBoolean(vars, remove_lease, "REMOVE_LEASE");
140 ProcessArgs args;
141 args.push_back("lease4_expire");
142 impl->runScript(args, vars);
143 return (0);
144}
145
152 if (status == CalloutHandle::NEXT_STEP_DROP ||
154 return (0);
155 }
156 ProcessEnvVars vars;
157 Lease4Ptr lease4;
158 handle.getArgument("lease4", lease4);
159 RunScriptImpl::extractLease4(vars, lease4, "LEASE4");
160 ProcessArgs args;
161 args.push_back("lease4_recover");
162 impl->runScript(args, vars);
163 return (0);
164}
165
172 if (status == CalloutHandle::NEXT_STEP_DROP ||
174 return (0);
175 }
176 ProcessEnvVars vars;
177 Pkt4Ptr pkt4;
178 handle.getArgument("query4", pkt4);
179 RunScriptImpl::extractPkt4(vars, pkt4, "QUERY4");
180 Lease4CollectionPtr leases4;
181 handle.getArgument("leases4", leases4);
182 RunScriptImpl::extractLeases4(vars, leases4, "LEASES4");
183 Lease4CollectionPtr deleted_leases4;
184 handle.getArgument("deleted_leases4", deleted_leases4);
185 RunScriptImpl::extractLeases4(vars, deleted_leases4, "DELETED_LEASES4");
186 ProcessArgs args;
187 args.push_back("leases4_committed");
188 impl->runScript(args, vars);
189 return (0);
190}
191
198 if (status == CalloutHandle::NEXT_STEP_DROP ||
200 return (0);
201 }
202 ProcessEnvVars vars;
203 Pkt4Ptr pkt4;
204 handle.getArgument("query4", pkt4);
205 RunScriptImpl::extractPkt4(vars, pkt4, "QUERY4");
206 Lease4Ptr lease4;
207 handle.getArgument("lease4", lease4);
208 RunScriptImpl::extractLease4(vars, lease4, "LEASE4");
209 ProcessArgs args;
210 args.push_back("lease4_release");
211 impl->runScript(args, vars);
212 return (0);
213}
214
221 if (status == CalloutHandle::NEXT_STEP_DROP ||
223 return (0);
224 }
225 ProcessEnvVars vars;
226 Pkt4Ptr pkt4;
227 handle.getArgument("query4", pkt4);
228 RunScriptImpl::extractPkt4(vars, pkt4, "QUERY4");
229 Lease4Ptr lease4;
230 handle.getArgument("lease4", lease4);
231 RunScriptImpl::extractLease4(vars, lease4, "LEASE4");
232 ProcessArgs args;
233 args.push_back("lease4_decline");
234 impl->runScript(args, vars);
235 return (0);
236}
237
244 if (status == CalloutHandle::NEXT_STEP_DROP ||
246 return (0);
247 }
248 ProcessEnvVars vars;
249 Pkt6Ptr pkt6;
250 handle.getArgument("query6", pkt6);
251 RunScriptImpl::extractPkt6(vars, pkt6, "QUERY6");
252 Lease6Ptr lease6;
253 handle.getArgument("lease6", lease6);
254 RunScriptImpl::extractLease6(vars, lease6, "LEASE6");
255 Option6IAPtr option6IA;
256 if (lease6->type_ == Lease::TYPE_NA) {
257 handle.getArgument("ia_na", option6IA);
258 } else {
259 handle.getArgument("ia_pd", option6IA);
260 }
261 RunScriptImpl::extractOptionIA(vars, option6IA, "PKT6_IA");
262 ProcessArgs args;
263 args.push_back("lease6_renew");
264 impl->runScript(args, vars);
265 return (0);
266}
267
274 if (status == CalloutHandle::NEXT_STEP_DROP ||
276 return (0);
277 }
278 ProcessEnvVars vars;
279 Pkt6Ptr pkt6;
280 handle.getArgument("query6", pkt6);
281 RunScriptImpl::extractPkt6(vars, pkt6, "QUERY6");
282 Lease6Ptr lease6;
283 handle.getArgument("lease6", lease6);
284 RunScriptImpl::extractLease6(vars, lease6, "LEASE6");
285 Option6IAPtr option6IA;
286 if (lease6->type_ == Lease::TYPE_NA) {
287 handle.getArgument("ia_na", option6IA);
288 } else {
289 handle.getArgument("ia_pd", option6IA);
290 }
291 RunScriptImpl::extractOptionIA(vars, option6IA, "PKT6_IA");
292 ProcessArgs args;
293 args.push_back("lease6_rebind");
294 impl->runScript(args, vars);
295 return (0);
296}
297
304 if (status == CalloutHandle::NEXT_STEP_DROP ||
306 return (0);
307 }
308 ProcessEnvVars vars;
309 Lease6Ptr lease6;
310 handle.getArgument("lease6", lease6);
311 RunScriptImpl::extractLease6(vars, lease6, "LEASE6");
312 bool remove_lease;
313 handle.getArgument("remove_lease", remove_lease);
314 RunScriptImpl::extractBoolean(vars, remove_lease, "REMOVE_LEASE");
315 ProcessArgs args;
316 args.push_back("lease6_expire");
317 impl->runScript(args, vars);
318 return (0);
319}
320
327 if (status == CalloutHandle::NEXT_STEP_DROP ||
329 return (0);
330 }
331 ProcessEnvVars vars;
332 Lease6Ptr lease6;
333 handle.getArgument("lease6", lease6);
334 RunScriptImpl::extractLease6(vars, lease6, "LEASE6");
335 ProcessArgs args;
336 args.push_back("lease6_recover");
337 impl->runScript(args, vars);
338 return (0);
339}
340
347 if (status == CalloutHandle::NEXT_STEP_DROP ||
349 return (0);
350 }
351 ProcessEnvVars vars;
352 Pkt6Ptr pkt6;
353 handle.getArgument("query6", pkt6);
354 RunScriptImpl::extractPkt6(vars, pkt6, "QUERY6");
355 Lease6CollectionPtr leases6;
356 handle.getArgument("leases6", leases6);
357 RunScriptImpl::extractLeases6(vars, leases6, "LEASES6");
358 Lease6CollectionPtr deleted_leases6;
359 handle.getArgument("deleted_leases6", deleted_leases6);
360 RunScriptImpl::extractLeases6(vars, deleted_leases6, "DELETED_LEASES6");
361 ProcessArgs args;
362 args.push_back("leases6_committed");
363 impl->runScript(args, vars);
364 return (0);
365}
366
373 if (status == CalloutHandle::NEXT_STEP_DROP ||
375 return (0);
376 }
377 ProcessEnvVars vars;
378 Pkt6Ptr pkt6;
379 handle.getArgument("query6", pkt6);
380 RunScriptImpl::extractPkt6(vars, pkt6, "QUERY6");
381 Lease6Ptr lease6;
382 handle.getArgument("lease6", lease6);
383 RunScriptImpl::extractLease6(vars, lease6, "LEASE6");
384 ProcessArgs args;
385 args.push_back("lease6_release");
386 impl->runScript(args, vars);
387 return (0);
388}
389
396 if (status == CalloutHandle::NEXT_STEP_DROP ||
398 return (0);
399 }
400 ProcessEnvVars vars;
401 Pkt6Ptr pkt6;
402 handle.getArgument("query6", pkt6);
403 RunScriptImpl::extractPkt6(vars, pkt6, "QUERY6");
404 Lease6Ptr lease6;
405 handle.getArgument("lease6", lease6);
406 RunScriptImpl::extractLease6(vars, lease6, "LEASE6");
407 ProcessArgs args;
408 args.push_back("lease6_decline");
409 impl->runScript(args, vars);
410 return (0);
411}
412
419 if (status == CalloutHandle::NEXT_STEP_DROP ||
421 return (0);
422 }
423 ProcessEnvVars vars;
424 Pkt6Ptr pkt6;
425 handle.getArgument("query6", pkt6);
426 RunScriptImpl::extractPkt6(vars, pkt6, "QUERY6");
428 handle.getArgument("address6", addr);
429 RunScriptImpl::extractString(vars, addr.toText(), "ADDRESS6");
430 Lease6Ptr lease6;
431 handle.getArgument("old_lease6", lease6);
432 if (lease6) {
433 RunScriptImpl::extractLease6(vars, lease6, "OLD_LEASE6");
434 }
435 handle.getArgument("new_lease6", lease6);
436 RunScriptImpl::extractLease6(vars, lease6, "NEW_LEASE6");
437 ProcessArgs args;
438 args.push_back("addr6_register");
439 impl->runScript(args, vars);
440 return (0);
441}
442
447 return (1);
448}
449
450} // end extern "C"
CalloutNextStep
Specifies allowed next steps.
@ NEXT_STEP_DROP
drop the packet
@ NEXT_STEP_SKIP
skip the next processing step
A generic exception that is thrown when an unexpected error condition occurs.
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
Per-packet callout handle.
CalloutNextStep getStatus() const
Returns the next processing step.
void getArgument(const std::string &name, T &value) const
Get argument.
static std::string getProcName()
returns the process name This value is used as when forming the default PID file name
Definition daemon.cc:156
Run Script implementation.
Definition run_script.h:28
static void extractBoolean(isc::asiolink::ProcessEnvVars &vars, const bool value, const std::string &prefix="", const std::string &suffix="")
Extract boolean data and append to environment.
Definition run_script.cc:55
static void extractLease4(isc::asiolink::ProcessEnvVars &vars, const isc::dhcp::Lease4Ptr &lease4, const std::string &prefix="", const std::string &suffix="")
Extract Lease4 data and append to environment.
static void extractString(isc::asiolink::ProcessEnvVars &vars, const std::string &value, const std::string &prefix="", const std::string &suffix="")
Extract string data and append to environment.
Definition run_script.cc:79
static void extractSubnet4(isc::asiolink::ProcessEnvVars &vars, const isc::dhcp::ConstSubnet4Ptr subnet4, const std::string &prefix="", const std::string &suffix="")
Extract Subnet4 data and append to environment.
static void extractHWAddr(isc::asiolink::ProcessEnvVars &vars, const isc::dhcp::HWAddrPtr &hwaddr, const std::string &prefix="", const std::string &suffix="")
Extract HWAddr data and append to environment.
Definition run_script.cc:88
static void extractOptionIA(isc::asiolink::ProcessEnvVars &vars, const isc::dhcp::Option6IAPtr option6IA, const std::string &prefix="", const std::string &suffix="")
Extract Option6IA data and append to environment.
static void extractLeases6(isc::asiolink::ProcessEnvVars &vars, const isc::dhcp::Lease6CollectionPtr &leases6, const std::string &prefix="", const std::string &suffix="")
Extract Lease6Collection data and append to environment.
static void extractLease6(isc::asiolink::ProcessEnvVars &vars, const isc::dhcp::Lease6Ptr &lease6, const std::string &prefix="", const std::string &suffix="")
Extract Lease6 data and append to environment.
static void extractClientId(isc::asiolink::ProcessEnvVars &vars, const isc::dhcp::ClientIdPtr client_id, const std::string &prefix="", const std::string &suffix="")
Extract ClientId data and append to environment.
static void extractPkt6(isc::asiolink::ProcessEnvVars &vars, const isc::dhcp::Pkt6Ptr &pkt6, const std::string &prefix="", const std::string &suffix="")
Extract Pkt6 data and append to environment.
static void extractPkt4(isc::asiolink::ProcessEnvVars &vars, const isc::dhcp::Pkt4Ptr &pkt4, const std::string &prefix="", const std::string &suffix="")
Extract Pkt4 data and append to environment.
static void extractLeases4(isc::asiolink::ProcessEnvVars &vars, const isc::dhcp::Lease4CollectionPtr &leases4, const std::string &prefix="", const std::string &suffix="")
Extract Lease4Collection data and append to environment.
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.
#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
boost::shared_ptr< Lease4Collection > Lease4CollectionPtr
A shared pointer to the collection of IPv4 leases.
Definition lease.h:551
boost::shared_ptr< const Subnet4 > ConstSubnet4Ptr
A const pointer to a Subnet4 object.
Definition subnet.h:455
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Definition pkt4.h:556
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition lease.h:556
boost::shared_ptr< Option6IA > Option6IAPtr
A pointer to the Option6IA object.
Definition option6_ia.h:20
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition hwaddr.h:166
boost::shared_ptr< ClientId > ClientIdPtr
Shared pointer to a Client ID.
Definition duid.h:216
boost::shared_ptr< Lease6Collection > Lease6CollectionPtr
A shared pointer to the collection of IPv6 leases.
Definition lease.h:724
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
Definition pkt6.h:31
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition lease.h:343
RunScriptImplPtr impl
boost::shared_ptr< RunScriptImpl > RunScriptImplPtr
The type of shared pointers to Run Script implementations.
Definition run_script.h:283
isc::log::Logger run_script_logger("run-script-hooks")
Defines the logger used by the top-level component of kea-lfc.
int lease4_recover(CalloutHandle &handle)
handle lease4_recover hook and set environment parameters for the script.
int lease4_release(CalloutHandle &handle)
handle lease4_release hook and set environment parameters for the script.
int lease4_decline(CalloutHandle &handle)
handle lease4_decline hook and set environment parameters for the script.
int leases6_committed(CalloutHandle &handle)
handle leases6_committed hook and set environment parameters for the script.
int lease6_release(CalloutHandle &handle)
handle lease6_release hook and set environment parameters for the script.
int leases4_committed(CalloutHandle &handle)
handle leases4_committed hook and set environment parameters for the script.
int lease6_rebind(CalloutHandle &handle)
handle lease6_rebind hook and set environment parameters for the script.
int multi_threading_compatible()
This function is called to retrieve the multi-threading compatibility.
int lease4_renew(CalloutHandle &handle)
handle lease4_renew hook and set environment parameters for the script.
int unload()
This function is called when the library is unloaded.
int lease6_expire(CalloutHandle &handle)
handle lease6_expire hook and set environment parameters for the script.
int lease4_expire(CalloutHandle &handle)
handle lease4_expire hook and set environment parameters for the script.
int addr6_register(CalloutHandle &handle)
handle addr6_register hook and set environment parameters for the script.
int load(LibraryHandle &handle)
This function is called when the library is loaded.
int lease6_recover(CalloutHandle &handle)
handle lease6_recover hook and set environment parameters for the script.
int lease6_decline(CalloutHandle &handle)
handle lease6_decline hook and set environment parameters for the script.
int lease6_renew(CalloutHandle &handle)
handle lease6_renew hook and set environment parameters for the script.
const isc::log::MessageID RUN_SCRIPT_UNLOAD
const isc::log::MessageID RUN_SCRIPT_LOAD
const isc::log::MessageID RUN_SCRIPT_LOAD_ERROR
@ TYPE_NA
the lease contains non-temporary IPv6 address
Definition lease.h:49