Kea 3.1.1
run_script_callouts.cc
Go to the documentation of this file.
1// Copyright (C) 2021-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 <run_script.h>
14#include <run_script_log.h>
15#include <dhcp/option6_ia.h>
16#include <dhcp/pkt4.h>
17#include <dhcp/pkt6.h>
18#include <dhcpsrv/cfgmgr.h>
19#include <dhcpsrv/lease.h>
20#include <dhcpsrv/subnet.h>
21#include <process/daemon.h>
22
23#include <string>
24
25namespace isc {
26namespace run_script {
27
29
30} // namespace run_script
31} // namespace isc
32
33using namespace isc;
34using namespace isc::asiolink;
35using namespace isc::data;
36using namespace isc::dhcp;
37using namespace isc::hooks;
38using namespace isc::process;
39using namespace isc::run_script;
40using namespace isc::util;
41using namespace std;
42
43// Functions accessed by the hooks framework use C linkage to avoid the name
44// mangling that accompanies use of the C++ compiler as well as to avoid
45// issues related to namespaces.
46extern "C" {
47
52int load(LibraryHandle& handle) {
53 try {
54 // Make the hook library not loadable by d2 or ca.
55 uint16_t family = CfgMgr::instance().getFamily();
56 const string& proc_name = Daemon::getProcName();
57 if (family == AF_INET) {
58 if (proc_name != "kea-dhcp4") {
59 isc_throw(isc::Unexpected, "Bad process name: " << proc_name
60 << ", expected kea-dhcp4");
61 }
62 } else {
63 if (proc_name != "kea-dhcp6") {
64 isc_throw(isc::Unexpected, "Bad process name: " << proc_name
65 << ", expected kea-dhcp6");
66 }
67 }
68
69 impl.reset(new RunScriptImpl());
70 impl->configure(handle);
71 } catch (const exception& ex) {
73 .arg(ex.what());
74 return (1);
75 }
76
78 return (0);
79}
80
84int unload() {
85 impl.reset();
87 return (0);
88}
89
96 if (status == CalloutHandle::NEXT_STEP_DROP ||
98 return (0);
99 }
100 ProcessEnvVars vars;
101 Pkt4Ptr pkt4;
102 handle.getArgument("query4", pkt4);
103 RunScriptImpl::extractPkt4(vars, pkt4, "QUERY4");
104 ConstSubnet4Ptr subnet4;
105 handle.getArgument("subnet4", subnet4);
106 RunScriptImpl::extractSubnet4(vars, subnet4, "SUBNET4");
107 ClientIdPtr clientid;
108 handle.getArgument("clientid", clientid);
109 RunScriptImpl::extractClientId(vars, clientid, "PKT4_CLIENT_ID");
110 HWAddrPtr hwaddr;
111 handle.getArgument("hwaddr", hwaddr);
112 RunScriptImpl::extractHWAddr(vars, hwaddr, "PKT4_HWADDR");
113 Lease4Ptr lease4;
114 handle.getArgument("lease4", lease4);
115 RunScriptImpl::extractLease4(vars, lease4, "LEASE4");
116 ProcessArgs args;
117 args.push_back("lease4_renew");
118 impl->runScript(args, vars);
119 return (0);
120}
121
128 if (status == CalloutHandle::NEXT_STEP_DROP ||
130 return (0);
131 }
132 ProcessEnvVars vars;
133 Lease4Ptr lease4;
134 handle.getArgument("lease4", lease4);
135 RunScriptImpl::extractLease4(vars, lease4, "LEASE4");
136 bool remove_lease;
137 handle.getArgument("remove_lease", remove_lease);
138 RunScriptImpl::extractBoolean(vars, remove_lease, "REMOVE_LEASE");
139 ProcessArgs args;
140 args.push_back("lease4_expire");
141 impl->runScript(args, vars);
142 return (0);
143}
144
151 if (status == CalloutHandle::NEXT_STEP_DROP ||
153 return (0);
154 }
155 ProcessEnvVars vars;
156 Lease4Ptr lease4;
157 handle.getArgument("lease4", lease4);
158 RunScriptImpl::extractLease4(vars, lease4, "LEASE4");
159 ProcessArgs args;
160 args.push_back("lease4_recover");
161 impl->runScript(args, vars);
162 return (0);
163}
164
171 if (status == CalloutHandle::NEXT_STEP_DROP ||
173 return (0);
174 }
175 ProcessEnvVars vars;
176 Pkt4Ptr pkt4;
177 handle.getArgument("query4", pkt4);
178 RunScriptImpl::extractPkt4(vars, pkt4, "QUERY4");
179 Lease4CollectionPtr leases4;
180 handle.getArgument("leases4", leases4);
181 RunScriptImpl::extractLeases4(vars, leases4, "LEASES4");
182 Lease4CollectionPtr deleted_leases4;
183 handle.getArgument("deleted_leases4", deleted_leases4);
184 RunScriptImpl::extractLeases4(vars, deleted_leases4, "DELETED_LEASES4");
185 ProcessArgs args;
186 args.push_back("leases4_committed");
187 impl->runScript(args, vars);
188 return (0);
189}
190
197 if (status == CalloutHandle::NEXT_STEP_DROP ||
199 return (0);
200 }
201 ProcessEnvVars vars;
202 Pkt4Ptr pkt4;
203 handle.getArgument("query4", pkt4);
204 RunScriptImpl::extractPkt4(vars, pkt4, "QUERY4");
205 Lease4Ptr lease4;
206 handle.getArgument("lease4", lease4);
207 RunScriptImpl::extractLease4(vars, lease4, "LEASE4");
208 ProcessArgs args;
209 args.push_back("lease4_release");
210 impl->runScript(args, vars);
211 return (0);
212}
213
220 if (status == CalloutHandle::NEXT_STEP_DROP ||
222 return (0);
223 }
224 ProcessEnvVars vars;
225 Pkt4Ptr pkt4;
226 handle.getArgument("query4", pkt4);
227 RunScriptImpl::extractPkt4(vars, pkt4, "QUERY4");
228 Lease4Ptr lease4;
229 handle.getArgument("lease4", lease4);
230 RunScriptImpl::extractLease4(vars, lease4, "LEASE4");
231 ProcessArgs args;
232 args.push_back("lease4_decline");
233 impl->runScript(args, vars);
234 return (0);
235}
236
243 if (status == CalloutHandle::NEXT_STEP_DROP ||
245 return (0);
246 }
247 ProcessEnvVars vars;
248 Pkt6Ptr pkt6;
249 handle.getArgument("query6", pkt6);
250 RunScriptImpl::extractPkt6(vars, pkt6, "QUERY6");
251 Lease6Ptr lease6;
252 handle.getArgument("lease6", lease6);
253 RunScriptImpl::extractLease6(vars, lease6, "LEASE6");
254 Option6IAPtr option6IA;
255 if (lease6->type_ == Lease::TYPE_NA) {
256 handle.getArgument("ia_na", option6IA);
257 } else {
258 handle.getArgument("ia_pd", option6IA);
259 }
260 RunScriptImpl::extractOptionIA(vars, option6IA, "PKT6_IA");
261 ProcessArgs args;
262 args.push_back("lease6_renew");
263 impl->runScript(args, vars);
264 return (0);
265}
266
273 if (status == CalloutHandle::NEXT_STEP_DROP ||
275 return (0);
276 }
277 ProcessEnvVars vars;
278 Pkt6Ptr pkt6;
279 handle.getArgument("query6", pkt6);
280 RunScriptImpl::extractPkt6(vars, pkt6, "QUERY6");
281 Lease6Ptr lease6;
282 handle.getArgument("lease6", lease6);
283 RunScriptImpl::extractLease6(vars, lease6, "LEASE6");
284 Option6IAPtr option6IA;
285 if (lease6->type_ == Lease::TYPE_NA) {
286 handle.getArgument("ia_na", option6IA);
287 } else {
288 handle.getArgument("ia_pd", option6IA);
289 }
290 RunScriptImpl::extractOptionIA(vars, option6IA, "PKT6_IA");
291 ProcessArgs args;
292 args.push_back("lease6_rebind");
293 impl->runScript(args, vars);
294 return (0);
295}
296
303 if (status == CalloutHandle::NEXT_STEP_DROP ||
305 return (0);
306 }
307 ProcessEnvVars vars;
308 Lease6Ptr lease6;
309 handle.getArgument("lease6", lease6);
310 RunScriptImpl::extractLease6(vars, lease6, "LEASE6");
311 bool remove_lease;
312 handle.getArgument("remove_lease", remove_lease);
313 RunScriptImpl::extractBoolean(vars, remove_lease, "REMOVE_LEASE");
314 ProcessArgs args;
315 args.push_back("lease6_expire");
316 impl->runScript(args, vars);
317 return (0);
318}
319
326 if (status == CalloutHandle::NEXT_STEP_DROP ||
328 return (0);
329 }
330 ProcessEnvVars vars;
331 Lease6Ptr lease6;
332 handle.getArgument("lease6", lease6);
333 RunScriptImpl::extractLease6(vars, lease6, "LEASE6");
334 ProcessArgs args;
335 args.push_back("lease6_recover");
336 impl->runScript(args, vars);
337 return (0);
338}
339
346 if (status == CalloutHandle::NEXT_STEP_DROP ||
348 return (0);
349 }
350 ProcessEnvVars vars;
351 Pkt6Ptr pkt6;
352 handle.getArgument("query6", pkt6);
353 RunScriptImpl::extractPkt6(vars, pkt6, "QUERY6");
354 Lease6CollectionPtr leases6;
355 handle.getArgument("leases6", leases6);
356 RunScriptImpl::extractLeases6(vars, leases6, "LEASES6");
357 Lease6CollectionPtr deleted_leases6;
358 handle.getArgument("deleted_leases6", deleted_leases6);
359 RunScriptImpl::extractLeases6(vars, deleted_leases6, "DELETED_LEASES6");
360 ProcessArgs args;
361 args.push_back("leases6_committed");
362 impl->runScript(args, vars);
363 return (0);
364}
365
372 if (status == CalloutHandle::NEXT_STEP_DROP ||
374 return (0);
375 }
376 ProcessEnvVars vars;
377 Pkt6Ptr pkt6;
378 handle.getArgument("query6", pkt6);
379 RunScriptImpl::extractPkt6(vars, pkt6, "QUERY6");
380 Lease6Ptr lease6;
381 handle.getArgument("lease6", lease6);
382 RunScriptImpl::extractLease6(vars, lease6, "LEASE6");
383 ProcessArgs args;
384 args.push_back("lease6_release");
385 impl->runScript(args, vars);
386 return (0);
387}
388
395 if (status == CalloutHandle::NEXT_STEP_DROP ||
397 return (0);
398 }
399 ProcessEnvVars vars;
400 Pkt6Ptr pkt6;
401 handle.getArgument("query6", pkt6);
402 RunScriptImpl::extractPkt6(vars, pkt6, "QUERY6");
403 Lease6Ptr lease6;
404 handle.getArgument("lease6", lease6);
405 RunScriptImpl::extractLease6(vars, lease6, "LEASE6");
406 ProcessArgs args;
407 args.push_back("lease6_decline");
408 impl->runScript(args, vars);
409 return (0);
410}
411
418 if (status == CalloutHandle::NEXT_STEP_DROP ||
420 return (0);
421 }
422 ProcessEnvVars vars;
423 Pkt6Ptr pkt6;
424 handle.getArgument("query6", pkt6);
425 RunScriptImpl::extractPkt6(vars, pkt6, "QUERY6");
427 handle.getArgument("address6", addr);
428 RunScriptImpl::extractString(vars, addr.toText(), "ADDRESS6");
429 Lease6Ptr lease6;
430 handle.getArgument("old_lease6", lease6);
431 if (lease6) {
432 RunScriptImpl::extractLease6(vars, lease6, "OLD_LEASE6");
433 }
434 handle.getArgument("new_lease6", lease6);
435 RunScriptImpl::extractLease6(vars, lease6, "NEW_LEASE6");
436 ProcessArgs args;
437 args.push_back("addr6_register");
438 impl->runScript(args, vars);
439 return (0);
440}
441
446 return (1);
447}
448
449} // 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:151
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:523
boost::shared_ptr< const Subnet4 > ConstSubnet4Ptr
A const pointer to a Subnet4 object.
Definition subnet.h:458
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:528
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:154
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:696
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:315
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:47