1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
|
// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
/**
@page dhcpv4Hooks The Hooks API for the DHCPv4 Server
@section dhcpv4HooksIntroduction Introduction
Kea features an API (the "Hooks" API) that allows user-written code to
be integrated into Kea and called at specific points in its processing.
An overview of the API and a tutorial for writing such code can be found in
the @ref hooksdgDevelopersGuide. Information for Kea maintainers can be
found in the @ref hooksComponentDeveloperGuide.
This manual is more specialized and is aimed at developers of hook
code for the DHCPv4 server. It describes each hook point, what the callouts
attached to the hook are able to do, and the arguments passed to the
callouts. Each entry in this manual has the following information:
- Name of the hook point.
- Arguments for the callout. As well as the argument name and data type, the
information includes the direction, which can be one of:
- @b in - the server passes values to the callout but ignored any data
returned.
- @b out - the callout is expected to set this value.
- <b>in/out</b> - the server passes a value to the callout and uses whatever
value the callout sends back. Note that the callout may choose not to
do any modification, in which case the server will use whatever value
it sent to the callout.
- Description of the hook. This explains where in the processing the hook
is located, the possible actions a callout attached to this hook could take,
and a description of the data passed to the callouts.
- Next step status: the action taken by the server when a callout chooses to set
status to specified value. Actions not listed explicitly are not supported.
If a callout sets status to unsupported value, this specific value will be
ignored and treated as if the status was CONTINUE.
@section dhcpv4HooksHookPoints Hooks in the DHCPv4 Server
The following list is roughly ordered by appearance of specific hook points during
packet processing, but the exact order depends on the actual processing. Hook points
that are not specific to packet processing (e.g. lease expiration) will be added
to the end of this list.
@subsection dhcpv4HooksBuffer4Receive buffer4_receive
- @b Arguments:
- name: @b query4, type: isc::dhcp::Pkt4Ptr, direction: <b>in/out</b>
- @b Description: this callout is executed when the server has received a
buffer containing a DHCPv4 message, but the message hasn't yet been parsed.
The sole argument "query4" contains a pointer to the isc::dhcp::Pkt4
object, which contains the source and destination address of the
received packet, the interface over which the packet has been received, and
a raw buffer, stored in the data_ field, containing the DHCPv4 message
in the wire format. None of the packet fields (op_, hlen_, chaddr_, etc.)
are set yet. Callouts installed on this hook point can modify the data
in the received buffer. The server will parse the buffer afterwards.
- <b>Next step status</b>: If any callout sets the status to SKIP, the server will
skip the buffer parsing. In this case there is an expectation that
the callout will parse the options carried in the buffer, create
@c isc::dhcp::Option objects (or derived) and add them to the "query4"
object using the @c isc::dhcp::Pkt4::addOption.
Otherwise the server will find out that some mandatory options are
missing (e.g. DHCP Message Type) and will drop the message. If you
want to have the capability to drop a message, it is better to use
the skip flag in the "pkt4_receive" callout.
@subsection dhcpv4HooksPkt4Receive pkt4_receive
- @b Arguments:
- name: @b query4, type: isc::dhcp::Pkt4Ptr, direction: <b>in/out</b>
- @b Description: this callout is executed when an incoming DHCPv4
packet is received and its content has been parsed. The sole
argument "query4" contains a pointer to an isc::dhcp::Pkt4 object
that contains all information regarding incoming packet, including
its source and destination addresses, interface over which it was
received, a list of all options present within and the relay
information. All fields of the Pkt4 object can be modified at this
time. By the time this hook is reached, the contents of the data_
field has been already parsed and stored in other fields. Therefore,
the modification in the data_ field has no effect.
- <b>Next step status</b>: If any callout sets the status to SKIP, the server will
drop the packet and start processing the next one. The reason for the drop
will be logged if logging is set to the appropriate debug level.
@subsection dhcpv4HooksSubnet4Select subnet4_select
- @b Arguments:
- name: @b query4, type: isc::dhcp::Pkt4Ptr, direction: <b>in/out</b>
- name: @b subnet4, type: isc::dhcp::Subnet4Ptr, direction: <b>in/out</b>
- name: @b subnet4collection, type: const isc::dhcp::Subnet4Collection *,
direction: <b>in</b>
- @b Description: this callout is executed when a subnet is being
selected for the incoming packet. All parameters and addresses
will be assigned from that subnet. A callout can select a
different subnet if it wishes so. The list of all subnets currently
configured are provided as "subnet4collection". The list itself must
not be modified.
- <b>Next step status</b>: If any callout installed on the "subnet4_select" hook
sets the next step status to SKIP, the server will not select any subnet.
Packet processing will continue, but will be severely limited.
@subsection dhcpv4HooksHost4Identifier host4_identifier
- @b Arguments:
- name: @b query4, type isc::dhcp::Pkt4Ptr, direction: <b>in</b>
- name: @b id_type, type isc::dhcp::Host::IdentifierType, direction: <b>in/out</b>
- name: @b id_value, type std::vector<uint8_t>, direction: <b>out</b>
- @b Description: this callout is executed only if flexible identifiers are
enabled, i.e. host-reservation-identifiers contain 'flex-id' value. This
callout enables external library to provide values for flexible identifiers.
To be able to use this feature, flex_id hook library is required.
- <b>Next step status</b>: If a callout installed on the "host4_identifier" hook
point sets the next step status to value other than NEXT_STEP_CONTINUE, the
identifier will not be used.
@subsection dhcpv4HooksLeaseSelect lease4_select
- @b Arguments:
- name: @b query4, type: isc::dhcp::Pkt4Ptr, direction: <b>in</b>
- name: @b subnet4, type: isc::dhcp::Subnet4Ptr, direction: <b>in</b>
- name: @b fake_allocation, type: bool, direction: <b>in</b>
- name: @b lease4, type: isc::dhcp::Lease4Ptr, direction: <b>in/out</b>
- @b Description: this callout is executed after the server engine
has selected a lease for the client's request, but before the lease has
been inserted into the database. Any modifications made to the
"lease4" object will affect the lease's record in the database.
The callout should sanity check all modifications as the server will
use that data as is, with no further checking.\n\n
The server processes lease requests for DHCPDISCOVER and DHCPREQUEST in a
very similar way. The only major difference is that for DHCPDISCOVER
the lease is only selected, but not inserted into the database. The callouts
may distinguish between DHCPDISCOVER and DHCPREQUEST by checking the
value of the "fake_allocation" flag: a value of true indicates that the
lease won't be inserted into the database (DHCPDISCOVER case), a value of
false indicates that it will (DHCPREQUEST case).
- <b>Next step status</b>: If any callout installed on the "lease4_select" hook
sets the next step action to SKIP, the server will not assign any lease and
the callouts become responsible for the lease assignment. If the callouts
fail to provide a lease, the packet processing will continue, but client
will not get an address.
@subsection dhcpv4HooksLeaseRenew lease4_renew
- @b Arguments:
- name: @b query4, type: isc::dhcp::Pkt4Ptr, direction: <b>in</b>
- name: @b subnet4, type: isc::dhcp::Subnet4Ptr, direction: <b>in</b>
- name: @b clientid, type: isc::dhcp::ClientId, direction: <b>in</b>
- name: @b hwaddr, type: isc::dhcp::HWAddr, direction: <b>in</b>
- name: @b lease4, type: isc::dhcp::Lease4Ptr, direction: <b>in/out</b>
- @b Description: this callout is executed when the server engine
is about to renew a lease, as a result of receiving DHCPREQUEST/Renewing
packet. The "lease4" argument points to @c isc::dhcp::Lease4 object that
contains the updated values. Callout can modify those values. Care should
be taken as the server will attempt to update the lease in the database
without any additional checks.
- <b>Next step status</b>: If any callout installed on the "lease4_renew" hook
sets the next step action to SKIP, the server will not update the lease in the
database and will continue using the old values instead.
@subsection dhcpv4HooksLeaseRelease lease4_release
- @b Arguments:
- name: @b query4, type: isc::dhcp::Pkt4Ptr, direction: <b>in</b>
- name: @b lease4, type: isc::dhcp::Lease4Ptr, direction: <b>in</b>
- @b Description: this callout is executed when the server engine
is about to release a lease, as a result of receiving DHCPRELEASE packet.
The "lease4" argument points to @c Lease4 object that contains the lease to
be released. It doesn't make sense to modify it at this time.
- <b>Next step status</b>: If any callout installed on the "lease4_release" hook
sets the next step action to SKIP, the server will not delete the lease.
It will be kept in the database and will go through the regular expiration/reuse
process.
@subsection dhcpv4HooksLeaseDecline lease4_decline
- @b Arguments:
- name: @b query4, type: isc::dhcp::Pkt4Ptr, direction: <b>in</b>
- name: @b lease4, type: isc::dhcp::Lease4Ptr, direction: <b>in</b>
- @b Description: this callout is executed when the server engine
is about to decline a lease, as a result of receiving DHCPDECLINE packet.
The server already sanity checked it (the packet is sane, attempts to decline
a lease that is valid and belongs to the client that requests its decline).
The "lease4" argument points to @c Lease4 object that contains the lease to
be released. Note this lease still contains client identifying information.
That data is provided for informational purposes and it doesn't make sense to
modify it at this time. All the information will be removed from the lease
before it is updated in the database.
- <b>Next step status</b>: If any callout installed on the "lease4_release" hook
sets the next step action to DROP, the server will not decline the lease.
Care should be taken when setting this status. The lease will be kept in
the database as it is and the client will incorrectly assume that the server
marked this lease as unavailable. If the client restarts its configuration,
it will get the same (not declined) lease as a result.
@subsection dhcpv4HooksPkt4Send pkt4_send
- @b Arguments:
- name: @b response4, type: isc::dhcp::Pkt4Ptr, direction: <b>in/out</b>
- name: @b query4, type: isc::dhcp::Pkt4Ptr, direction: <b>in</b>
- @b Description: this callout is executed when server's response
is about to be sent back to the client. The sole argument "response4"
contains a pointer to an isc::dhcp::Pkt4 object carrying the
packet, with source and destination addresses set, interface over which
it will be sent, and a list of all options and relay information. All fields
of the @c Pkt4 object can be modified at this time, except @c buffer_out_.
(This is scratch space used for constructing the packet after all
pkt4_send callouts are complete, so any changes to that field will
be overwritten.)\n\n
The argument query4 contains a pointer to the corresponding query packet
(allowing to perform correlation between response and query). This object
cannot be modified.
- <b>Next step action</b>: if any callout installed on the "pkt4_send" hook
sets the next step action to SKIP, the server will not construct the raw
buffer. The expectation is that if the callout set skip flag, it is
responsible for constructing raw form on its own. Otherwise the output
packet will be sent with zero length.
@subsection dhcpv4HooksBuffer4Send buffer4_send
- @b Arguments:
- name: @b response4, type: isc::dhcp::Pkt4Ptr, direction: <b>in/out</b>
- @b Description: this callout is executed when server's response
is about to be sent back to the client. The sole argument "response4"
contains a pointer to an @c isc::dhcp::Pkt4 object that contains the
packet, with source and destination addresses set, interface over which
it will be sent, and a list of all options and relay information. The raw
on-wire form is already prepared in @c buffer_out_ (see
@c isc::dhcp::Pkt4::getBuffer())
Callouts should not modify the packet fields or options contents at this
time, because they were already used to construct on-wire buffer. Their
modification would have no effect.
- <b>Next step status</b>: if any callout sets the next step action to SKIP,
the server will drop this response packet. However, the original request
packet from a client was processed, so server's state most likely has changed
(e.g. lease was allocated). Setting this flag merely stops the change
being communicated to the client.
@subsection dhcpv4HooksLease4Expire lease4_expire
- @b Arguments:
- name: @b lease4, type: isc::dhcp::Lease4Ptr, direction: <b>in/out</b>
- name: @b remove_lease, type: bool, direction: <b>in</b>
- @b Description: this callout is executed for each expired lease when
the server performs reclamation of the expired leases. During this
process the server executes "lease4_expire" callout, removes the DNS
records associated with this lease and finally removes the lease from
the database or updates its status to "expired-reclaimed". The "lease4"
argument contains the pointer to the lease being reclaimed. The second
argument "remove_lease" indicates if the reclaimed leases should be
removed from the lease database (if true), or their state should be
set to "expired-reclaimed" in the lease database. This argument
is only used by the callout if it takes responsibility for the lease
reclamation, i.e. it sets the "skip" flag to "true". The "remove_lease"
argument is set to "true" if the "flush-reclaimed-timer-wait-time" is
set to 0 in the server configuration file.
- <b>Next step status</b>: if the callout sets the next step action to SKIP,
the server will assume that the callout has fully reclaimed the lease, i.e.
performed the DNS update and updated the lease in the database. The
server will not perform any further actions on the lease for which the
skip flag has been set. It is important to note that if the callout
sets this flag but fails to reclaim the lease in the database, the
reclamation routine will repeatedly process this lease in subsequent
runs. Therefore, the implementors of this callout must make sure that
skip flag is only set when the lease has been actually reclaimed in the
database by the callout.
@subsection dhcpv4HooksLease4Recover lease4_recover
- @b Arguments:
- name: @b lease4, type: isc::dhcp::Lease4Ptr, direction: <b>in</b>
- @b Description: this callout is executed for each declined lease that
has expired (was put aside for the duration of decline-probation-period)
and is being recovered. The lease has already been stripped
from any client identifying information when it was put into declined
state. In principle the callouts can modify the lease in this hook,
but it makes little sense. There's no useful data in the lease, except
the IPv4 address (which must not be modified).
- <b>Next step status</b>: if the callout sets the next step action to SKIP,
the server will skip the lease recovery. In other words, it will keep
the lease as is. This is not recommended in general, as the declined
expired leases will remain in the database and their recovery will
be attempted during the next reclaim cycle.
@subsection dhcpv4HooksControlCommandReceive control_command_receive
- @b Arguments:
- name: @b command, type: isc::data::ConstElementPtr, direction: <b>in/out</b>
- name: @b response, type: isc::data::ConstElementPtr, direction: <b>in/out</b>
- @b Description: this callout is executed when DHCPv4 server receives a
control command over the command channel (typically unix domain socket).
The "command" argument is a pointer to the parsed JSON structure
including command name and command arguments. If the callout implements
the specified command, it handles the command and creates appropriate
response. The response should be returned in the "response" argument.
In most cases, the callout which handles the command will set the next
step action to SKIP, to prevent the server from trying to handle the
command on its own and overriding the response created by the callouts.
A notable exception is the 'list-commands' command for which the callouts
should not set the next step action to SKIP. The server has a special
code path for this command which combines the list of commands returned
by the callouts with the list of commands supported by the server. If
the callout sets the next step action to SKIP in this case, the server
will only return the list of commands supported by the hook library.
The callout can modify the command arguments to influence the command
processing by the Command Manager. For example, it may freely modify
the configuration received in 'config-set' before it is processed by
the server. The SKIP action is not set in this case.
- <b>Next step status</b>: if any callout sets the next step action to SKIP,
the server will assume that the command has been handled by the callouts
and will expect that the response is provided in the "response" argument.
The server will not handle the command in this case but simply return the
response returned by the callout to the caller.
@section dhcpv4HooksOptionsAccess Accessing DHCPv4 Options within a Packet
When the server constructs a response message to a client it includes
DHCP options configured for this client in a response message. Apart
from the dynamically created options, such as Client FQDN option, it
typically includes many options specified in the server configuration
and held within the configuration structures by @c CfgMgr. Option
instances are created once, during server configuration, and the
@c CfgMgr holds pointers to those instances until the next server
reconfiguration.
When the server includes an option in a response message it copies
a pointer to the instance of this option, rather than entire option.
This ensures the good performance of response message creation. However,
it also implies that any modification to the option carried in the
DHCP response will affect an instance of this option in the server
configuration structures. This is obviously not desired as it would
affect all subsequent DHCP transactions involving this option. The
DHCP server code avoids modifying the options included in the messages
so it is possible to ensure good performance without a risk of
accidentally modifying server configuration. The situation is
different with hooks libraries which purpose is, in many cases,
to modify values of options inserted by the server.
Thus, @c Pkt class provides a mechanism to return a copy of an
option to a caller (e.g. a callout), rather than an instance
shared with the @c CfgMgr. This mechanism is enabled for all instances
of @c Pkt4 passed to the callouts, i.e. "query4" and "response4"
arguments. It is also automatically disabled when the callout
returns the control back to the server.
At every hook point, where the server passes an instance of a packet
to the callouts, the server calls
@c isc::dhcp::Pkt4::setCopyRetrievedOptions (true)
to force copying options retrieved by @c isc::dhcp::Pkt4::getOption
within callouts. The copied option replaces an original option within a
packet and any modification to the option content by the callout
would only affect the option instance associated with the packet.
On the other hand, copying each retrieved option may be expensive.
If performance of a hook library is a concern, it is possible for the
hook library to disable copying retrieved options by calling
@c isc::dhcp::Pkt4::setCopyRetrievedOptions (false) within a callout.
In this case however, the hook library implementer must be aware that any
modification of the option instance would affect the server configuration
and may disrupt server's operation. Thus, disabling copying of retrieved
options is not recommended unless the hook library is not intended
to modify configured options carried within a packet.
*/
|