libdhcpsrv.dox 25 KB
Newer Older
1
// Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC")
2
//
3
4
5
// 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/.
6

7
/**
8
 @page libdhcpsrv libkea-dhcpsrv - Server DHCP Library
9

10
11
12
13
This library contains code used for the DHCPv4 and DHCPv6 servers' operations,
including the "Lease Manager" that manages information about leases and the
"Configuration Manager" that stores the servers' configuration etc.
The code here is server specific. For generic (useful to the server,
14
client, relay and other tools like perfdhcp) code, please see
15
16
\ref libdhcp.

17
This library contains several crucial elements for the operation of the DHCP server:
18

19
- isc::dhcp::LeaseMgr - lease manager is the name for the database backend that stores
20
  leases.
21
- isc::dhcp::CfgMgr - configuration manager that holds DHCP specific
22
23
  configuration information (subnets, pools, options, timer values etc.) in
  easy to use format.
24
- isc::dhcp::AllocEngine - allocation engine that handles new requests and allocates new
25
  leases.
26
27
- isc::dhcp::HostMgr - manager for static reservations (a.k.a. host reservations).
- isc::dhcp::D2ClientMgr - DHCP-DDNS (D2) client manager which is responsible for
28
  the communication between the DHCP server and the D2 component.
29
30
- isc::dhcp::Dhcp4o6IpcBase - common part (base class) of DHCPv4-over-DHCPv6
  inter server communication (aka IPC).
31
32
33
34

@section leasemgr Lease Manager

LeaseMgr provides a common, unified abstract API for all database backends. All
35
backends are derived from the base class isc::dhcp::LeaseMgr. Currently Kea
36
supports three backends, implemented in the following classes:
37

38
39
40
- isc::dhcp::Memfile_LeaseMgr - stores leases in a CSV file,
- isc::dhcp::MySqlLeaseMgr - stores leases in a MySQL database
- isc::dhcp::PgSqlLeaseMgr - stores leases in a PostgreSQL database
41
42
43

@section cfgmgr Configuration Manager

44
45
46
Configuration Manager (\ref isc::dhcp::CfgMgr) is a singleton object which
holds configuration information necessary for the operation of Kea daemons.
A complete collection of information for the daemon is stored in the
47
48
\ref isc::dhcp::SrvConfig object. Internally, the Configuration Manager
holds a list of \ref isc::dhcp::SrvConfig objects, from which one
49
50
51
is marked as "current configuration".

When the server starts up or is being reconfigured a new
52
\ref isc::dhcp::SrvConfig object, referred to as "staging configuration",
53
54
55
56
is created. The staging configuration is held at the tip of the list of
configurations. The object can be accessed by calling the
\ref isc::dhcp::CfgMgr::getStagingCfg. This object can be accessed
from different stages of the configuration parsing and modified as needed.
57
Modifications of the staging configuration do not affect the current
58
59
60
61
62
63
64
65
configuration. The staging configuration is unused until the
\ref isc::dhcp::CfgMgr::commit function is called. This exception safe method
marks the staging object as "current configuration". The const pointer to the
current configuration can be accessed by calling a
\ref isc::dhcp::CfgMgr::getCurrentCfg.

The staging configuration can be discarded at any time before it is committed
by calling the \ref isc::dhcp::CfgMgr::rollback. This removes the
66
\ref isc::dhcp::SrvConfig object from the Configuration Manager. When
67
the \ref isc::dhcp::CfgMgr::getStagingCfg is called again a fresh/default
68
\ref isc::dhcp::SrvConfig object is returned.
69
70
71

The Configuration Manager stores previous configurations, i.e. configurations
which occurred prior to the most current configuration. This is currently
72
unused (except for unit tests) by the daemons, but in the future this
73
74
75
76
77
78
79
80
81
mechanism can be used to trigger a rollover of the server configuration
to a last good configuration that the administrator prefers.

The previous configurations are identified by the value which specifies a
distance between the current configuration and the previous
configuration. For example: the value of 1 identifies an immediate
predecessor of the current configuration, the value of 2 identifies the
one that occurred before it etc.

82
All configuration classes are derived from the abstract base class
83
\ref isc::data::CfgToElement and define the toElement virtual method
84
85
86
which returns a \ref isc::data::ConstElementPtr which must be
parsed into the same object, i.e. fullfil this property:
@code
87
for all valid C: parse(parse(C)->toElement()) == parse(C)
88
89
90
@endcode


91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
@section hostmgr Host Manager

Host Manager implemented by the \ref isc::dhcp::HostMgr is a singleton object
which provides means to retrieve resources statically assigned to the DHCP
clients, such as IP addresses, prefixes or hostnames. The statically assigned
resources are called reservations (or host reservations) and they are
represented in the code by the \ref isc::dhcp::Host class.

The reservations can be specified in the configuration file or in some
other storage (typically in a database). A dedicated object, called
host data source, is needed to retrieve the host reservations from the
database. This object must implement the \ref isc::dhcp::BaseHostDataSource
interface and its implementation is specific to the type of storage
holding the reservations. For example, the host data source managing
host reservations in the MySQL database is required to establish
106
connection to the MySQL database and issue specific queries. Once
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
implemented, the \ref isc::dhcp::HostMgr::create method must be updated
to create an instance of this datasource. Note, that this instance is
created as "alternate host data source" as opposed to the primary data
source which returns host reservations specified in the configuration file.
The primary data source is implemented internally in the
\ref isc::dhcp::HostMgr and uses the configuration data structures held by
the \ref isc::dhcp::CfgMgr to retrieve the reservations. In general, the
\ref isc::dhcp::HostMgr first searches for the reservations using the
primary data source and falls back to the use of alternate data source
when nothing has been found. For those methods which are meant to return
multiple reservations (e.g. find all reservations for the particular
client), the \ref isc::dhcp::HostMgr will use both primary and alternate
data source (if present) and concatenate results.

For more information about the \ref isc::dhcp::HostMgr please refer to its
documentation.

124
125
126
127
128
129
130
131
132
@subsection postgreSQLHostMgr PostgreSQL Host Reservation Management

Storing and retrieving host reservations within a PostgreSQL schema is
provided by the class, \ref isc::dhcp::PgSqlHostDataSource, a derivation of
\ref isc::dhcp::BaseHostDataSource and is depicted in the following
class diagram:

@image html pgsql_host_data_source.svg  "PgSqlHostDataSource Class Diagram"

133
134
135
@section optionsConfig Options Configuration Information

The \ref isc::dhcp::CfgOption object holds a collection of options being
136
sent to the client. Since each subnet comes with a distinct set of
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
options, every \ref isc::dhcp::Subnet object holds its own copy of the
\ref isc::dhcp::CfgOption object with specific options.

The DHCP server also allows for configuration of "global" options
which are shared by all subnets. The rule here is that if a particular
option appears in the global options set and the subnet specific options
set, the subnet specific option takes precedence. The global options
configuration is held in the dedicated instance of the
\ref isc::dhcp::CfgOption class. This instance is owned by the
\ref isc::dhcp::SrvConfig class.

When the new configuration is parsed, the global options are merged into
the \ref isc::dhcp::CfgOption instances for all subnets. This is
causing some overhead during the reconfiguration of the server but on
the other hand it avoids the lookup of options in two places (among
subnet specific options and global options) during each packet
153
processing.
154
155
156
157
158
159

One of the benefits of keeping a separate set of global options is
that there may be cases when the server administrator doesn't specify
any subnet configuration and only wants global options to be used.
This is the case, when the DHCP server is used for stateless
configuration, i.e. client's are not allocated an address or prefix,
160
and only stateless configuration is handed out.
161

162
163
164
165
166
167
168
@section allocengine Allocation Engine

Allocation Engine (\ref isc::dhcp::AllocEngine) is what its name say - an engine
that handles allocation of new leases. It takes parameters that the client
provided (client-id, DUID, subnet, a hint if the user provided one, etc.) and
then attempts to allocate a lease.

169
There is no single best solution to the address assignment problem. Server
170
171
172
173
174
175
176
177
is expected to pick an address from its available pools is currently not used.
There are many possible algorithms that can do that, each with its own advantages
and drawbacks. This allocation engine must provide robust operation is radically
different scenarios, so there address selection problem was abstracted into
separate module, called allocator. Its sole purpose is to pick an address from
a pool. Allocation engine will then check if the picked address is free and if
it is not, then will ask allocator to pick again.

Tomek Mrugalski's avatar
Tomek Mrugalski committed
178
At least 3 allocators will be implemented:
179

180
- Iterative - it iterates over all resources (addresses or prefixes) in
Tomek Mrugalski's avatar
Tomek Mrugalski committed
181
available pools, one by one. The advantages of this approach are: speed
182
183
184
185
186
187
188
189
190
191
192
(typically it only needs to increase address just one), the guarantee to cover
all addresses and predictability.  This allocator behaves reasonably good in
case of nearing depletion. Even when pools are almost completely allocated, it
still will be able to allocate outstanding leases efficiently. Predictability
can also be considered a serious flaw in some environments, as prediction of the
next address is trivial and can be leveraged by an attacker. Another drawback of
this allocator is that it does not attempt to give the same address to returning
clients (clients that released or expired their leases and are requesting a new
lease will likely to get a different lease). This allocator is not suitable for
temporary addresses, which must be randomized. This allocator is implemented
in \ref isc::dhcp::AllocEngine::IterativeAllocator.
193
194
195
196
197
198
199

- Hashed - ISC-DHCP uses hash of the client-id or DUID to determine, which
address is tried first. If that address is not available, the result is hashed
again. That procedure is repeated until available address is found or there
are no more addresses left. The benefit of that approach is that it provides
a relative lease stability, so returning old clients are likely to get the same
address again. The drawbacks are increased computation cost, as each iteration
200
requires use of a hashing function. That is especially difficult when the
201
202
203
204
205
pools are almost depleted. It also may be difficult to guarantee that the
repeated hashing will iterate over all available addresses in all pools. Flawed
hash algorithm can go into cycles that iterate over only part of the addresses.
It is difficult to detect such issues as only some initial seed (client-id
or DUID) values may trigger short cycles. This allocator is currently not
206
implemented. This will be the only allocator allowed for temporary addresses.
207
208
209
210
211
212
213
214
215

- Random - Another possible approach to address selection is randomization. This
allocator can pick an address randomly from the configured pool. The benefit
of this approach is that it is easy to implement and makes attacks based on
address prediction more difficult. The drawback of this approach is that
returning clients are almost guaranteed to get a different address. Another
drawback is that with almost depleted pools it is increasingly difficult to
"guess" an address that is free. This allocator is currently not implemented.

Tomek Mrugalski's avatar
Tomek Mrugalski committed
216
@subsection allocEngineTypes Different lease types support
217
218
219
220
221
222

Allocation Engine has been extended to support different types of leases. Four
types are supported: TYPE_V4 (IPv4 addresses), TYPE_NA (normal IPv6 addresses),
TYPE_TA (temporary IPv6 addresses) and TYPE_PD (delegated prefixes). Support for
TYPE_TA is partial. Some routines are able to handle it, while other are
not. The major missing piece is the RandomAllocator, so there is no way to randomly
Tomek Mrugalski's avatar
Tomek Mrugalski committed
223
224
225
generate an address. This defeats the purpose of using temporary addresses for now.

@subsection allocEnginePD Prefix Delegation support in AllocEngine
226

Tomek Mrugalski's avatar
Tomek Mrugalski committed
227
228
229
The Allocation Engine supports allocation of the IPv6 addresses and prefixes.
For a prefix pool, the iterative allocator "walks over"
every available pool. It is similar to how it iterates over address pool,
230
231
232
233
234
235
236
237
but instead of increasing address by just one, it walks over the whole delegated
prefix length in one step. This is implemented in
isc::dhcp::AllocEngine::IterativeAllocator::increasePrefix(). Functionally the
increaseAddress(addr) call is equivalent to increasePrefix(addr, 128)
(increasing by a /128 prefix, i.e. a single address).  However, both methods are
kept, because increaseAddress() is faster and this is a routine that may be
called many hundred thousands times per second.

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
@subsection allocEngineDHCPv4HostReservation Host Reservation support

The Allocation Engine supports allocation of statically assigned addresses
to the DHCPv4 clients, a.k.a. Host Reservation.

When the server receives a DHCPDISCOVER or DHCPREQUEST from the client it
calls \ref isc::dhcp::AllocEngine::allocateLease4 to obtain the suitable lease
for the client. If the Allocation Engine determines that the particular client
has a reservation it will try to allocate a reserved address for it. If the
client requested allocation or renewal of a different address, the Allocation
Engine will respond with a NULL lease to indicate that the address
desired by the client could not be assigned. The DHCP server should send
a DHCPNAK to the client and the client should fall back to the DHCP
server discovery. When the client sends DHCPDISCOVER, the Allocation
Engine offers the reserved address and the client should request the
offered address in subsequent DHCPREQUEST messages.

There are cases when the Allocation Engine is unable to assign the
reserved address for the client. This includes the situations when
the address had been previously reserved for another client or the
address had been assigned out of the dynamic address pool. Such address
may still remain in use of the client which obtained it first and the
Allocation Engine must not assign it to the client for which it is
reserved until the client using this address releases or the server
assigns a different address for it.

In order to resolve this conflict the Allocation Engine will refuse to
265
renew the lease for the client using the address not reserved for it.
266
267
268
269
270
271
272
This client should fall back to the 4-way exchange and the Allocation
Engine will assign a different address. As a result, the reserved
address will be freed for the use of the client for which the reservation
was made. The client will be offered/allocated a reserved address
the next time it retries sending a DHCPDISCOVER/DHCPREQUEST message to
the server.

273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
@section timerManager Timer Manager

The fundamental role of the DHCP server is to receive and process DHCP
messages received over the sockets opened on network interfaces. The
servers' include the main loops in which the servers passively wait
for the messages. This is done by calling the
@c isc::dhcp::IfaceMgr::receive4 and/or @c isc::dhcp::IfaceMgr::receive6
methods for DHCPv4 and DHCPv6 server respectively. Internally, these
methods call @c select() on open sockets, which blocks for a
specified amount of time.

The implication of using the @c select() is that the server has no
means to process any "events" while it is waiting for the @c select()
to return. An example of such an event is the expiration of the timer
which controls when the server should detect and process expired
leases.

The @c isc::dhcp::TimerMgr has been created to address the issue of
processing expired leases according to the the dedicated timer.
292
Nevertheless, this concept is universal and should be used for
293
294
295
296
297
298
299
all timers which need to be triggered asynchronously, i.e. independently
from processing the DHCP messages.

The @c TimerMgr allows for registering timers and associating them with
user callback functions, which are executed without waiting for the
call to the @c select() function to return as a result of the timeout.
When the particular timer elapses, the blocking call to select is
300
301
interrupted by sending data over a dedicated (for a timer)
@c isc::util::WatchSocket. Each timer has an instance of
302
@c isc::util::WatchSocket associated with it, and each such socket
303
is registered with the @c IfaceMgr using the @c IfaceMgr::addExternalSocket.
304
When the transmission of the data over the watch socket interrupts the
305
@c select() call, the user callback is executed by
306
@c isc::dhcp::IfaceMgr and the watch socket is cleared to accept
307
subsequent events for that particular timer.
308
309
310

The timers are implemented using the @c isc::asiolink::IntervalTimer class.
They are run in a dedicated thread which is owned (created and destroyed)
311
312
by @c isc::dhcp::TimerMgr. This worker thread runs an instance
of @c isc::asiolink::IOService object which is associated with all
313
registered timers. The thread uses a common callback function which
314
is executed when a timer elapses. This callback function receives
315
316
a name of the elapsed timer as an argument and, based on that, selects the
appropriate @c isc::util::WatchSocket to be marked as ready. In order to
317
overcome the race conditions with the main thread, the worker thread blocks
318
319
320
321
322
323
324
325
right after it marks the watch socket as ready, and waits for this
socket to be cleared by the main thread. This is the indication
that the timer specific callback function has been invoked and the
worker thread may continue monitoring registered timers and signal
their readiness when they elapse.

@section leaseReclamationRoutine Leases Reclamation Routine

326
Lease reclamation is the process in which the expired lease becomes
327
328
329
330
331
332
333
334
available for re-assignment to the same or another client. When the
server reclaims the lease it executes the callouts registered for the
"lease4_expire" and "lease6_expire" hook points, performs the DNS update
to remove any DNS records associated with the expired lease, and finally
marks a lease as reclaimed in the lease database. The lease may be
marked as reclaimed by setting its state to @c Lease::STATE_EXPIRED_RECLAIMED
or by being removed from the database.

335
Reclamation is performed periodically for a bulk of expired
336
337
338
339
340
341
342
343
344
leases in the lease reclamation routine. The lease reclamation routines
for both DHCP servers are implemented in the @c isc::dhcp::AllocEngine:
- @c isc::dhcp::AllocEngine::reclaimExpiredLeases4 (DHCPv4)
- @c isc::dhcp::AllocEngine::reclaimExpiredLeases6 (DHCPv6)

Note that besides the reclamation of the leases, these methods also
update the relevant statistics, i.e. decrease the number of assigned
leases and increase the number of reclaimed leases.

345
The reclamation routines are executed periodically according to
346
347
348
349
350
351
the server configuration (see the documentation for the
"expired-leases-processing" configuration map). Internally, they are
registered as callback functions in the @c isc::dhcp::TimerMgr
(see @ref timerManager for the details), during the servers' startup
or reconfiguration.

352
Execution of the reclamation routine may take a relatively
353
354
long period of time. It depends on the complexity of the callouts,
whether the DNS update is required for leases, and the type of the
355
356
lease database used. While the reclamation routine is
executed, the server will not process any DHCP messages to avoid
357
358
359
360
race conditions being a result of concurrent access to the lease
database to allocate and reclaim leases. To make sure that the
server remains responsive, it is possible to limit the number of
leases being processed by the leases reclamation routine and/or
361
limit the time for the reclamation routine to process
362
363
364
365
366
367
368
369
370
371
leases. Both limits are specified in the respective arguments
passed to the lease reclamation routines.

As mentioned above, reclaimed leases may be marked as such, by
updating their state to @c Lease::STATE_EXPIRED_RECLAIMED or by
being removed. This behavior is controlled by the boolean parameter
passed to the reclamation routine. The first approach is desired
when the server should provide "lease affinity", i.e. ability to
re-assign the same lease to the returning client. By only
updating the lease state, the server preserves association of the
372
lease with a particular client. When that client returns the
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
server may assign the same lease to the client, assuming that this
lease is still available. The lease is removed during the
reclamation when the lease affinity is not required and it is
preferred to not keep redundant information (about expired
leases) in the lease database.

If the reclaimed leases are not removed, they are held in the
database for a specified amount of time after their expiration.
Each reclaimed lease is removed when this time elapses for it.
The @c isc::dhcp::LeaseMgr::deleteExpiredReclaimedLeases4 and
@c isc::dhcp::LeaseMgr::deleteExpiredReclaimedLeases6 are used
to remove those leases for which the specified amount of time
since expiration elapsed. These methods are executed periodically
by the DHCP servers using the dedicated timers registered in the
@c isc::dhcp::TimerMgr.

389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
@section subnetSelect Subnet Selection

An important service offered by this library is the subnet selection
from a query packet.

@subsection dhcp4SubnetSelect DHCPv4 Subnet Selection

Selectors (i.e., members of @c SubnetSelector class) are:
- incoming interface name
- gateway address - giaddr field
- client address - ciaddr field
- local address
- remote address
- option select - from the first Relay Agent Link Selection suboption or
  from a Subnet Selection option
- client classes - used to reject a matching rule and try next rules

First use the option select, next if the message was relayed (not undefined
gateway address) use the gateway address as a subnet relay address.

If a subnet was not already selected choose an address between:

- if the gateway address is not undefined the gateway address
- if the client address is not undefined and the local address not the
  broadcast address (i.e., renew or rebind) the client address
- if the remote address is not undefined and the local address not the
  broadcast address (i.e., renew or rebind) the remote address
- at this point try the interface name as a subnet interface
- if the interface name does not select a subnet choose the interface address
  (last resort)

Match the chosen address in a subnet address range.

@subsection dhcp4o6SubnetSelect DHCPv4-over-DHCPv6 Subnet Selection

Selectors (i.e., members of @c SubnetSelector class) are:
- incoming interface name
- gateway address - giaddr field (should be always undefined)
- client address - ciaddr field
- local address - set to the interface IPv4 address
- remote address - IPv6 address
- option select - from a Subnet Selection option
- first relay link address - (IPv6) undefined or the first relay link
  address which is not undefined or link local (i.e., usable)
- interface ID - (IPv6) when a relay message includes an interface ID
  relay option
- client classes - used to reject a matching rule and try next rules

Check if DHCPv4-over-DHCPv6 is enabled for this particular subnet and
continue with the next subnet is if it is not.

First the remote address is matched in a subnet IPv6 range, second
the interface ID if it is set is matched, third the interface name.

These rules are applied for each subnet configuration so if two
subnets match the first one is returned (vs. the first matching rule).

@todo better DHCPv4-over-DHCPv6 selection, e.g., handle relayed
messages and return best (vs first) match.

@subsection dhcp6SubnetSelection DHCPv6 Subnet Selection

Selectors (i.e., members of @c SubnetSelector class) are:
- incoming interface name
- remote address
- first relay link address - undefined or the first relay link address which
  is not undefined or link local (i.e., usable)
- interface ID - when a relay message includes an interface ID relay option
- client classes - used to reject a matching rule and try next rules

If the first relay link address is undefined the client is directly connected:
the interface name is matched and if it does not select a subnet the remote
address is matched in a subnet address range.

If the first relay link address is not undefined the query was relayed:
the interface ID is tried and if it does not select a subnet the first
relay address is matched as a subnet relay address.

467
468
469
470
471
472
473
474
475
476
477
478
479
480
@section dhcp4o6Ipc DHCPv4-over-DHCPv6 Inter Process Communication

DHCPv4-over-DHCPv6 support is implemented using cooperating
DHCPv6 and DHCPv6 servers. Servers communicate over a pair of
local UDP sockets using consecutive ports. The common part of
the Inter Process Communication (IPC) is provided by the base class
@c isc::dhcp::Dhcp4o6IpcBase.

The receiving interface name and remote IPv6 address meta information
are conveyed within a Vendor Specific Information option with the ISC
enterprise ID carrying interface and remote address suboptions.
\ref isc::dhcp::Dhcp4o6IpcBase::send adds them,
\ref isc::dhcp::Dhcp4o6IpcBase::receive decodes and removes them.

481
482
483
Also see \ref dhcpv4o6Dhcp4 and \ref dhcpv4o6Dhcp6 for details on how IPC
is used by DHCPv4 and DHCPv6 components.

484
485
486
487
@todo

DHCPv4-over-DHCPv6 which are relayed by a DHCPv6 relay are not yet supported.

488

489
*/