Commit 02f6c505 authored by Thomas Markwalder's avatar Thomas Markwalder
Browse files

[4096] Merge branch 'master' into trac4096

    Eval library now supports actual parsing.  Need to use it
    in class definition's ExpressionParser.
parents 668ec9e6 ab2bcf4e
1050. [doc] [tmark]
Corrected the descriptions of ncr-protocol and ncr-format parameters
in the Kea Admin Guide.
(Trac #4117 git 034c1c95b57768d5abbc7fb40cc57d7cadad21dd)
1049. [build] fdupont
Add a new --enable-generate-parser configuration parameter
(disabled by default) which makes flex and bison to regenerate
parser files.
(trac #4125, git 18321bf85f93b24d720f1ab2d90b4f4da85bc471)
1048. [func] fdupont,tomek
Implement expression parser for client classification.
(Trac #4088, git ac9eb312bfd1c6bf22a868ad789a0c049f33f637)
1047. [func]* stephen
Change the way that hooks libraries are defined in the configuration
file in preparation for allowing the specification of library-specific
parameters in a future version of Kea.
(Trac #3259, git b2986b0b0299e691b13123922129bdbf8575afdb)
1046. [func] tmark
Upon startup Kea servers will now detect memfile lease files
that need upgrading, and will launch in instance of the LFC
to convert them to the most current memfile schema version.
(Trac #3601, git ce4b0e42e8a01bbf3b58fdb1f505bbd6e2fad134)
1045. [func] tmark
Added classes for storing client class definitions to libdhcpsrv.
(Trac #4095, git 1039a942450e2a45a1e1aa9924cae4fdbd1541fe)
......
......@@ -1212,6 +1212,51 @@ AC_SUBST(PERL)
AC_PATH_PROGS(AWK, gawk awk)
AC_SUBST(AWK)
AC_ARG_ENABLE(generate_parser, [AC_HELP_STRING([--enable-generate-parser],
[indicates that the parsers will be regenerated. This implies that the
bison and flex are required [default=no]])],
enable_generate_parser=$enableval, enable_generate_parser=no)
# Check if flex is avaible. Flex is not needed for building Kea sources,
# unless you want to regenerate grammar in src/lib/eval
AC_PROG_LEX
# Check if bison is available. Bison is not needed for building Kea sources,
# unless you want to regenerate grammar in src/lib/eval
AC_PROG_YACC
if test "x$enable_generate_parser" != "xno"; then
if test "x$LEX" == "x"; then
AC_MSG_ERROR([Flex is required for enable-generate-parser, but was not found])
fi
if test "x$YACC" == "x"; then
AC_MSG_ERROR([Bison is required for enable-generate-parser, but was not found])
fi
# Ok, let's check if we have at least 3.0.0 version of the bison. The code used
# to generate src/lib/eval parser is roughly based on bison 3.0 examples.
cat > bisontest.y << EOF
%require "3.0.0"
%token X
%%
%start Y;
Y: X;
EOF
# Try to compile.
$YACC bisontest.y -o bisontest.cc
if test $? -ne 0 ; then
$YACC -V
$RM -f bisontest.y bisontest.cc
AC_MSG_ERROR("Error with $YACC. Possibly incorrect version? Required at least 3.0.0.")
fi
$RM -f bisontest.y bisontest.cc
fi
AM_CONDITIONAL([GENERATE_PARSER], [test x$enable_generate_parser != xno])
AC_ARG_ENABLE(generate_docs, [AC_HELP_STRING([--enable-generate-docs],
[regenerate documentation using Docbook [default=no]])],
enable_generate_docs=$enableval, enable_generate_docs=no)
......@@ -1527,6 +1572,10 @@ Log4cplus:
Kea config backend:
CONFIG_BACKEND: ${CONFIG_BACKEND}
Flex/bison:
FLEX: ${LEX}
BISON: ${YACC}
END
# Avoid confusion on DNS/DHCP and only mention MySQL if it
......@@ -1587,6 +1636,7 @@ Developer:
C++ Code Coverage: $USE_LCOV
Logger checks: $enable_logger_checks
Generate Documentation: $enable_generate_docs
Parser Generation: $enable_generate_parser
END
......
......@@ -8,20 +8,22 @@ EXTRA_DIST += devel/qa.dox
EXTRA_DIST += images/isc-logo.png
nobase_dist_doc_DATA = examples/kea4/single-subnet.json
nobase_dist_doc_DATA += examples/kea4/several-subnets.json
nobase_dist_doc_DATA = examples/ddns/sample1.json
nobase_dist_doc_DATA += examples/ddns/template.json
nobase_dist_doc_DATA += examples/kea4/hooks.json
nobase_dist_doc_DATA += examples/kea4/leases-expiration.json
nobase_dist_doc_DATA += examples/kea4/multiple-options.json
nobase_dist_doc_DATA += examples/kea4/reservations.json
nobase_dist_doc_DATA += examples/kea4/leases-expiration.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/kea4/several-subnets.json
nobase_dist_doc_DATA += examples/kea4/single-subnet.json
nobase_dist_doc_DATA += examples/kea6/advanced.json
nobase_dist_doc_DATA += examples/kea6/stateless.json
nobase_dist_doc_DATA += examples/kea6/reservations.json
nobase_dist_doc_DATA += examples/kea6/hooks.json
nobase_dist_doc_DATA += examples/kea6/leases-expiration.json
nobase_dist_doc_DATA += examples/ddns/sample1.json
nobase_dist_doc_DATA += examples/ddns/template.json
nobase_dist_doc_DATA += examples/kea6/multiple-options.json
nobase_dist_doc_DATA += examples/kea6/reservations.json
nobase_dist_doc_DATA += examples/kea6/several-subnets.json
nobase_dist_doc_DATA += examples/kea6/simple.json
nobase_dist_doc_DATA += examples/kea6/stateless.json
devel:
mkdir -p html
......
# This is an example configuration file for the DHCPv4 server in Kea
# illustrating the configuration of hooks libraries. It uses a basic scenario
# of one IPv4 subnet configured with the default values for all parameters.
{"Dhcp4":
{
# Kea is told to listen on the ethX interface only.
"interfaces-config": {
"interfaces": [ "ethX" ]
},
# Set up the storage for leases.
"lease-database": {
"type": "memfile"
},
# Define a single subnet.
"subnet4": [
{
"pools": [ { "pool": "192.0.2.1 - 19.2.0.2.200" } ],
"subnet": "192.0.2.0/24",
"interface": "ethX"
}
],
# Set up the hooks libraries. For this example, we assume that two libraries
# are loaded, called "security" and "charging". Note that order is important:
# "security" is specified first so if both libraries supply a hook function
# for a given hook, the function in "security" will be called before that in
# "charging".
"hooks-libraries": [
{
"library": "/opt/lib/security.so"
},
{
"library": "/opt/lib/charging.so"
}
]
}
}
# This is an example configuration file for the DHCPv6 server in Kea
# illustrating the configuration of hooks libraries. It uses a basic scenario
# of one IPv6 subnet configured with the default values for all parameters.
{"Dhcp6":
{
# Kea is told to listen on the ethX interface only.
"interfaces-config": {
"interfaces": [ "ethX" ]
},
# Set up the storage for leases.
"lease-database": {
"type": "memfile"
},
# Define a single subnet.
"subnet6": [
{
"pools": [ { "pool": "2001:db8:1::/80" } ],
"subnet": "2001:db8:1::/64",
"interface": "ethX"
}
],
# Set up the hooks libraries. For this example, we assume that two libraries
# are loaded, called "security" and "charging". Note that order is important:
# "security" is specified first so if both libraries supply a hook function
# for a given hook, the function in "security" will be called before that in
# "charging".
"hooks-libraries": [
{
"library": "/opt/lib/security.so"
},
{
"library": "/opt/lib/charging.so"
}
]
}
}
......@@ -150,6 +150,27 @@
will create an empty lease file if one is not
present. Necessary disk write permission is required.
</para>
<section id="memfile-upgrade">
<title>Upgrading Memfile Lease Files from an Earlier Version of Kea</title>
<para>
There are no special steps required to upgrade memfile lease files
from an earlier version of Kea to a new version of Kea.
During startup the servers will check the schema version of the lease
files against their own. If there is a mismatch, the servers will
automatically launch the LFC process to convert the files to the
server's schema version. While this mechanism is primarily meant to
ease the process of upgrading to newer versions of Kea, it can also
be used for downgrading should the need arise. When upgrading, any
values not present in the original lease files will be assigned
appropriate default values. When downgrading, any data present in
the files but not in the server's schema will be dropped.
If you wish to convert the files manually, prior to starting the
servers you may do so by running the LFC process yourself.
See <xref linkend="kea-lfc"/> for more information.
</para>
</section>
<!-- @todo: document lease file upgrades once they are implemented in kea-admin -->
</section>
......
......@@ -152,7 +152,7 @@ strings <userinput>path</userinput>/kea-dhcp-ddns | sed -n 's/;;;; //p'
If the file already exists and contains the PID of a live process,
the server will issue a DHCP_DDNS_ALREADY_RUNNING log message and exit. It
is possible, though unlikely, that the file is a remnant of a system crash
and the process to which the PID belongs is unrelated to Kea. In such a
and the process to which the PID belongs is unrelated to Kea. In such a
case it would be necessary to manually delete the PID file.
</para>
......@@ -233,15 +233,15 @@ strings <userinput>path</userinput>/kea-dhcp-ddns | sed -n 's/;;;; //p'
</simpara></listitem>
<listitem><simpara>
<command>ncr_protocol</command> - Packet format to use when sending requests to D2.
Currently only JSON format is supported. Other formats may be available
in future releases.
<command>ncr_protocol</command> - Socket protocol to use when sending requests to D2.
Currently only UDP is supported. TCP may be available in an upcoming
release.
</simpara></listitem>
<listitem><simpara>
<command>ncr_format</command> - Socket protocol to use when sending requests to D2.
Currently only UDP is supported. TCP may be available in an upcoming
release.
<command>ncr_format</command> - Packet format to use when sending requests to D2.
Currently only JSON format is supported. Other formats may be available
in future releases.
</simpara></listitem>
</itemizedlist>
......
......@@ -1769,18 +1769,15 @@ It is merely echoed by the server
continue lease operations without running the risk that its memory usage
grows without limit. The default value is 1024.
</simpara></listitem>
<listitem><simpara>
<command>ncr-format</command> - socket protocol use when sending requests to D2. Currently
<command>ncr-protocol</command> - socket protocol use when sending requests to D2. Currently
only UDP is supported. TCP may be available in an upcoming release.
</simpara></listitem>
<listitem><simpara>
<command>ncr-protocol</command> - packet format to use when sending requests to D2.
<command>ncr-format</command> - packet format to use when sending requests to D2.
Currently only JSON format is supported. Other formats may be available
in future releases.
</simpara></listitem>
</itemizedlist>
By default, kea-dhcp-ddns is assumed to be running on the same machine as kea-dhcp4, and
all of the default values mentioned above should be sufficient.
......
......@@ -1751,11 +1751,11 @@ should include options from the isc option space:
continue lease operations. The default value is 1024.
</simpara></listitem>
<listitem><simpara>
<command>ncr-format</command> - Socket protocol use when sending requests to D2. Currently
<command>ncr-protocol</command> - Socket protocol use when sending requests to D2. Currently
only UDP is supported. TCP may be available in an upcoming release.
</simpara></listitem>
<listitem><simpara>
<command>ncr-protocol</command> - Packet format to use when sending requests to D2.
<command>ncr-format</command> - Packet format to use when sending requests to D2.
Currently only JSON format is supported. Other formats may be available
in future releases.
</simpara></listitem>
......
......@@ -46,25 +46,30 @@
<command>hooks-libraries</command> keyword in the
configuration for that process. (Note that
the word "hooks" is plural). The value of the keyword
is an array of strings, each string corresponding to a hooks library.
For example, to set up two hooks libraries for the DHCPv4 server, the
configuration would be:
is an array of map structures, each structure corresponding to a hooks
library. For example, to set up two hooks libraries for the DHCPv4
server, the configuration would be:
<screen>
<userinput>"Dhcp4": {
:
"hooks-libraries": [
"/opt/charging.so",
"/opt/local/notification.so"
{
"library": "/opt/charging.so"
},
{
"library": "/opt/local/notification.so"
}
]
:
}</userinput>
</screen>
</para>
<note><para>
At present, the libraries are specified as a simple list. A future
version of Kea will support the capability of specifying a set of
parameters for each library. When that is added, it is likely
that the syntax for specifying hooks libraries will change.
This is a change to the syntax used in Kea 0.9.2 and earlier, where
hooks-libraries was a list of strings, each string being the name of
a library. The change has been made in Kea 1.0 to facilitate the
specification of library-specific parameters, a feature that will be
added to a future version of Kea.
</para></note>
<para>
Notes:
......@@ -79,7 +84,18 @@
<listitem><para>
An empty list has the same effect as omitting the
<command>hooks-libraries</command> configuration element all together.
</para></listitem>
</para>
<note><para>
There is one case where this is not true: if Kea
is running with a configuration that contains a
<command>hooks-libraries</command> item, and that item is
removed and the configuration reloaded, the removal will be
ignored and the libraries remain loaded. As a workaround,
instead of removing the <command>hooks-libraries</command>
item, change it to an empty list. This will be fixed in a
future version of Kea.
</para></note>
</listitem>
</itemizedlist>
</para>
<para>
......
......@@ -10,10 +10,18 @@
"item_default": [],
"list_item_spec":
{
"item_name": "hooks-library",
"item_type": "string",
"item_name": "hooks-library-spec",
"item_type": "map",
"item_optional": false,
"item_default": ""
"item_default": {},
"map_item_spec": [
{
"item_name": "library",
"item_type": "string",
"item_optional": false,
"item_default": ""
}
]
}
},
......
......@@ -2772,7 +2772,6 @@ TEST_F(Dhcp4ParserTest, vendorOptionsCsv) {
// of hooks libraries.
std::string
buildHooksLibrariesConfig(const std::vector<std::string>& libraries) {
const string quote("\"");
// Create the first part of the configuration string.
string config =
......@@ -2786,7 +2785,7 @@ buildHooksLibrariesConfig(const std::vector<std::string>& libraries) {
if (i > 0) {
config += string(", ");
}
config += (quote + libraries[i] + quote);
config += (string("{ \"library\": \"") + libraries[i] + string("\" }"));
}
// Append the remainder of the configuration.
......
......@@ -10,10 +10,18 @@
"item_default": [],
"list_item_spec":
{
"item_name": "hooks-library",
"item_type": "string",
"item_name": "hooks-library-spec",
"item_type": "map",
"item_optional": false,
"item_default": ""
"item_default": {},
"map_item_spec": [
{
"item_name": "library",
"item_type": "string",
"item_optional": false,
"item_default": ""
}
]
}
},
......
......@@ -2912,6 +2912,9 @@ TEST_F(Dhcp6ParserTest, DISABLED_stdOptionDataEncapsulate) {
// of hooks libraries.
std::string
buildHooksLibrariesConfig(const std::vector<std::string>& libraries) {
const string lbrace("{");
const string rbrace("}");
const string liblabel("\"library\": ");
const string quote("\"");
// Create the first part of the configuration string.
......@@ -2924,7 +2927,7 @@ buildHooksLibrariesConfig(const std::vector<std::string>& libraries) {
if (i > 0) {
config += string(", ");
}
config += (quote + libraries[i] + quote);
config += (lbrace + liblabel + quote + libraries[i] + quote + rbrace);
}
// Append the remainder of the configuration.
......
......@@ -132,7 +132,7 @@ typedef boost::shared_ptr<ClientClassDef> ClientClassDefPtr;
/// @brief Defines a map of ClientClassDef's, keyed by the class name.
typedef std::map<std::string,ClientClassDefPtr> ClientClassDefMap;
/// @brief Defines a pointer to a ClientClassDictionary
/// @brief Defines a pointer to a ClientClassDefMap
typedef boost::shared_ptr<ClientClassDefMap> ClientClassDefMapPtr;
/// @brief Defines a pair for working wiht ClientClassMap
......
......@@ -22,14 +22,14 @@ namespace isc {
namespace dhcp {
CSVLeaseFile4::CSVLeaseFile4(const std::string& filename)
: CSVFile(filename) {
: VersionedCSVFile(filename) {
initColumns();
}
void
CSVLeaseFile4::open(const bool seek_to_end) {
// Call the base class to open the file
CSVFile::open(seek_to_end);
VersionedCSVFile::open(seek_to_end);
// and clear any statistics we may have
clearStatistics();
......@@ -62,7 +62,7 @@ CSVLeaseFile4::append(const Lease4& lease) {
row.writeAt(getColumnIndex("state"), lease.state_);
try {
CSVFile::append(row);
VersionedCSVFile::append(row);
} catch (const std::exception&) {
// Catch any errors so we can bump the error counter than rethrow it
++write_errs_;
......@@ -85,7 +85,7 @@ CSVLeaseFile4::next(Lease4Ptr& lease) {
try {
// Get the row of CSV values.
CSVRow row;
CSVFile::next(row);
VersionedCSVFile::next(row);
// The empty row signals EOF.
if (row == CSVFile::EMPTY_ROW()) {
lease.reset();
......@@ -137,16 +137,18 @@ CSVLeaseFile4::next(Lease4Ptr& lease) {
void
CSVLeaseFile4::initColumns() {
addColumn("address");
addColumn("hwaddr");
addColumn("client_id");
addColumn("valid_lifetime");
addColumn("expire");
addColumn("subnet_id");
addColumn("fqdn_fwd");
addColumn("fqdn_rev");
addColumn("hostname");
addColumn("state");
addColumn("address", "1.0");
addColumn("hwaddr", "1.0");
addColumn("client_id", "1.0");
addColumn("valid_lifetime", "1.0");
addColumn("expire", "1.0");
addColumn("subnet_id", "1.0");
addColumn("fqdn_fwd", "1.0");
addColumn("fqdn_rev", "1.0");
addColumn("hostname", "1.0");
addColumn("state", "2.0", "0");
// Any file with less than hostname is invalid
setMinimumValidColumns("hostname");
}
IOAddress
......
......@@ -20,7 +20,7 @@
#include <dhcpsrv/lease.h>
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/lease_file_stats.h>
#include <util/csv_file.h>
#include <util/versioned_csv_file.h>
#include <stdint.h>
#include <string>
#include <time.h>
......@@ -39,7 +39,7 @@ namespace dhcp {
/// validation (see http://kea.isc.org/ticket/2405). However, when #2405
/// is implemented, the @c next function may need to be updated to use the
/// validation capablity of @c Lease4.
class CSVLeaseFile4 : public isc::util::CSVFile, public LeaseFileStats {
class CSVLeaseFile4 : public isc::util::VersionedCSVFile, public LeaseFileStats {
public:
/// @brief Constructor.
......
......@@ -23,14 +23,14 @@ namespace isc {
namespace dhcp {
CSVLeaseFile6::CSVLeaseFile6(const std::string& filename)
: CSVFile(filename) {
: VersionedCSVFile(filename) {
initColumns();
}
void
CSVLeaseFile6::open(const bool seek_to_end) {
// Call the base class to open the file
CSVFile::open(seek_to_end);
VersionedCSVFile::open(seek_to_end);
// and clear any statistics we may have
clearStatistics();
......@@ -61,7 +61,7 @@ CSVLeaseFile6::append(const Lease6& lease) {
}
row.writeAt(getColumnIndex("state"), lease.state_);
try {
CSVFile::append(row);
VersionedCSVFile::append(row);
} catch (const std::exception&) {
// Catch any errors so we can bump the error counter than rethrow it
++write_errs_;
......@@ -84,7 +84,7 @@ CSVLeaseFile6::next(Lease6Ptr& lease) {
try {
// Get the row of CSV values.
CSVRow row;
CSVFile::next(row);
VersionedCSVFile::next(row);
// The empty row signals EOF.
if (row == CSVFile::EMPTY_ROW()) {
lease.reset();
......@@ -122,20 +122,23 @@ CSVLeaseFile6::next(Lease6Ptr& lease) {
void
CSVLeaseFile6::initColumns() {
addColumn("address");
addColumn("duid");
addColumn("valid_lifetime");
addColumn("expire");
addColumn("subnet_id");
addColumn("pref_lifetime");
addColumn("lease_type");
addColumn("iaid");
addColumn("prefix_len");
addColumn("fqdn_fwd");
addColumn("fqdn_rev");
addColumn("hostname");
addColumn("hwaddr");
addColumn("state");
addColumn("address", "1.0");
addColumn("duid", "1.0");
addColumn("valid_lifetime", "1.0");
addColumn("expire", "1.0");
addColumn("subnet_id", "1.0");
addColumn("pref_lifetime", "1.0");
addColumn("lease_type", "1.0");
addColumn("iaid", "1.0");
addColumn("prefix_len", "1.0");
addColumn("fqdn_fwd", "1.0");
addColumn("fqdn_rev", "1.0");
addColumn("hostname", "1.0");
addColumn("hwaddr", "2.0");
addColumn("state", "3.0", "0");
// Any file with less than hostname is invalid
setMinimumValidColumns("hostname");
}