From f5f56e1a1c4d9e9496fcb9d81131066a964ccd23 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 13 Apr 2024 14:15:43 +0200 Subject: Adding upstream version 2.4.1. Signed-off-by: Daniel Baumann --- src/bin/dhcp4/dhcp4.dox | 352 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 352 insertions(+) create mode 100644 src/bin/dhcp4/dhcp4.dox (limited to 'src/bin/dhcp4/dhcp4.dox') diff --git a/src/bin/dhcp4/dhcp4.dox b/src/bin/dhcp4/dhcp4.dox new file mode 100644 index 0000000..e6034b5 --- /dev/null +++ b/src/bin/dhcp4/dhcp4.dox @@ -0,0 +1,352 @@ +// Copyright (C) 2012-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 dhcp4 DHCPv4 Server Component + +Kea includes the "kea-dhcp4" component, which is the DHCPv4 server +implementation. This component is built around the +@ref isc::dhcp::Dhcpv4Srv class which controls all major operations +performed by the server such as: DHCP messages processing, callouts +execution for many hook points, FQDN processing and interactions with the +"kea-dhcp-ddns" component, lease allocation, system signals handling etc. + +The "kea-dhcp4" component requires linking with many different libraries +to obtain access to common functions like: interfaces and sockets +management, configuration parsing, leases management and allocation, +hooks infrastructure, statistics management etc. + +The following sections walk through some of the details of the "kea-dhcp4" +component implementation. + +@section dhcpv4ConfigParser Configuration Parser in DHCPv4 + +Note: parsers are currently being migrated to @ref isc::data::SimpleParser. See +@ref ccSimpleParser page for details. + +The common configuration parsers for the DHCP servers are located in the +src/lib/dhcpsrv/parsers/ directory. Parsers specific to the DHCPv4 component +are located in the src/bin/dhcp4/json_config_parser.cc. These parsers derive +from the common configuration parsers and customize their behavior. For +example: the @c Subnet4ConfigParser is used to parse parameters +describing a single subnet. It derives from the @c +isc::dhcp::SubnetConfigParser, which implements the common base for both +DHCPv4 and DHCPv6 subnets. The @ref Subnet4ConfigParser +implements the @c initSubnet abstract method, which creates an instance of +the DHCPv4 subnet. This method is invoked by the parent class. + +Some parsers for the DHCPv4 server derive from the isc::dhcp::DhcpConfigParser +class directly. This is an abstract class, defining a basic interface for +all configuration parsers. All DHCPv4 parsers deriving from this class +directly have their entire implementation in the +src/bin/dhcp4/json_config_parser.cc. + +@section dhcpv4ConfigParserBison Configuration Parser for DHCPv4 (bison) + +If you are here only to learn absolute minimum about the new parser, here's how you +use it: + +@code + // The following code: + json = isc::data::Element::fromJSONFile(file_name, true); + + // can be replaced with this: + Parser4Context parser; + json = parser.parseFile(file_name, Parser4Context::PARSER_DHCP4); +@endcode + +For an introduction, rationale and issues the new parser tries to address, +see @ref dhcpv6ConfigParserBison. + +The code change for 5017 introduces flex/bison based parser. It is +essentially defined in two files: dhcp4_lexer.ll, which defines +regular expressions that are used on the input (be it a file or a +string in memory). In essence, this code is being called repeatedly +and each time it returns a token. This repeats until either the +parsing is complete or syntax error is encountered. For detailed +discussion, how they operate see @ref dhcpv6ConfigParserBison. + +@section dhcpv4ConfigSubParser Parsing Partial Configuration in DHCPv4 + +See @ref dhcpv6ConfigSubParser. + +@section dhcp4ParserIncludes Config File Includes + +See @ref dhcp6ParserIncludes. + +@section dhcp4ParserConflicts Avoiding syntactical conflicts in parsers + +See @ref dhcp6ParserConflicts. + +@section dhcpv4ConfigInherit DHCPv4 configuration inheritance + +One notable useful feature of DHCP configuration is its parameter inheritance. +For example, the "renew-timer" value may be specified at a global scope and it then +applies to all subnets. However, some subnets may have it overwritten with subnet +specific values that takes precedence over global values that are considered +defaults. The parameters inheritance is implemented by means of the "global +context". The global context is represented by the isc::dhcp::ParserContext +class and it holds pointers to storage of different kinds, e.g. text parameters, +numeric parameters etc. When the server is parsing the top level configuration +parameters it passes pointers to the storages of the appropriate kind, to the +parsers being invoked to parse the global values. Parsers will store the +parsed values into these storages. Once the global parameters are stored in the +global context, the parsers for the nested configuration parameters are invoked. +These parsers check the presence of the parameters overriding the values of +the global parameters. If a value is not present, the values from the global +context is used. + +A good example of inheritance is the implementation of the @ref +isc::dhcp::SubnetConfigParser. The @c getParam method is used throughout the +class to obtain values of the parameters defining a subnet. It first checks +if the specific value is present in the local values storage. If it is not +present, it uses the value from the global context. + + @code + isc::dhcp::Triplet + SubnetConfigParser::getParam(const std::string& name) { + uint32_t value = 0; + try { + // look for local value + value = uint32_values_->getParam(name); + } catch (const DhcpConfigError &) { + try { + // no local, use global value + value = global_context_->uint32_values_->getParam(name); + } catch (const DhcpConfigError &) { + isc_throw(DhcpConfigError, "Mandatory parameter " << name + << " missing (no global default and no subnet-" + << "specific value)"); + } + } + + return (Triplet(value)); +} +@endcode + +Note that if the value is neither present in the local storage nor in the global +context an error is signaled. + +Parameter inheritance is done once, during the reconfiguration phase. +Reconfigurations are rare, so extra logic here is not a problem. On the other +hand, values of those parameters may be used thousands times per second, so +access to these parameters must be as efficient as possible. In fact, +currently the code has to only call @c Subnet4::getT1(), regardless if the +"renew-timer" has been specified as a global or subnet specific value. + +Debugging a configuration parser may be confusing. Therefore there is a special +class called DebugParser. It does not configure anything, but just +accepts any parameter of any type. If requested to commit configuration, it will +print out received parameter name and its value. This class is not currently used, +but it is convenient to have it every time a new parameter is added to the DHCP +configuration. For that purpose it should be left in the code. + +@section dhcpv4OptionsParse Custom functions to parse message options + +The DHCPv4 server implementation provides a generic support to define option +formats and set option values. A number of options formats have been defined +for standard options in libdhcp++. However, the formats for vendor specific +options are dynamically configured by the server's administrator and thus can't +be stored in libdhcp++. Such option formats are stored in the +@ref isc::dhcp::CfgMgr. The libdhcp++ provides functions for recursive parsing +of options which may be encapsulated by other options up to any level of +encapsulation, but these functions are unaware of the option formats defined +in the @ref isc::dhcp::CfgMgr because they belong to a different library. +Therefore, the generic functions @ref isc::dhcp::LibDHCP::unpackOptions4 and +@ref isc::dhcp::LibDHCP::unpackOptions6 are only useful to parse standard +options whose definitions are provided in the libdhcp++. In order to overcome +this problem a callback mechanism has been implemented in @c Option and @c Pkt4 +classes. By installing a callback function on an instance of @c Pkt4, the +server may provide a custom implementation of the options parsing algorithm. +This callback function will take precedence over the @c LibDHCP::unpackOptions4 +and @c LibDHCP::unpackOptions6 functions. With this approach, the callback is +implemented within the context of the server and it has access to all objects +which define its configuration (including dynamically created option +definitions). + +Private (codes 224-254) and VSI (code 43) options are not decoded +by @c LibDHCP::unpackOptions4 but by @ref isc::dhcp::Dhcpv4Srv::deferredUnpack +function after classification. To make this function to perform or not +deferred processing the simplest is to add or not the option code +to the @ref isc::dhcp::Pkt4::getDeferredOptions list. + +@section dhcpv4DDNSIntegration DHCPv4 Server Support for the Dynamic DNS Updates +The DHCPv4 server supports processing of the DHCPv4 Client FQDN option (RFC4702) +and the DHCPv4 Host Name option (RFC2132). A client may send one of these options +to convey its fully qualified or partial name to the server. The server may use +this name to perform DNS updates for the client. If server receives both options +in the same message, the DHCPv4 Client FQDN %Option is processed and the Host +Name option is ignored. If only Host Name Option is present in the client's +message, it is used to update DNS. + +The server may be configured to use a different name to perform DNS update for the +client. In this case the server will return one of the DHCPv4 Client FQDN or +Host Name %Option in its response with the name which was selected for the +client to indicate that this name will be used to perform DNS update. + +The kea-dhcp-ddns process is responsible for the actual communication with the +DNS, i.e. to send DNS update messages. The kea-dhcp4 module is responsible for +generating @ref isc::dhcp_ddns::NameChangeRequest and sending it to +the kea-dhcp-ddns module. The @ref isc::dhcp_ddns::NameChangeRequest object +represents changes to the DNS bindings, related to acquisition, renewal or +release of the DHCP lease. The kea-dhcp4 module implements the simple FIFO queue +of the NameChangeRequest objects. The module logic, which processes the incoming +DHCPv4 Client FQDN and Host Name Options puts these requests into the FIFO queue. + +@todo Currently the FIFO queue is not processed after the NameChangeRequests are +generated and added to it. In the future implementation steps it is planned to +create a code which will check if there are any outstanding requests in the queue +and send them to the kea-dhcp-ddns module when server is idle waiting for DHCP +messages. + +When client gets an address from the server, a DHCPv4 server may generate 0, 1 +or 2 NameChangeRequests during single message processing. Server generates no +NameChangeRequests if it is not configured to update DNS or it rejects the DNS +update for any other reason. + +The server may generate one NameChangeRequest in the case where a client acquires a new +lease or it releases an existing one. In the former case, the NameChangeRequest +type is CHG_ADD, which indicates that the kea-dhcp-ddns module should add a new +DNS binding for the client, and it is assumed that there is no DNS binding for +this client already. In the latter case, the NameChangeRequest type is CHG_REMOVE +to indicate to the kea-dhcp-ddns module that an existing DNS binding should be +removed from the DNS. The binding consists of the forward and reverse mapping. +The server may only remove the mapping which it had added. Therefore, the lease +database holds the information which updates (no update, reverse only update, +forward only update or both reverse and forward update) have been performed when +the lease was acquired or renewed. Server checks this information to make a +decision which mapping it is supposed to remove when lease is released. + +The server may generate two NameChangeRequests in the case where client is +renewing a lease and it already has a DNS binding for that lease. The DHCPv4 +server will check if there is an existing lease for the client which has sent a +message and if DNS Updates had been performed for this lease. If the notion of +client's FQDN changes, comparing to the information stored in the lease +database, the DHCPv4 has to remove an existing binding from the DNS and then add +a new binding according to the new FQDN information received from the client. If +the client's FQDN information (including the client's name and type of update +performed) doesn't change comparing to the NameChangeRequest is not generated. + +The DHCPv4 Client FQDN %Option comprises flags which communicate to the server +what updates (if any) client expects the server to perform. Server may be +configured to obey client's preference or to do FQDN processing in a different way. +If the server overrides client's preference it will communicate it by sending +the DHCPv4 Client FQDN %Option in its responses to a client, with the appropriate +flags set. + +@todo Note: the current implementation doesn't allow configuration of the +server's behavior with respect to DNS Updates. This is planned for the future. +The default behavior is constituted by the set of constants defined in the +(upper part of) dhcp4_srv.cc file. Once the configuration is implemented, +these constants will be removed. + +@section dhcpv4Classifier DHCPv4 Client Classification + +The Kea DHCPv4 currently supports two classification modes: simplified client +classification (that was an early implementation that used values of vendor class option) +and full client classification. + +@subsection dhcpv4ClassifierSimple Simple Client Classification in DHCPv4 + +The Kea DHCPv4 server supports simplified client classification. It is called +"simplified", because the incoming packets are classified based on the content +of the vendor class (60) option. More flexible classification was added in 1.0 +and is described in @ref dhcpv4ClassifierFull . + +For each incoming packet, @ref isc::dhcp::Dhcpv4Srv::classifyPacket() method is called. +It attempts to extract content of the vendor class option and interpret as a name +of the class. For now, the code has been tested with two classes used in cable modem +networks: eRouter1.0 and docsis3.0, but any other content of the vendor class option will +be interpreted as a class name. + +In principle any given packet can belong to zero or more classes. As the current +classifier is very modest, there's only one way to assign a class (based on vendor class +option), the ability to assign more than one class to a packet is not yet exercised. +Nevertheless, there is such a possibility and it will be used in a near future. To +check whether a packet belongs to given class, isc::dhcp::Pkt4::inClass method should +be used. + +The code sometimes refers to this classification as "simple" or 'built-in", because +it does not require any configuration and thus is built into the server logic. + +@subsection dhcpv4ClassifierFull Full Client Classification in DHCPv4 + +Kea 1.0 introduced full client classification. Each client class consists of a name +and an expression that can be evaluated on an incoming packet. If it evaluates to +true, this packet is considered a member of said class. Class definitions are stored +in isc::dhcp::ClientClassDef objects that are kept in isc::dhcp::ClientClassDictionary. +This is convenient as there are often multiple classes associated with a given scope. +As of Kea 1.0, the only supported scope is global, but there are plans to support +class definitions that are subnet specific. + +Client classification is done in isc::dhcp::Dhcpv4Srv::classifyPacket. First, the old +"built-in" (see @ref dhcpv4ClassifierSimple) classification is called. Then the code +iterates over all class definitions and for each class definition it calls +isc::dhcp::evaluate, which is implemented in libeval (see @ref libeval). If the +evaluation is successful, the class name is added to the packet (by calling +isc::dhcp::pkt::addClass). + +If packet belongs to at least one class, this fact is logged. If there are any +exceptions raised during class evaluation, an error is logged and the code attempts +to evaluate the next class. + +@subsection dhcpv4ClassifierUsage How client classification information is used in DHCPv4 + +The classification code has been revamped in Kea 1.1. The old code that did specific +things for cable modems can now be achieved with the general classification code. Users +can simply define the class with next-address and/or filename in it. + +It is possible to define class restrictions in subnet, so a given subnet is only +accessible to clients that belong to a given class. That is implemented as +isc::dhcp::Pkt4::classes_ being passed in isc::dhcp::Dhcpv4Srv::selectSubnet() +to isc::dhcp::CfgMgr::getSubnet4(). Currently this capability is usable, but +the number of scenarios it supports is limited. + +Finally, it is possible to define client class-specific options, so clients belonging +to a class foo, will get options associated with class foo. This is implemented in +isc::dhcp::Dhcpv4Srv::buildCfgOptionList. + +@section dhcpv4ConfigBackend Configuration backend for DHCPv4 + +Earlier Kea versions had a concept of backends, which were implementations of +different ways how configuration could be delivered to Kea. It seems that the +concept of backends didn't get much enthusiasm from users and having multiple +backends was cumbersome to maintain, so it was removed in 1.0. + +@section dhcpv4SignalBasedReconfiguration Reconfiguring DHCPv4 server with SIGHUP signal + +Online reconfiguration (reconfiguration without a need to restart the server) is an +important feature which is supported by all modern DHCP servers. When using the JSON +configuration backend, a configuration file name is specified with a command line +option of the DHCP server binary. The configuration file is used to configure the +server at startup. If the initial configuration fails, the server will fail to start. +If the server starts and configures successfully it will use the initial configuration +until it is reconfigured. + +The reconfiguration request can be triggered externally (from other process) by editing +a configuration file and sending a SIGHUP signal to DHCP server process. After receiving +the SIGHUP signal, the server will re-read the configuration file specified at startup. +If the reconfiguration fails, the server will continue to run and use the last good +configuration. + +The signal handler for SIGHUP (also for SIGTERM and SIGINT) are installed in the +kea_controller.cc using the @c isc::util::SignalSet class. The +@c isc::dhcp::Dhcp4Srv calls @c isc::dhcp::Daemon::handleSignal on each pass +through the main loop. This method fetches the last received signal and calls +a handler function defined in the kea_controller.cc. The handler function +calls a static function @c configure defined in the kea_controller.cc. + +The signal handler reconfigures the server using the configuration file +specified at server startup. The location of this file is held in the +@c Daemon class. + +@section dhcpv4Other Other DHCPv4 topics + +For hooks API support in DHCPv4, see @ref dhcpv4Hooks. + +For a description of how DHCPv4-over-DHCPv6 is implemented, see @subpage dhcpv4o6Dhcp4. + +*/ -- cgit v1.2.3