123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- // Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- // PERFORMANCE OF THIS SOFTWARE.
- /**
- @page dhcp6 DHCPv6 Server Component
- BIND10 offers DHCPv6 server implementation. It is implemented as
- b10-dhcp6 component. Its primary code is located in
- isc::dhcp::Dhcpv6Srv class. It uses \ref libdhcp extensively,
- especially lib::dhcp::Pkt6, isc::dhcp::Option and
- isc::dhcp::IfaceMgr classes. Currently this code offers skeleton
- functionality, i.e. it is able to receive and process incoming
- requests and trasmit responses. However, it does not have database
- management, so it returns only one, hardcoded lease to whoever asks
- for it.
- DHCPv6 server component does not support relayed traffic yet, as
- support for relay decapsulation is not implemented yet.
- DHCPv6 server component does not use BIND10 logging yet.
- @section dhcpv6Session BIND10 message queue integration
- DHCPv6 server component is now integrated with BIND10 message queue.
- It follows the same principle as DHCPv4. See \ref dhcpv4Session for
- details.
- @section dhcpv6ConfigParser Configuration Parser in DHCPv6
- b10-dhcp6 component uses BIND10 cfgmgr for commands and configuration. During
- initial configuration (See \ref
- isc::dhcp::ControlledDhcpv6Srv::establishSession()), the configuration handler
- callback is installed (see isc::dhcp::ControlledDhcpv6Srv::dhcp6ConfigHandler().
- It is called every time there is a new configuration. In particular, it is
- called every time during daemon start process. It contains a
- isc::data::ConstElementPtr to a new configuration. This simple handler calls
- \ref isc::dhcp::configureDhcp6Server() method that processes received configuration.
- This method iterates over list of received configuration elements and creates a
- list of parsers for each received entry. Parser is an object that is derived
- from a DhcpConfigParser class. Once a parser is created
- (constructor), its value is set (using build() method). Once all parsers are
- build, the configuration is then applied ("committed") and commit() method is
- called.
- All parsers are defined in src/bin/dhcp6/config_parser.cc file. Some of them
- are generic (e.g. Uint32Parser that is able to handle any
- unsigned 32 bit integer), but some are very specialized (e.g.
- Subnets6ListConfigParser parses definitions of Subnet6 lists). In some cases,
- e.g. subnet6 definitions, the configuration entry is not a simple value, but
- a map or a list itself. In such case, the parser iterates over all elements
- and creates parsers for a given scope. This process may be repeated (sort of)
- recursively.
- @section dhcpv6ConfigInherit DHCPv6 Configuration Inheritance
- One notable useful feature of DHCP configuration is its parameter inheritance.
- For example, 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 more
- specific values that takes precedence over global values that are considered
- defaults. Some parsers (e.g. Uint32Parser and StringParser) implement that
- inheritance. By default, they store values in global uint32_defaults and
- string_defaults storages. However, it is possible to instruct them to store
- parsed values in more specific storages. That capability is used, e.g. in
- Subnet6ConfigParser that has its own storage that is unique for each subnet.
- Finally, during commit phase (commit() method), appropriate parsers can use
- apply parameter inheritance.
- Debugging 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 DHCP
- configuration. For that purpose it should be left in the code.
- Parameter inheritance is done during reconfiguration phase, as 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 its use must be as
- simple as possible. In fact, currently the code has to call Subnet6->getT1() and
- do not implement any fancy inheritance logic.
- @section dhcpv6DDNSIntegration DHCPv6 Server Support for the Dynamic DNS Updates
- The DHCPv6 server supports processing of the DHCPv6 Client FQDN Option described in
- the RFC4704. This Option is sent by the DHCPv6 client to instruct the server to
- update the DNS mappings for the acquired lease. A client may send its fully
- qualified domain name, a partial name or it may choose that server will generate
- the name. In the last case, the client sends an empty domain-name field in the
- DHCPv6 Client FQDN Option.
- As described in RFC4704, client may choose that the server delegates the forward
- DNS update to the client and that the server performs the reverse update only. Current
- version of the DHCPv6 server does not support delegation of the forward update
- to the client. The implementation of this feature is planned for the future releases.
- The b10-dhcp-ddns process is responsible for the actual communication with the DNS
- server, i.e. to send DNS Update messages. The b10-dhcp6 module is responsible
- for generating so called @ref isc::dhcp_ddns::NameChangeRequest and sending it to the
- b10-dhcp-ddns module. The @ref isc::dhcp_ddns::NameChangeRequest object represents changes to the
- DNS bindings, related to acquisition, renewal or release of the lease. The bind10-dhcp6
- module implements the simple FIFO queue of the NameChangeRequest objects. The module
- logic, which processes the incoming DHCPv6 Client FQDN 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 b10-dhcp-ddns module when server is idle waiting for DHCP messages.
- In the simplest case, when client gets one address from the server, a DHCPv6 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.
- Server may generate 1 NameChangeRequest in a situation when a client acquires a
- new lease or it releases an existing lease. In the former case, the NameChangeRequest
- type is CHG_ADD, which indicates that the b10-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 b10-dhcp-ddns module that the existing DNS binding should be removed
- from the DNS. The binding consists of the forward and reverse mapping.
- A server may only remove the mapping which it had added. Therefore, the lease database
- holds an information which updates (no update, reverse only update, forward only update,
- both reverse and forward update) have been performed when the lease was acquired.
- Server checks this information to make a decision which mapping it is supposed to
- remove when a lease is released.
- Server may generate 2 NameChangeRequests in case the client is renewing a lease and
- it already has a DNS binding for that lease. Note, that renewal may be triggered
- as a result of sending a RENEW message as well as the REQUEST message. In both cases
- DHCPv6 server will check if there is an existing lease for the client which has sent
- a message, and it will check in the lease database if the DNS Updates had
- been performed for this client. If the notion of client's FQDN changes comparing to
- the information stored in the lease database, the DHCPv6 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 FQDN sent in the message which triggered a renewal
- doesn't change (comparing to the information in the lease database) the NameChangeRequest
- is not generated.
- In the more complex scenarios, when server sends multiple IA_NA options, each holding
- multiple IAADDR options, server will generate more NameChangeRequests for a single
- message being processed. That is 0, 1, 2 for the individual IA_NA. Generation of
- the distinct NameChangeRequests for each IADDR is not supported yet.
- The DHCPv6 Client FQDN Option comprises "NOS" 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 do FQDN processing in a
- different way. If the server overrides client's preference it will communicate it
- by sending the DHCPv6 Client FQDN Option in its responses to a client, with
- appropriate flags set.
- @todo Note, that current implementation doesn't allow configuration of the server's behaviour
- with respect to DNS Updates. This is planned for the future. The default behaviour is
- constituted by the set of constants defined in the (upper part of) dhcp6_srv.cc file.
- Once the configuration is implemented, these constants will be removed.
- @todo Add section about setting up options and their definitions with bindctl.
- @section dhcpv6OptionsParse Custom functions to parse message options
- The DHCPv6 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
- @c isc::dhcp::CfgMgr. The libdhcp++ provides functions for recursive parsing
- of options which may be encapsulated by other options up to the any level of
- encapsulation but these functions are unaware of the option formats defined
- in the @c isc::dhcp::CfgMgr because they belong to a different library.
- Therefore, the generic functions @c isc::dhcp::LibDHCP::unpackOptions4 and
- @c isc::dhcp::LibDHCP::unpackOptions6 are only useful to parse standard
- options which definitions are provided in the libdhcp++. In order to overcome
- this problem a callback mechanism has been implemented in @c Option and @c Pkt6
- classes. By installing a callback function on the instance of the @c Pkt6 the
- server may provide a custom implementation of the options parsing algorithm.
- This callback function will take precedence over the @c LibDHCP::unpackOptions6
- and @c LibDHCP::unpackOptions4 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 dhcpv6Classifier DHCPv6 Client Classification
- Kea DHCPv6 server currently supports simplified client classification. It is called
- "simplified", because the incoming packets are classified based on the content
- of the vendor class (16) option. More flexible classification is planned, but there
- are no specific development dates agreed.
- For each incoming packet, @ref isc::dhcp::Dhcpv6Srv::classifyPacket() method is
- called. It attempts to extract content of the vendor class option and interprets
- as a name of the class. Although the RFC3315 says that the vendor class may
- contain more than one chunk of data, the existing code handles only one data
- block, because that is what actual devices use. 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.
- Neverthless, 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::Pkt6::inClass method should
- be used.
- Currently there is no class behaviour coded in DHCPv6, hence no v6 equivalent of
- @ref isc::dhcp::Dhcpv4Srv::classSpecificProcessing. Should any need for such a code arise,
- it will be conducted in an external hooks library.
- 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::Pkt6::classes_
- being passed in isc::dhcp::Dhcpv6Srv::selectSubnet() to isc::dhcp::CfgMgr::getSubnet6().
- Currently this capability is usable, but the number of scenarios it supports is
- limited.
- @section dhcpv6ConfigBackend Configuration backend for DHCPv6
- There are many theoretical ways in which server configuration can be stored. Kea 0.8 and
- earlier versions used BIND10 framework and its internal storage for DHCPv6 server configuration.
- The legacy ISC-DHCP implementation uses flat files. Configuration stored in JSON files is
- becoming more and more popular among various projects. There are unofficial patches for
- ISC-DHCP that keep parts of the configuration in LDAP. It was also suggested that in some
- cases it would be convenient to keep configuration in XML files.
- Kea 0.9 introduces configuration backends that are switchable during compilation phase.
- There is a new parameter for configure script: --with-kea-config. It currently supports
- two values: BUNDY and JSON.
- BUNDY (which is the default value as of April 2014) means that Kea6 is linked with the
- Bundy (former BIND10) configuration backend that connects to the BIND10 framework and in general works
- exactly the same as Kea 0.8 and earlier versions. The benefits of that backend are uniform
- integration with Bundy/BIND10 framework, easy on-line reconfiguration using bindctl, available
- RESTful API. On the other hand, it requires the whole heavy Bundy framework that requires
- Python3 to be present. That framework is going away with the release of Kea 0.9.
- JSON is a new configuration backend that causes Kea to read JSON configuration file from
- disk. It does not require any framework and thus is considered more lightweight. It will
- allow dynamic on-line reconfiguration, but will lack remote capabilities (i.e. no RESTful
- API). This configuration backend is expected to be the default for upcoming Kea 0.9. It
- requires <tt> -c config-file </tt> command-line option.
- Internally, configuration backends are implemented as different implementations of the
- isc::dhcp::ControlledDhcpv6Srv class, stored in {kea,bundy}_controller.cc files. Depending on
- the choice made by ./configure script, only one of those files is compiled and linked.
- There are backend specific tests in src/bin/dhcp6/tests/{kea,bundy}_controller_unittest.cc.
- Only tests specific to selected backend are linked and executed during make distcheck.
- While it is unlikely that ISC will support more than one backend at any given time, there
- are several aspects that make that approach appealing in the long term. First, having
- two backends is essential during transition time, where both old and new backend is used.
- Second, there are external organizations that develop and presumably maintain LDAP backend
- for ISC-DHCP. Is at least possible that similar will happen for Kea. Finally, if we ever
- extend the isc::dhcp::CfgMgr with configuration export, this approach could be used as
- a migration tool.
- @section dhcpv6SignalBasedReconfiguration Reconfiguring DHCPv6 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::Dhcp6Srv 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.
- In order for the signal handler to know the location of the configuration file
- (specified at process startup), the location of this file needs to be stored
- in a static variable so as it may be directly accessed by the signal handler.
- This static variable is stored in the @c dhcp::Daemon class and all Kea processes
- can use it (all processes derive from this class). The configuration file
- location is initialized when the @c Daemon::init method is called. Therefore,
- derived classes should call it in their implementations of the @c init method.
- @section dhcpv6Other Other DHCPv6 topics
- For hooks API support in DHCPv6, see @ref dhcpv6Hooks.
- */
|