diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib/dhcpsrv/libdhcpsrv.dox | 528 |
1 files changed, 528 insertions, 0 deletions
diff --git a/src/lib/dhcpsrv/libdhcpsrv.dox b/src/lib/dhcpsrv/libdhcpsrv.dox new file mode 100644 index 0000000..803517d --- /dev/null +++ b/src/lib/dhcpsrv/libdhcpsrv.dox @@ -0,0 +1,528 @@ +// Copyright (C) 2012-2023 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 libdhcpsrv libkea-dhcpsrv - Server DHCP Library + +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, +client, relay and other tools like perfdhcp) code, please see +\ref libdhcp. + +This library contains several crucial elements for the operation of the DHCP server: + +- isc::dhcp::CfgGlobals - global scalar (i.e. not list or map) parameters. +- isc::dhcp::LeaseMgr - lease manager is the name for the database backend that stores + leases. +- isc::dhcp::CfgMgr - configuration manager that holds DHCP specific + configuration information (subnets, pools, options, timer values etc.) in + easy to use format. +- isc::dhcp::AllocEngine - allocation engine that handles new requests and allocates new + leases. +- isc::dhcp::HostMgr - manager for static reservations (a.k.a. host reservations). +- isc::dhcp::D2ClientMgr - DHCP-DDNS (D2) client manager which is responsible for + the communication between the DHCP server and the D2 component. +- isc::dhcp::Dhcp4o6IpcBase - common part (base class) of DHCPv4-over-DHCPv6 + inter server communication (aka IPC). + +@section cfgglobals Global Parameters + +The global parameters handle direct (vs using a search in a name to +value table) access to global scalar (i.e. not list or map) parameter values. + +This is related to the procedure to add a new global scalar parameter to +the DHCPv4 or DHCPv6 (DHCPvX below) server implementation: + +- update the src/bin/dhcpX/dhcpX_lexer.ll to add the new token +- update the src/bin/dhcpX/dhcpX_parser.yy to add the new syntax +- update the src/bin/dhcpX/json_config_parser.cc to add the new parameter + in the global parameter big if statement +- update the src/lib/dhcpsrv/parsers/simple_parserX.cc file to add the new + parameter in the GLOBALX_PARAMETERS keyword list and eventually in the + GLOBALX_DEFAULTS list +- update the cfg_globals.h and cfg_globals.cc files, note that specific to + v4 or v6 parameters are after no specific +- if the parameter exists for shared networks, subnets, etc, + the corresponding tables must be updated in simple parser files + +Note there is nothing to update for a global parameter in the configuration +backend: no new column in database schemas, no code in hooks. Of course +this does not apply to parameters which exist at not global level too. + +@section leasemgr Lease Manager + +LeaseMgr provides a common, unified abstract API for all database backends. All +backends are derived from the base class isc::dhcp::LeaseMgr. Currently Kea +supports three backends, implemented in the following classes: + +- 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 + +@section cfgmgr Configuration Manager + +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 +\ref isc::dhcp::SrvConfig object. Internally, the Configuration Manager +holds a list of \ref isc::dhcp::SrvConfig objects, from which one +is marked as "current configuration". + +When the server starts up or is being reconfigured a new +\ref isc::dhcp::SrvConfig object, referred to as "staging configuration", +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. +Modifications of the staging configuration do not affect the current +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 +\ref isc::dhcp::SrvConfig object from the Configuration Manager. When +the \ref isc::dhcp::CfgMgr::getStagingCfg is called again a fresh/default +\ref isc::dhcp::SrvConfig object is returned. + +The Configuration Manager stores previous configurations, i.e. configurations +which occurred prior to the most current configuration. This is currently +unused (except for unit tests) by the daemons, but in the future this +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. + +All configuration classes are derived from the abstract base class +\ref isc::data::CfgToElement and define the toElement virtual method +which returns a \ref isc::data::ConstElementPtr which must be +parsed into the same object, i.e. fulfill this property: +@code +for all valid C: parse(parse(C)->toElement()) == parse(C) +@endcode + + +@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 +connection to the MySQL database and issue specific queries. A factory +method creating an instance of a base host data source object must be +registered (at global object initialization for built-in backends, +dynamically for backends loaded at run-time). See host_data_source_factory.cc +for example code that registers MySQL and PostgreSQL. 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. + +@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" + +@section optionsConfig Options Configuration Information + +The \ref isc::dhcp::CfgOption object holds a collection of options being +sent to the client. Since each subnet comes with a distinct set of +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 +processing. + +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, +and only stateless configuration is handed out. + +@section allocengine Allocation Engine + +The Allocation Engine (\ref isc::dhcp::AllocEngine) is one of the core Kea modules. +It uses the data from the received client DHCP messages to find an available +lease and allocate it to the client. Finding a free lease is very complex +because the engine has to consider the client's hints, whether or not the +client has a static reservation, classes associated with the client, and +many more. If the engine cannot allocate a lease indicated in the hint and +the client has no static reservations, it has to find an available lease +in the configured address or prefix delegation pools. It is the responsibility +of the allocator (\ref isc::dhcp::Allocator). + +Allocators are implemented in C++ classes with a well-defined interface. Each +allocator uses a different algorithm for selecting a lease from the configured +pools: + +- Iterative - it iterates over all resources (addresses or prefixes) in +available pools, one by one. The advantages of this approach are: speed +(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 get a different lease). This allocator is not suitable for +temporary addresses, which must be randomized. This allocator is implemented +in \ref isc::dhcp::IterativeAllocator. + +- Random - an allocator generating IP permutations within configured address pool +using the Fisher-Yates shuffle algorithm. The allocator picks the leases from +the permutation, so the leases are offered in random order. The permutation +holds a state indicating which leases have already been offered to avoid +returning the same lease multiple times. The advantage of the random allocator +is that it makes the attacks based on address prediction more difficult. On +the other hand, this allocator consumes more memory than the iterative allocator +to hold the permutation state. This allocator is implemented +in \ref isc::dhcp::RandomAllocator. + +The following allocators are not implemented in Kea but can be considered in +the future: + +- FLQ (Free Lease Queue) - it is a specialized allocator optimizing lease +selection when the server has nearly depleted pools. The iterative and +random allocators can be slow in this case because they are unaware of +which leases have already been taken. The FLQ allocator tracks lease +allocations and avoids offering already allocated leases. It must maintain +the list of available leases and offer them from this list. When the lease +is allocated, it must be removed from the list. Populating the list of +available leases is performed during the server startup or reconfiguration, +possibly impacting the server's startup and reconfiguration time. + +- 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 +requires use of a hashing function. That is especially difficult when the +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. + +@subsection allocEngineTypes Different lease types support + +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 +generate an address. This defeats the purpose of using temporary addresses for now. + +@subsection allocEnginePD Prefix Delegation support in AllocEngine + +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, +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. + +@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 +renew the lease for the client using the address not reserved for it. +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. + +@subsection allocEngineReuse Allocation Engine Cache + +The allocation engine provides a cache-like feature: when a suitable +lease already exists for a client if its age is small enough compared +to the valid lifetime (threshold parameter) and below a configured maximum +(max age parameter) the lease can be reused. A reusable lease is marked +by a not zero reuseable_valid_lft_ value. + +@section timerManager Timer Manager + +The @c isc::dhcp::TimerMgr is a singleton class used throughout the +server process to register and unregister timers triggering periodic +tasks such as lease file cleanup, reclamation of expired leases etc. + +The Timer Manger is using ASIO deadline timers (wrapped in +@c isc::asiolink::IntervalTimer class) to execute tasks according to +the configured periods. Therefore, the server process must provide the +Timer Manager with the pointer to the @c isc::asiolink::IOService which +the server is using to run asynchronous tasks. + +Current implementation of the DHCP servers uses synchronous calls to +@c select() function to check if any transmission has been received +on any socket. This poses a problem with running asynchronous calls +via @c IOService in the main server loop because the @c select() +blocks for a specified amount of time while asynchronous calls +are not triggered. In the future we should migrate from the synchronous +@c select() calls into asynchronous calls using ASIO. Currently, +we mitigate the problem by lowering the @c select() timeout to 1s, +and polling @c IOService for "ready" timers (handlers) after +@c select() returns. This may cause delays of "ready" handlers +execution by around 1s. However, this is acceptable for the current +applications of the periodic timers. + +@section leaseReclamationRoutine Leases Reclamation Routine + +Lease reclamation is the process in which the expired lease becomes +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. + +Reclamation is performed periodically for a bulk of expired +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. + +The reclamation routines are executed periodically according to +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. + +Execution of the reclamation routine may take a relatively +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 +lease database used. While the reclamation routine is +executed, the server will not process any DHCP messages to avoid +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 +limit the time for the reclamation routine to process +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 +lease with a particular client. When that client returns the +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. + +@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. + +@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. + +Also see \ref dhcpv4o6Dhcp4 and \ref dhcpv4o6Dhcp6 for details on how IPC +is used by DHCPv4 and DHCPv6 components. + +@todo + +DHCPv4-over-DHCPv6 which are relayed by a DHCPv6 relay are not yet supported. + +@section libdhcpsrvMTConsiderations Multi-Threading Consideration for Server DHCP Library + +Note that for backends specific consideration is in @ref +dhcpDatabaseBackendsMTConsiderations. + +Below Kea thread safe means thread safe when the multi-threading mode is +true (when it is false packets are processed by the main thread). + +By default this library is not thread safe, in particular all classes used +for configuration are not thread safe. Exceptions are: + + - allocation engine allocator is Kea thread safe. + + - resource handler is thread safe. + + - last allocated members of subnets are Kea thread safe. + + - timer manager functions are Kea thread safe. + +*/ |