123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- // Copyright (C) 2012-2016 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
- 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 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 @ref 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<uint32_t>
- 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<uint32_t>(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).
- @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 dhcpEval). 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.
- @subpage dhcpv4o6Dhcp4
- */
|