Commit bc03b9cc authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

Merge branch 'master' into trac2340

with fixing conflicts in
	ChangeLog
	examples/README
parents 55be177f 0375b659
492. [func] tomek
libdhcpsrv: The DHCP Configuration Manager is now able to store
information about IPv4 subnets and pools. It is still not possible
to configure that information. Such capability will be implemented
in a near future.
(Trac #2237, git a78e560343b41f0f692c7903c938b2b2b24bf56b)
491. [func] tomek
b10-dhcp6: Configuration for DHCPv6 has been implemented.
Currently it is possible to configure IPv6 subnets and pools
within those subnets, global and per subnet values of renew,
rebind, preferred and valid lifetimes. Configured parameters
are accepted, but are not used yet by the allocation engine yet.
(Trac #2269, git 028bed9014b15facf1a29d3d4a822c9d14fc6411)
490. [func] tomek
libdhcpsrv: An abstract API for lease database has been
implemented. It offers a common interface to all concrete
database backends.
(Trac #2140, git df196f7609757253c4f2f918cd91012bb3af1163)
489. [func] muks
The isc::dns::RRsetList class has been removed. It was now unused
inside the BIND 10 codebase, and the interface was considered
prone to misuse.
(Trac #2266, git 532ac3d0054f6a11b91ee369964f3a84dabc6040)
488. [build] jinmei
On configure, changed the search order for Python executable.
It first ties more specific file names such as "python3.2" before
......
......@@ -57,29 +57,6 @@
* that does not support msgq. That is useful for embedded environments.
* It may also be useful in validation.
*
* @page dhcpv6 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.
*
* @page libdhcp libdhcp++
*
* @section libdhcpIntro Libdhcp++ Library Introduction
......
......@@ -15,12 +15,17 @@
* <a href="http://bind10.isc.org/">BIND10 webpage (http://bind10.isc.org)</a>
*
* @section DNS
* - Authoritative DNS (todo)
* - Recursive resolver (todo)
* - @subpage DataScrubbing
*
* @section DHCP
* - @subpage dhcpv4
* - @subpage dhcpv4Session
* - @subpage dhcpv6
* - @subpage dhcpv6-session
* - @subpage dhcpv6-config-parser
* - @subpage dhcpv6-config-inherit
* - @subpage libdhcp
* - @subpage libdhcpIntro
* - @subpage libdhcpIfaceMgr
......
......@@ -2751,13 +2751,13 @@ then change those defaults with config set Resolver/forward_addresses[0]/address
<title>DHCPv4 Server Configuration</title>
<para>
The DHCPv4 server does not have a lease database implemented yet
nor any support for configuration, so every time the same set
nor any support for configuration, so the same set
of configuration options (including the same fixed address)
will be assigned every time.
</para>
<para>
At this stage of development, the only way to alter the server
configuration is to tweak its source code. To do so, please
configuration is to modify its source code. To do so, please
edit src/bin/dhcp4/dhcp4_srv.cc file and modify following
parameters and recompile:
<screen>
......@@ -2944,16 +2944,95 @@ const std::string HARDCODED_SERVER_ID = "192.0.2.1";</screen>
<section id="dhcp6-config">
<title>DHCPv6 Server Configuration</title>
<para>
The DHCPv6 server does not have lease database implemented yet
or any support for configuration, so every time the same set
of configuration options (including the same fixed address)
will be assigned every time.
Once the server is started, it can be configured. To view the
current configuration, use the following command in <command>bindctl</command>:
<screen>
&gt; <userinput>config show Dhcp6</userinput></screen>
When starting Dhcp6 daemon for the first time, the default configuration
will be available. It will look similar to this:
<screen>
&gt; <userinput>config show Dhcp6</userinput>
Dhcp6/interface "eth0" string (default)
Dhcp6/renew-timer 1000 integer (default)
Dhcp6/rebind-timer 2000 integer (default)
Dhcp6/preferred-lifetime 3000 integer (default)
Dhcp6/valid-lifetime 4000 integer (default)
Dhcp6/subnet6 [] list (default)</screen>
</para>
<para>
At this stage of development, the only way to alter server
configuration is to tweak its source code. To do so, please
edit src/bin/dhcp6/dhcp6_srv.cc file, modify the following
parameters and recompile:
To change one of the parameters, simply follow
the usual <command>bindctl</command> procedure. For example, to make the
leases longer, change their valid-lifetime parameter:
<screen>
&gt; <userinput>config set Dhcp6/valid-lifetime 7200</userinput>
&gt; <userinput>config commit</userinput></screen>
Please note that most Dhcp6 parameters are of global scope
and apply to all defined subnets, unless they are overridden on a
per-subnet basis.
</para>
<para>
The essential role of DHCPv6 server is address assignment. The server
has to be configured with at least one subnet and one pool of dynamic
addresses to be managed. For example, assume that the server
is connected to a network segment that uses the 2001:db8:1::/64
prefix. The Administrator of that network has decided that addresses from range
2001:db8:1::1 to 2001:db8:1::ffff are going to be managed by the Dhcp6
server. Such a configuration can be achieved in the following way:
<screen>
&gt; <userinput>config add Dhcp6/subnet6</userinput>
&gt; <userinput>config set Dhcp6/subnet6[0]/subnet "2001:db8:1::/64"</userinput>
&gt; <userinput>config set Dhcp6/subnet6[0]/pool [ "2001:db8:1::0 - 2001:db8:1::ffff" ]</userinput>
&gt; <userinput>config commit</userinput></screen>
Note that subnet is defined as a simple string, but the pool parameter
is actually a list of pools: for this reason, the pool definition is
enclosed in square brackets, even though only one range of addresses
is specified.</para>
<para>It is possible to define more than one pool in a
subnet: continuing the previous example, further assume that
2001:db8:1:0:5::/80 should be also be managed by the server. It could be written as
2001:db8:1:0:5:: to 2001:db8:1::5:ffff:ffff:ffff, but typing so many 'f's
is cumbersome. It can be expressed more simply as 2001:db8:1:0:5::/80. Both
formats are supported by Dhcp6 and can be mixed in the pool list.
For example, one could define the following pools:
<screen>
&gt; <userinput>config set Dhcp6/subnet6[0]/pool [ "2001:db8:1::1 - 2001:db8:1::ffff", "2001:db8:1:0:5::/80" ]</userinput>
&gt; <userinput>config commit</userinput></screen>
The number of pools is not limited, but for performance reasons it is recommended to
use as few as possible.
</para>
<para>
The server may be configured to serve more than one subnet. To add a second subnet,
use a command similar to the following:
<screen>
&gt; <userinput>config add Dhcp6/subnet6</userinput>
&gt; <userinput>config set Dhcp6/subnet6[1]/subnet "2001:db8:beef::/48"</userinput>
&gt; <userinput>config set Dhcp6/subnet6[1]/pool [ "2001:db8:beef::/48" ]</userinput>
&gt; <userinput>config commit</userinput></screen>
Arrays are counted from 0. subnet[0] refers to the subnet defined in the
previous example. The <command>config add Dhcp6/subnet6</command> adds
another (second) subnet. It can be referred to as
<command>Dhcp6/subnet6[1]</command>. In this example, we allow server to
dynamically assign all addresses available in the whole subnet. Although
very wasteful, it is certainly a valid configuration to dedicate the
whole /48 subnet for that purpose.
</para>
<para>
When configuring a DHCPv6 server using prefix/length notation, please pay
attention to the boundary values. When specifying that the server should use
a given pool, it will be able to allocate also first (typically network
address) address from that pool. For example for pool 2001:db8::/64 the
2001:db8:: address may be assigned as well. If you want to avoid this,
please use min-max notation.
</para>
<para>
Note: Although configuration is now accepted, it is not internally used
by they server yet. At this stage of development, the only way to alter
server configuration is to modify its source code. To do so, please edit
src/bin/dhcp6/dhcp6_srv.cc file, modify the following parameters and
recompile:
<screen>
const std::string HARDCODED_LEASE = "2001:db8:1::1234:abcd";
const uint32_t HARDCODED_T1 = 1500; // in seconds
......
......@@ -7,7 +7,7 @@ this directory.
On the top (sub) directory (where this README file is stored), we
provide a sample configure.ac and Makefile.am files for GNU automake
environments with helper autoconf macros to detect the available and
environments with helper autoconf macros to detect the availability and
location of BIND 10 header files and library objects.
You can use the configure.ac and Makefile.am files with macros under
......
......@@ -93,7 +93,7 @@ public:
/// that corresponds to this derived class and prepares a new value to
/// apply to the server.
/// In the above example, the derived class for the identifier "param1"
/// would be passed an data \c Element storing an integer whose value
/// would be passed a data \c Element storing an integer whose value
/// is 10, and would record that value internally;
/// the derived class for the identifier "param2" would be passed a
/// map element and (after parsing) convert it into some internal
......
......@@ -46,6 +46,7 @@ pkglibexec_PROGRAMS = b10-dhcp6
b10_dhcp6_SOURCES = main.cc
b10_dhcp6_SOURCES += ctrl_dhcp6_srv.cc ctrl_dhcp6_srv.h
b10_dhcp6_SOURCES += config_parser.cc config_parser.h
b10_dhcp6_SOURCES += dhcp6_log.cc dhcp6_log.h
b10_dhcp6_SOURCES += dhcp6_srv.cc dhcp6_srv.h
......@@ -62,6 +63,7 @@ b10_dhcp6_LDADD = $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcp++.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/dhcp/libb10-dhcpsrv.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/config/libb10-cfgclient.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/cc/libb10-cc.la
......
This diff is collapsed.
// Copyright (C) 2012 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.
#include <string>
#include <exceptions/exceptions.h>
#include <cc/data.h>
#ifndef DHCP6_CONFIG_PARSER_H
#define DHCP6_CONFIG_PARSER_H
namespace isc {
namespace dhcp {
class Dhcpv6Srv;
/// An exception that is thrown if an error occurs while configuring an
/// \c Dhcpv6Srv object.
class Dhcp6ConfigError : public isc::Exception {
public:
/// @brief constructor
///
/// @param file name of the file, where exception occurred
/// @param line line of the file, where exception occurred
/// @param what text description of the issue that caused exception
Dhcp6ConfigError(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) {}
};
class DhcpConfigParser {
///
/// \name Constructors and Destructor
///
/// Note: The copy constructor and the assignment operator are
/// intentionally defined as private to make it explicit that this is a
/// pure base class.
//@{
private:
DhcpConfigParser(const DhcpConfigParser& source);
DhcpConfigParser& operator=(const DhcpConfigParser& source);
protected:
/// \brief The default constructor.
///
/// This is intentionally defined as \c protected as this base class should
/// never be instantiated (except as part of a derived class).
DhcpConfigParser() {}
public:
/// The destructor.
virtual ~DhcpConfigParser() {}
//@}
/// \brief Prepare configuration value.
///
/// This method parses the "value part" of the configuration identifier
/// that corresponds to this derived class and prepares a new value to
/// apply to the server.
///
/// This method must validate the given value both in terms of syntax
/// and semantics of the configuration, so that the server will be
/// validly configured at the time of \c commit(). Note: the given
/// configuration value is normally syntactically validated, but the
/// \c build() implementation must also expect invalid input. If it
/// detects an error it may throw an exception of a derived class
/// of \c isc::Exception.
///
/// Preparing a configuration value will often require resource
/// allocation. If it fails, it may throw a corresponding standard
/// exception.
///
/// This method is not expected to be called more than once in the
/// life of the object. Although multiple calls are not prohibited
/// by the interface, the behavior is undefined.
///
/// \param config_value The configuration value for the identifier
/// corresponding to the derived class.
virtual void build(isc::data::ConstElementPtr config_value) = 0;
/// \brief Apply the prepared configuration value to the server.
///
/// This method is expected to be exception free, and, as a consequence,
/// it should normally not involve resource allocation.
/// Typically it would simply perform exception free assignment or swap
/// operation on the value prepared in \c build().
/// In some cases, however, it may be very difficult to meet this
/// condition in a realistic way, while the failure case should really
/// be very rare. In such a case it may throw, and, if the parser is
/// called via \c configureDhcp6Server(), the caller will convert the
/// exception as a fatal error.
///
/// This method is expected to be called after \c build(), and only once.
/// The result is undefined otherwise.
virtual void commit() = 0;
};
/// @brief a pointer to configuration parser
typedef boost::shared_ptr<DhcpConfigParser> ParserPtr;
/// @brief a collection of parsers
///
/// This container is used to store pointer to parsers for a given scope.
typedef std::vector<ParserPtr> ParserCollection;
/// \brief Configure an \c Dhcpv6Srv object with a set of configuration values.
///
/// This function parses configuration information stored in \c config_set
/// and configures the \c server by applying the configuration to it.
/// It provides the strong exception guarantee as long as the underlying
/// derived class implementations of \c DhcpConfigParser meet the assumption,
/// that is, it ensures that either configuration is fully applied or the
/// state of the server is intact.
///
/// If a syntax or semantics level error happens during the configuration
/// (such as malformed configuration or invalid configuration parameter),
/// this function throws an exception of class \c Dhcp6ConfigError.
/// If the given configuration requires resource allocation and it fails,
/// a corresponding standard exception will be thrown.
/// Other exceptions may also be thrown, depending on the implementation of
/// the underlying derived class of \c Dhcp6ConfigError.
/// In any case the strong guarantee is provided as described above except
/// in the very rare cases where the \c commit() method of a parser throws
/// an exception. If that happens this function converts the exception
/// into a \c FatalError exception and rethrows it. This exception is
/// expected to be caught at the highest level of the application to terminate
/// the program gracefully.
///
/// \param server The \c Dhcpv6Srv object to be configured.
/// \param config_set A JSON style configuration to apply to \c server.
isc::data::ConstElementPtr
configureDhcp6Server(Dhcpv6Srv& server,
isc::data::ConstElementPtr config_set);
}; // end of isc::dhcp namespace
}; // end of isc namespace
#endif // DHCP6_CONFIG_PARSER_H
......@@ -25,6 +25,7 @@
#include <dhcp6/ctrl_dhcp6_srv.h>
#include <dhcp6/dhcp6_log.h>
#include <dhcp6/spec_config.h>
#include <dhcp6/config_parser.h>
#include <dhcp/iface_mgr.h>
#include <exceptions/exceptions.h>
#include <util/buffer.h>
......@@ -47,8 +48,15 @@ ConstElementPtr
ControlledDhcpv6Srv::dhcp6ConfigHandler(ConstElementPtr new_config) {
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_COMMAND, DHCP6_CONFIG_UPDATE)
.arg(new_config->str());
ConstElementPtr answer = isc::config::createAnswer(0,
"Thank you for sending config.");
if (server_) {
return (configureDhcp6Server(*server_, new_config));
}
// That should never happen as we install config_handler after we instantiate
// the server.
ConstElementPtr answer = isc::config::createAnswer(1,
"Configuration rejected, server is during startup/shutdown phase.");
return (answer);
}
......@@ -86,7 +94,7 @@ void ControlledDhcpv6Srv::sessionReader(void) {
}
void ControlledDhcpv6Srv::establishSession() {
string specfile;
if (getenv("B10_FROM_BUILD")) {
specfile = string(getenv("B10_FROM_BUILD")) +
......@@ -96,15 +104,27 @@ void ControlledDhcpv6Srv::establishSession() {
}
/// @todo: Check if session is not established already. Throw, if it is.
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_CCSESSION_STARTING)
.arg(specfile);
cc_session_ = new Session(io_service_.get_io_service());
config_session_ = new ModuleCCSession(specfile, *cc_session_,
dhcp6ConfigHandler,
NULL,
dhcp6CommandHandler, false);
config_session_->start();
// We initially create ModuleCCSession() without configHandler, as
// the session module is too eager to send partial configuration.
// We want to get the full configuration, so we explicitly call
// getFullConfig() and then pass it to our configHandler.
config_session_->setConfigHandler(dhcp6ConfigHandler);
try {
configureDhcp6Server(*this, config_session_->getFullConfig());
} catch (const Dhcp6ConfigError& ex) {
LOG_ERROR(dhcp6_logger, DHCP6_CONFIG_LOAD_FAIL).arg(ex.what());
}
/// Integrate the asynchronous I/O model of BIND 10 configuration
/// control with the "select" model of the DHCP server. This is
/// fully explained in \ref dhcpv6Session.
......
/**
@page dhcpv6 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 dhcpv6-session 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 dhcpv6-config-parser 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 \ref isc::dhcp::Dhcp6ConfigParser class. Once a parser is created
(constructor), its value is set (using build() method). Once all parsers are
build, the configuration is then applied ("commited") and commit() method is
called.
All parsers are defined in src/bin/dhcp6/config_parser.cc file. Some of them
are generic (e.g. \ref isc::dhcp::Uint32Parser that is able to handle any
unsigned 32 bit integer), but some are very specialized (e.g. \ref
isc::dhcp::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 dhcpv6-config-inherit DHCPv6 Configuration Inheritance
One notable useful features 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. \ref isc::dhcp::Uint32Parser and \ref
isc::dhcp::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 \ref isc::dhcp::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 \ref isc::dhcp::DummyParser. 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.
*/
......@@ -4,9 +4,97 @@
"module_description": "DHCPv6 server daemon",
"config_data": [
{ "item_name": "interface",
"item_type": "string",
"item_type": "list",
"item_optional": false,
"item_default": "eth0"
"item_default": [ "all" ],
"list_item_spec":
{
"item_name": "interface_name",
"item_type": "string",
"item_optional": false,
"item_default": "all"
}
} ,
{ "item_name": "renew-timer",
"item_type": "integer",
"item_optional": false,
"item_default": 1000
},
{ "item_name": "rebind-timer",
"item_type": "integer",
"item_optional": false,
"item_default": 2000
},
{ "item_name": "preferred-lifetime",
"item_type": "integer",
"item_optional": false,
"item_default": 3000
},
{ "item_name": "valid-lifetime",
"item_type": "integer",
"item_optional": false,
"item_default": 4000
},
{ "item_name": "subnet6",
"item_type": "list",
"item_optional": false,
"item_default": [],
"list_item_spec":
{
"item_name": "single-subnet6",
"item_type": "map",
"item_optional": false,
"item_default": {},
"map_item_spec": [
{ "item_name": "subnet",
"item_type": "string",
"item_optional": false,
"item_default": ""
},
{ "item_name": "renew-timer",
"item_type": "integer",
"item_optional": false,
"item_default": 1000
},
{ "item_name": "rebind-timer",
"item_type": "integer",
"item_optional": false,
"item_default": 2000
},
{ "item_name": "preferred-lifetime",
"item_type": "integer",
"item_optional": false,
"item_default": 3000
},
{ "item_name": "valid-lifetime",
"item_type": "integer",
"item_optional": false,
"item_default": 7200
},
{ "item_name": "pool",
"item_type": "list",
"item_optional": false,
"item_default": [],
"list_item_spec":
{
"item_name": "type",
"item_type": "string",
"item_optional": false,
"item_default": ""
}
}
]
}
}
],
"commands": [
......
......@@ -109,3 +109,23 @@ processed any command-line switches and is starting.
This is a debug message issued during the IPv6 DHCP server startup.
It lists some information about the parameters with which the server