// Copyright (C) 2012-2013 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 DHCPv4 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 bind10-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 NameChangeRequests 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 bind10-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 bind10-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 if there is 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 dhcpv6Other Other DHCPv6 topics For hooks API support in DHCPv6, see @ref dhcpv6Hooks. */