Commit 7bf8cef1 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[master] Merge branch 'trac3467'

parents 3ca1a4f5 5c1d4387
......@@ -4,8 +4,10 @@ EXTRA_DIST = version.ent.in differences.txt Doxyfile Doxyfile-xml
nobase_dist_doc_DATA = examples/kea4/single-subnet.json
nobase_dist_doc_DATA += examples/kea4/several-subnets.json
nobase_dist_doc_DATA += examples/kea4/multiple-options.json
nobase_dist_doc_DATA += examples/kea6/simple.json
nobase_dist_doc_DATA += examples/kea6/several-subnets.json
nobase_dist_doc_DATA += examples/kea6/multiple-options.json
nobase_dist_doc_DATA += examples/ddns/sample1.json
nobase_dist_doc_DATA += examples/ddns/template.json
......
# This is an example configuration file for the DHCPv4 server in Kea.
# It demonstrates simple configuration of the options for a subnet.
{ "Dhcp4":
{
# Kea is told to listen on eth0 interface only.
"interfaces": [ "eth0" ],
# We need to specify lease type. As of May 2014, three backends are supported:
# memfile, mysql and pgsql. We'll just use memfile, because it doesn't require
# any prior set up.
"lease-database": {
"type": "memfile"
},
# Addresses will be assigned with valid lifetimes being 4000. Client
# is told to start renewing after 1000 seconds. If the server does not respond
# after 2000 seconds since the lease was granted, client is supposed
# to start REBIND procedure (emergency renewal that allows switching
# to a different server).
"valid-lifetime": 4000,
# Renew and rebind timers are commented out. This implies that options
# 58 and 59 will not be sent to the client. In this case it is up to
# the client to pick the timer values according to RFC2131. Uncomment the
# timers to send these options to the client.
# "renew-timer": 1000,
# "rebind-timer": 2000,
# Defining a subnet. There are 3 DHCP options returned to the
# clients connected to this subnet. The first two options are
# identified by the name. The third option is identified by the
# option code.
"subnet4": [
{
"pools": [ { "pool": "192.0.2.10 - 192.0.2.200" } ],
"subnet": "192.0.2.0/24",
"interface": "eth0",
"option-data": [
{
"name": "domain-name-servers",
"data": "192.0.2.1, 192.0.2.2"
},
{
"name": "routers",
"data": "192.0.2.1"
},
{
"code": 15,
"data": "example.org"
}
]
}
]
},
# The following configures logging. It assumes that messages with at least
# informational level (info, warn, error) will will be logged to stdout.
"Logging": {
"loggers": [
{
"name": "kea-dhcp4",
"output_options": [
{
"output": "stdout"
}
],
"severity": "INFO"
}
]
}
}
# This is an example configuration file for DHCPv6 server in Kea.
# It demonstrates simple configuration of the options for a subnet.
{ "Dhcp6":
{
# Kea is told to listen on eth0 interface only.
"interfaces": [ "eth0" ],
# We need to specify lease type. As of May 2014, three backends are supported:
# memfile, mysql and pgsql. We'll just use memfile, because it doesn't require
# any prior set up.
"lease-database": {
"type": "memfile"
},
# Addresses will be assigned with preferred and valid lifetimes
# being 3000 and 4000, respectively. Client is told to start
# renewing after 1000 seconds. If the server does not repond
# after 2000 seconds since the lease was granted, client is supposed
# to start REBIND procedure (emergency renewal that allows switching
# to a different server).
"preferred-lifetime": 3000,
"valid-lifetime": 4000,
"renew-timer": 1000,
"rebind-timer": 2000,
# Defining a subnet. There are 2 DHCP options returned to the
# clients connected to this subnet. The first option is identified
# by the name. The second option is identified by the code.
"subnet6": [
{
"pools": [ { "pool": "2001:db8:1::/80" } ],
"subnet": "2001:db8:1::/64",
"interface": "eth0",
"option-data": [
{
"name": "dns-servers",
"data": "2001:db8:2::45, 2001:db8:2::100"
},
{
"code": 12,
"data": "2001:db8:1:0:ff00::1"
},
]
}
]
},
# The following configures logging. Kea will log all debug messages
# to /var/log/kea-debug.log file.
"Logging": {
"loggers": [
{
"name": "kea-dhcp6",
"output_options": [
{
"output": "/var/log/kea-debug.log"
}
],
"debuglevel": 99,
"severity": "DEBUG"
}
]
}
}
......@@ -552,6 +552,12 @@ temporarily override a list of interface names and listen on all interfaces.
}</screen>
</para>
<para>
Most of the parameters in the "option-data" structure are optional and
can be omitted in some circumstances as discussed in the
<xref linkend="dhcp4-option-data-defaults"/>.
</para>
<para>
It is possible to specify or override options on a per-subnet basis. If
clients connected to most of your subnets are expected to get the
......@@ -589,15 +595,6 @@ temporarily override a list of interface names and listen on all interfaces.
</screen>
</para>
<note>
<para>
In future versions of Kea, it will not be necessary to specify
the <command>code</command>, <command>space</command>
and <command>csv-format</command> fields, as they will
be set automatically.
</para>
</note>
<para>
The currently supported standard DHCPv4 options are
listed in <xref linkend="dhcp4-std-options-list"/>
......@@ -1099,6 +1096,76 @@ temporarily override a list of interface names and listen on all interfaces.
</para>
</section>
<section id="dhcp4-option-data-defaults">
<title>Unspecified parameters for DHCPv4 option configuration</title>
<para>In many cases it is not required to specify all parameters for
an option configuration and the default values may be used. However, it is
important to understand the implications of not specifing some of them
as it may result in configuration errors. The list below explains
the behavior of the server when a particular parameter is not explicitly
specified:
<itemizedlist>
<listitem>
<simpara><command>name</command> - the server requires an option name or
option code to identify an option. If this parameter is unspecified, the
option code must be specified.
</simpara>
</listitem>
<listitem>
<simpara><command>code</command> - the server requires an option name or
option code to identify an option. This parameter may be left unspecified if
the <command>name</command> parameter is specified. However, this also
requires that the particular option has its definition (it is either a
standard option or an administrator created a definition for the option
using an 'option-def' structure), as the option definition associates an
option with a particular name. It is possible to configure an option
for which there is no definition (unspecified option format).
Configuration of such options requires the use of option code.
</simpara>
</listitem>
<listitem>
<simpara><command>space</command> - if the option space is unspecified it
will default to 'dhcp4' which is an option space holding DHCPv4 standard
options.
</simpara>
</listitem>
<listitem>
<simpara><command>data</command> - if the option data is unspecified it
defaults to an empty value. The empty value is mostly used for the
options which have no payload (boolean options), but it is legal to specify
empty values for some options which carry variable length data and which
spec allows for the length of 0. For such options, the data parameter
may be omitted in the configuration.</simpara>
</listitem>
<listitem>
<simpara><command>csv-format</command> - if this value is not specified
and the definition for the particular option exists, the server will assume
that the option data is specified as a list of comma separated values to be
assigned to individual fields of the DHCP option. If the definition
does not exist for this option, the server will assume that the data
parameter contains the option payload in the binary format (represented
as a string of hexadecimal digits). Note that not specifying this
parameter doesn't imply that it defaults to a fixed value, but
the configuration data interpretation also depends on the presence
of the option definition. An administrator must be aware if the
definition for the particular option exists when this parameter
is not specified. It is generally recommended to not specify this
parameter only for the options for which the definition exists, e.g.
standard options. Setting <command>csv-format</command> to an explicit
value will cause the server to strictly check the format of the option
data specified.
</simpara>
</listitem>
</itemizedlist>
</para>
</section>
<section id="dhcp4-stateless-configuration">
<title>Stateless Configuration of DHCPv4 clients</title>
<para>The DHCPv4 server supports the stateless client configuration whereby the
......
......@@ -647,6 +647,13 @@ temporarily override a list of interface names and listen on all interfaces.
to validate data correctness in hexadecimal is limited.
</para>
<para>
Most of the parameters in the "option-data" structure are optional and
can be omitted in some circumstances as discussed in the
<xref linkend="dhcp6-option-data-defaults"/>.
</para>
<para>
It is possible to override options on a per-subnet basis. If
clients connected to most of your subnets are expected to get the
......@@ -684,16 +691,6 @@ temporarily override a list of interface names and listen on all interfaces.
</screen>
</para>
<note>
<para>
In future versions of Kea, it will not be necessary to specify
the <command>code</command>, <command>space</command>
and <command>csv-format</command> fields, as they will
be set automatically.
</para>
</note>
<para>
The currently supported standard DHCPv6 options are
listed in <xref linkend="dhcp6-std-options-list"/>.
......@@ -1093,6 +1090,76 @@ should include options from the isc option space:
</para>
</section>
<section id="dhcp6-option-data-defaults">
<title>Unspecified parameters for DHCPv6 option configuration</title>
<para>In many cases it is not required to specify all parameters for
an option configuration and the default values can be used. However, it is
important to understand the implications of not specifing some of them
as it may result in configuration errors. The list below explains
the behavior of the server when a particular parameter is not explicitly
specified:
<itemizedlist>
<listitem>
<simpara><command>name</command> - the server requires an option name or
option code to identify an option. If this parameter is unspecified, the
option code must be specified.
</simpara>
</listitem>
<listitem>
<simpara><command>code</command> - the server requires an option name or
option code to identify an option. This parameter may be left unspecified if
the <command>name</command> parameter is specified. However, this also
requires that the particular option has its definition (it is either a
standard option or an administrator created a definition for the option
using an 'option-def' structure), as the option definition associates an
option with a particular name. It is possible to configure an option
for which there is no definition (unspecified option format).
Configuration of such options requires the use of option code.
</simpara>
</listitem>
<listitem>
<simpara><command>space</command> - if the option space is unspecified it
will default to 'dhcp6' which is an option space holding DHCPv6 standard
options.
</simpara>
</listitem>
<listitem>
<simpara><command>data</command> - if the option data is unspecified it
defaults to an empty value. The empty value is mostly used for the
options which have no payload (boolean options), but it is legal to specify
empty values for some options which carry variable length data and which
spec allows for the length of 0. For such options, the data parameter
may be omitted in the configuration.</simpara>
</listitem>
<listitem>
<simpara><command>csv-format</command> - if this value is not specified
and the definition for the particular option exists, the server will assume
that the option data is specified as a list of comma separated values to be
assigned to individual fields of the DHCP option. If the definition
does not exist for this option, the server will assume that the data
parameter contains the option payload in the binary format (represented
as a string of hexadecimal digits). Note that not specifying this
parameter doesn't imply that it defaults to a fixed value, but
the configuration data interpretation also depends on the presence
of the option definition. An administrator must be aware if the
definition for the particular option exists when this parameter
is not specified. It is generally recommended to not specify this
parameter only for the options for which the definition exists, e.g.
standard options. Setting <command>csv-format</command> to an explicit
value will cause the server to strictly check the format of the option
data specified.
</simpara>
</listitem>
</itemizedlist>
</para>
</section>
<section id="dhcp6-config-subnets">
<title>IPv6 Subnet Selection</title>
<para>
......
......@@ -129,6 +129,41 @@ LibDHCP::getOptionDef(const Option::Universe u, const uint16_t code) {
return (OptionDefinitionPtr());
}
OptionDefinitionPtr
LibDHCP::getOptionDef(const Option::Universe u, const std::string& name) {
const OptionDefContainer& defs = getOptionDefs(u);
const OptionDefContainerNameIndex& idx = defs.get<2>();
const OptionDefContainerNameRange& range = idx.equal_range(name);
if (range.first != range.second) {
return (*range.first);
}
return (OptionDefinitionPtr());
}
OptionDefinitionPtr
LibDHCP::getVendorOptionDef(const Option::Universe u, const uint32_t vendor_id,
const std::string& name) {
const OptionDefContainer* defs = NULL;
if (u == Option::V4) {
defs = getVendorOption4Defs(vendor_id);
} else if (u == Option::V6) {
defs = getVendorOption6Defs(vendor_id);
}
if (!defs) {
return (OptionDefinitionPtr());
}
const OptionDefContainerNameIndex& idx = defs->get<2>();
const OptionDefContainerNameRange& range = idx.equal_range(name);
if (range.first != range.second) {
return (*range.first);
}
return (OptionDefinitionPtr());
}
OptionDefinitionPtr
LibDHCP::getVendorOptionDef(const Option::Universe u, const uint32_t vendor_id,
const uint16_t code) {
......
// Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-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
......@@ -20,6 +20,7 @@
#include <util/buffer.h>
#include <iostream>
#include <string>
namespace isc {
namespace dhcp {
......@@ -55,6 +56,16 @@ public:
static OptionDefinitionPtr getOptionDef(const Option::Universe u,
const uint16_t code);
/// @brief Return the definition of option having a specified name.
///
/// @param u universe (v4 or V6)
/// @param name Option name.
///
/// @return Pointer to the option definition or NULL pointer if option
/// definition has not been found.
static OptionDefinitionPtr getOptionDef(const Option::Universe u,
const std::string& name);
/// @brief Returns vendor option definition for a given vendor-id and code
///
/// @param u universe (V4 or V6)
......@@ -66,6 +77,19 @@ public:
const uint32_t vendor_id,
const uint16_t code);
/// @brief Returns vendor option definition for a given vendor-id and
/// option name.
///
/// @param u Universe (V4 or V6)
/// @param vendor_id Enterprise-id for a given vendor
/// @param name Option name.
///
/// @return A pointer to an option definition or NULL pointer if
/// no option definition found.
static OptionDefinitionPtr getVendorOptionDef(const Option::Universe u,
const uint32_t vendor_id,
const std::string& name);
/// @brief Check if the specified option is a standard option.
///
/// @param u universe (V4 or V6)
......
// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-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
......@@ -17,7 +17,7 @@
#include <asiolink/io_address.h>
#include <dhcp/option.h>
#include <boost/shared_ptr.hpp>
#include <vector>
namespace isc {
......@@ -94,6 +94,9 @@ protected:
AddressContainer addrs_;
};
/// @brief Pointer to the @c Option6AddrLst object.
typedef boost::shared_ptr<Option6AddrLst> Option6AddrLstPtr;
} // isc::dhcp namespace
} // isc namespace
......
......@@ -717,6 +717,17 @@ typedef boost::multi_index_container<
uint16_t,
&OptionDefinition::getCode
>
>,
// Start definition of index #2
boost::multi_index::hashed_non_unique<
// Use option name as the index key. This value is
// returned by the @c OptionDefinition::getName
// method.
boost::multi_index::const_mem_fun<
OptionDefinition,
std::string,
&OptionDefinition::getName
>
>
>
> OptionDefContainer;
......@@ -736,6 +747,15 @@ typedef OptionDefContainer::nth_index<1>::type OptionDefContainerTypeIndex;
typedef std::pair<OptionDefContainerTypeIndex::const_iterator,
OptionDefContainerTypeIndex::const_iterator> OptionDefContainerTypeRange;
/// Type of the index #2 - option name.
typedef OptionDefContainer::nth_index<2>::type OptionDefContainerNameIndex;
/// Pair of iterators to represent the range of options definitions
/// having the same option name. The first element in this pair
/// represents the beginning of the range, the second element
/// represents the end.
typedef std::pair<OptionDefContainerNameIndex::const_iterator,
OptionDefContainerNameIndex::const_iterator> OptionDefContainerNameRange;
} // namespace isc::dhcp
} // namespace isc
......
......@@ -16,6 +16,7 @@
#include <dhcp/dhcp4.h>
#include <dhcp/dhcp6.h>
#include <dhcp/docsis3_option_defs.h>
#include <dhcp/libdhcp++.h>
#include <dhcp/option4_addrlst.h>
#include <dhcp/option4_client_fqdn.h>
......@@ -1141,6 +1142,69 @@ TEST_F(LibDhcpTest, stdOptionDefs6) {
typeid(Option6AddrLst));
}
// This test checks if the DHCPv6 option definition can be searched by
// an option name.
TEST_F(LibDhcpTest, getOptionDefByName6) {
// Get all definitions.
const OptionDefContainer& defs = LibDHCP::getOptionDefs(Option::V6);
// For each definition try to find it using option name.
for (OptionDefContainer::const_iterator def = defs.begin();
def != defs.end(); ++def) {
OptionDefinitionPtr def_by_name =
LibDHCP::getOptionDef(Option::V6, (*def)->getName());
ASSERT_TRUE(def_by_name);
ASSERT_TRUE(**def == *def_by_name);
}
}
// This test checks if the DHCPv4 option definition can be searched by
// an option name.
TEST_F(LibDhcpTest, getOptionDefByName4) {
// Get all definitions.
const OptionDefContainer& defs = LibDHCP::getOptionDefs(Option::V4);
// For each definition try to find it using option name.
for (OptionDefContainer::const_iterator def = defs.begin();
def != defs.end(); ++def) {
OptionDefinitionPtr def_by_name =
LibDHCP::getOptionDef(Option::V4, (*def)->getName());
ASSERT_TRUE(def_by_name);
ASSERT_TRUE(**def == *def_by_name);
}
}
// This test checks if the definition of the DHCPv6 vendor option can
// be searched by option name.
TEST_F(LibDhcpTest, getVendorOptionDefByName6) {
const OptionDefContainer* defs =
LibDHCP::getVendorOption6Defs(VENDOR_ID_CABLE_LABS);
ASSERT_TRUE(defs != NULL);
for (OptionDefContainer::const_iterator def = defs->begin();
def != defs->end(); ++def) {
OptionDefinitionPtr def_by_name =
LibDHCP::getVendorOptionDef(Option::V6, VENDOR_ID_CABLE_LABS,
(*def)->getName());
ASSERT_TRUE(def_by_name);
ASSERT_TRUE(**def == *def_by_name);
}
}
// This test checks if the definition of the DHCPv4 vendor option can
// be searched by option name.
TEST_F(LibDhcpTest, getVendorOptionDefByName4) {
const OptionDefContainer* defs =
LibDHCP::getVendorOption4Defs(VENDOR_ID_CABLE_LABS);
ASSERT_TRUE(defs != NULL);
for (OptionDefContainer::const_iterator def = defs->begin();
def != defs->end(); ++def) {
OptionDefinitionPtr def_by_name =
LibDHCP::getVendorOptionDef(Option::V4, VENDOR_ID_CABLE_LABS,
(*def)->getName());
ASSERT_TRUE(def_by_name);
ASSERT_TRUE(**def == *def_by_name);
}
}
// tests whether v6 vendor-class option can be parsed properly.
TEST_F(LibDhcpTest, vendorClass6) {
......
......@@ -138,7 +138,27 @@ CfgOptionDef::get(const std::string& option_space,
return (OptionDefinitionPtr());
}
OptionDefinitionPtr
CfgOptionDef::get(const std::string& option_space,
const std::string& option_name) const {
// Get the pointer to collection of the option definitions that belong
// to the particular option space.
OptionDefContainerPtr defs = getAll(option_space);
// If there are any option definitions for this option space, get the