Commit 4cbf341f authored by Francis Dupont's avatar Francis Dupont
Browse files

[master] Finished merge of (hex in integer options)

parents fc28ed03 9957f9c1
1242. [func] fdupont
Integer fields in options can now be specified in either
decimal or hexadecimal format.
(Trac $4540, git xxx)
1241. [func] fdupont 1241. [func] fdupont
Support for tuple-based options added. DHCPv6 option Support for tuple-based options added. DHCPv6 option
bootfile-param (code 60) can now be set in a more convenient bootfile-param (code 60) can now be set in a more convenient
......
# This is an example configuration file for the DHCPv4 server in Kea. // This is an example configuration file for the DHCPv4 server in Kea.
# It demonstrates simple configuration of the options for a subnet. // It demonstrates simple configuration of the options for a subnet.
{ "Dhcp4": { "Dhcp4":
{ {
# Kea is told to listen on ethX interface only. // Kea is told to listen on ethX interface only.
"interfaces-config": { "interfaces-config": {
"interfaces": [ "ethX" ] "interfaces": [ "ethX" ]
}, },
# We need to specify the the database used to store leases. As of // We need to specify the the database used to store leases. As of
# September 2016, four database backends are supported: MySQL, // September 2016, four database backends are supported: MySQL,
# PostgreSQL, Cassandra, and the in-memory database, Memfile. // PostgreSQL, Cassandra, and the in-memory database, Memfile.
# We'll use memfile because it doesn't require any prior set up. // We'll use memfile because it doesn't require any prior set up.
"lease-database": { "lease-database": {
"type": "memfile" "type": "memfile"
}, },
# Addresses will be assigned with a lifetime of 4000 seconds. // Addresses will be assigned with a lifetime of 4000 seconds.
"valid-lifetime": 4000, "valid-lifetime": 4000,
# Renew and rebind timers are commented out. This implies that options // 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 // 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 // the client to pick the timer values according to RFC2131. Uncomment the
# timers to send these options to the client. // timers to send these options to the client.
# "renew-timer": 1000, // "renew-timer": 1000,
# "rebind-timer": 2000, // "rebind-timer": 2000,
// Defining a subnet. There are 3 DHCP options returned to the // Defining a subnet. There are some DHCP options returned to the
// clients connected to this subnet. The first and third options are // clients connected to this subnet. The first and third options are
// clients connected to this subnet. The first two options are
// identified by the name. The third option is identified by the // identified by the name. The third option is identified by the
// option code. // option code.
"subnet4": [ "subnet4": [
...@@ -37,39 +38,85 @@ ...@@ -37,39 +38,85 @@
"subnet": "192.0.2.0/24", "subnet": "192.0.2.0/24",
"interface": "ethX", "interface": "ethX",
"option-data": [ "option-data": [
// When specifying options, you typically need to specify
// one of (name or code) and data. The full option specification
// covers name, code, space, csv-format and data.
// space defaults to "dhcp4" which is usually correct, unless you
// use encapsulate options. csv-format defaults to "true", so
// this is also correct, unless you want to specify the whole
// option value as long hex string. For example, to specify
// domain-name-servers you could do this:
// {
// "name": "domain-name-servers",
// "code": 6,
// "csv-format": "true",
// "space": "dhcp4",
// "data": "192.0.2.1, 192.0.2.2"
// }
// but it's a lot of writing, so it's easier to do this instead:
{ {
"name": "domain-name-servers", "name": "domain-name-servers",
"data": "192.0.2.1, 192.0.2.2" "data": "192.0.2.1, 192.0.2.2"
}, },
// Note the Kea provides some of the options on its own. In
// particular:
// - IP address lease time (option 51) is governed by valid-lifetime
// parameter, so you don't need to specify it as option.
// - Subnet mask (option 1) is calculated automatically from the
// subnet parameter specified for each "subnet4" entry.
// - renewal-timer (option 58) is calculated from renew-timer
// parameter
// - rebind timer (option 59) is calculated from rebind-timer
// parameter
// For each IPv4 subnet you most likely need to specify at least
// one router.
{ {
"name": "routers", "name": "routers",
"data": "192.0.2.1" "data": "192.0.2.1"
}, },
// Typically people prefer to refer to options by their names, so they
// don't need to remember the code names. However, some people like
// to use numerical values. For example, option "domain-name" uses
// option code 15, so you can reference to it either by
// "name": "domain-name" or "code": 15.
{
"code": 15,
"data": "example.org"
},
// String options that have a comma in their values need to have
// it escaped (i.e. each comma is predeced by two backslashes).
// That's because commas are reserved for separating fields in
// compound options. At the same time, we need to be conformant
// with JSON spec, that does not allow "\,". Therefore the
// slightly uncommon double backslashes notation is needed.
// Legal JSON escapes are \ followed by "\/bfnrt character
// or \u followed by 4 hexa-decimal numbers (currently Kea
// supports only \u0000 to \u00ff code points).
// CSV processing translates '\\' into '\' and '\,' into ','
// only so for instance '\x' is translated into '\x'. But
// as it works on a JSON string value each of these '\'
// characters must be doubled on JSON input.
{ {
// String options that have a comma in their values need to have "name": "boot-file-name",
// it escaped (i.e. each comma is predeced by two backslashes). "data": "EST5EDT4\\,M3.2.0/02:00\\,M11.1.0/02:00"
// That's because commas are reserved for separating fields in
// compound options. At the same time, we need to be conformant
// with JSON spec, that does not allow "\,". Therefore the
// slightly uncommon double backslashes notation is needed.
"name": "boot-file-name",
"data": "EST5EDT4\\,M3.2.0/02:00\\,M11.1.0/02:00"
// Legal JSON escapes are \ followed by "\/bfnrt character },
// or \u followed by 4 hexa-decimal numbers (currently Kea // Options that take integer values can either be specified in
// supports only \u0000 to \u00ff code points). // dec or hex format. Hex format could be either plain (e.g. abcd)
// CSV processing translates '\\' into '\' and '\,' into ',' // or prefixed with 0x (e.g. 0xabcd).
// only so for instance '\x' is translated into '\x'. But {
// as it works on a JSON string value each of these '\' "name": "default-ip-ttl",
// characters must be doubled on JSON input. "data": "0xf0"
} }
] ]
} }
] ]
}, },
# The following configures logging. It assumes that messages with at least // The following configures logging. It assumes that messages with at least
# informational level (info, warn, error and fatal) should be logged to stdout. // informational level (info, warn, error and fatal) should be logged to stdout.
"Logging": { "Logging": {
"loggers": [ "loggers": [
{ {
......
# This is an example configuration file for DHCPv6 server in Kea. // This is an example configuration file for DHCPv6 server in Kea.
# It demonstrates simple configuration of the options for a subnet. // It demonstrates simple configuration of the options for a subnet.
{ "Dhcp6": { "Dhcp6":
{ {
# Kea is told to listen on ethX interface only. // Kea is told to listen on ethX interface only.
"interfaces-config": { "interfaces-config": {
"interfaces": [ "ethX" ] "interfaces": [ "ethX" ]
}, },
# We need to specify the the database used to store leases. As of // We need to specify the the database used to store leases. As of
# September 2016, four database backends are supported: MySQL, // September 2016, four database backends are supported: MySQL,
# PostgreSQL, Cassandra, and the in-memory database, Memfile. // PostgreSQL, Cassandra, and the in-memory database, Memfile.
# We'll use memfile because it doesn't require any prior set up. // We'll use memfile because it doesn't require any prior set up.
"lease-database": { "lease-database": {
"type": "memfile" "type": "memfile"
}, },
# Addresses will be assigned with preferred and valid lifetimes // Addresses will be assigned with preferred and valid lifetimes
# being 3000 and 4000, respectively. Client is told to start // being 3000 and 4000, respectively. Client is told to start
# renewing after 1000 seconds. If the server does not respond // renewing after 1000 seconds. If the server does not respond
# after 2000 seconds since the lease was granted, client is supposed // after 2000 seconds since the lease was granted, client is supposed
# to start REBIND procedure (emergency renewal that allows switching // to start REBIND procedure (emergency renewal that allows switching
# to a different server). // to a different server).
"preferred-lifetime": 3000, "preferred-lifetime": 3000,
"valid-lifetime": 4000, "valid-lifetime": 4000,
"renew-timer": 1000, "renew-timer": 1000,
"rebind-timer": 2000, "rebind-timer": 2000,
# Defining a subnet. There are 3 DHCP options returned to the // Defining a subnet. There are some DHCP options returned to the
# clients connected to this subnet. The first option is identified // clients connected to this subnet. The first option is identified
# by the name. The second option is identified by the code. // by the name. The second option is identified by the code.
# There are two address pools defined within this subnet. Pool // There are two address pools defined within this subnet. Pool
# specific value for option 12 is defined for the pool: // specific value for option 12 is defined for the pool:
# 2001:db8:1::1 - 2001:db8:1::100. Clients obtaining an address // 2001:db8:1::1 - 2001:db8:1::100. Clients obtaining an address
# from this pool will be assigned option 12 with a value of // from this pool will be assigned option 12 with a value of
# 3001:cafe::21. Clients belonging to this subnet but obtaining // 3001:cafe::21. Clients belonging to this subnet but obtaining
# addresses from the other pool, or the clients obtaining // addresses from the other pool, or the clients obtaining
# stateless configuration will be assigned subnet specific value // stateless configuration will be assigned subnet specific value
# of option 12, i.e. 2001:db8:1:0:ff00::1. // of option 12, i.e. 2001:db8:1:0:ff00::1.
# For DHCPv6 subnets can have prefix delegation pools too so // For DHCPv6 subnets can have prefix delegation pools too so
# a pd-pools with an option-data is defined too. // a pd-pools with an option-data is defined too.
"subnet6": [ "subnet6": [
{ {
"option-data": [ // This is how option values are defined for this particular subnet.
{ "option-data": [
"name": "dns-servers", // When specifying options, you typically need to specify
"data": "2001:db8:2::45, 2001:db8:2::100" // one of (name or code) and data. The full option specification
}, // covers name, code, space, csv-format and data.
{ // space defaults to "dhcp6" which is usually correct, unless you
"code": 12, // use encapsulate options. csv-format defaults to "true", so
"data": "2001:db8:1:0:ff00::1" // this is also correct, unless you want to specify the whole
}, // option value as long hex string. For example, to specify
{ // domain-name-servers you could do this:
// {
// "name": "dns-servers",
// "code": 23,
// "csv-format": "true",
// "space": "dhcp6",
// "data": "2001:db8:2::45, 2001:db8:2::100"
// }
// but it's a lot of writing, so it's easier to do this instead:
{
"name": "dns-servers",
"data": "2001:db8:2::45, 2001:db8:2::100"
},
// Typically people prefer to refer to options by their names, so they
// don't need to remember the code names. However, some people like
// to use numerical values. For example, DHCPv6 can optionally use
// server unicast communication, if extra option is present. Option
// "unicast" uses option code 12, so you can reference to it either
// by "name": "unicast" or "code": 12.
{
"code": 12,
"data": "2001:db8:1:0:ff00::1"
},
// String options that have a comma in their values need to have // String options that have a comma in their values need to have
// it escaped (i.e. each comma is predeced by two backslashes). // it escaped (i.e. each comma is predeced by two backslashes).
// That's because commas are reserved for separating fields in // That's because commas are reserved for separating fields in
// compound options. At the same time, we need to be conformant // compound options. At the same time, we need to be conformant
// with JSON spec, that does not allow "\,". Therefore the // with JSON spec, that does not allow "\,". Therefore the
// slightly uncommon double backslashes notation is needed. // slightly uncommon double backslashes notation is needed.
"name": "new-posix-timezone",
"data": "EST5EDT4\\,M3.2.0/02:00\\,M11.1.0/02:00"
// Legal JSON escapes are \ followed by "\/bfnrt character // Legal JSON escapes are \ followed by "\/bfnrt character
// or \u followed by 4 hexa-decimal numbers (currently Kea // or \u followed by 4 hexa-decimal numbers (currently Kea
...@@ -69,14 +91,26 @@ ...@@ -69,14 +91,26 @@
// only so for instance '\x' is translated into '\x'. But // only so for instance '\x' is translated into '\x'. But
// as it works on a JSON string value each of these '\' // as it works on a JSON string value each of these '\'
// characters must be doubled on JSON input. // characters must be doubled on JSON input.
}, {
{ "name": "new-posix-timezone",
"data": "EST5EDT4\\,M3.2.0/02:00\\,M11.1.0/02:00"
},
// Options that take integer values can either be specified in
// dec or hex format. Hex format could be either plain (e.g. abcd)
// or prefixed with 0x (e.g. 0xabcd).
{
"name": "preference",
"data": "0xf0"
},
// A few options are encoded in (length, string) tuples // A few options are encoded in (length, string) tuples
// which can be defined using only strings as the CSV // which can be defined using only strings as the CSV
// processing computes lengths. // processing computes lengths.
"name": "bootfile-param", {
"data": "root=/dev/sda2, quiet, splash" "name": "bootfile-param",
} "data": "root=/dev/sda2, quiet, splash"
}
], ],
"pools": [ "pools": [
{ {
...@@ -111,8 +145,8 @@ ...@@ -111,8 +145,8 @@
] ]
}, },
# The following configures logging. It assumes that messages with at least // The following configures logging. It assumes that messages with at least
# informational level (info, warn, error and fatal) should be logged to stdout. // informational level (info, warn, error and fatal) should be logged to stdout.
"Logging": { "Logging": {
"loggers": [ "loggers": [
{ {
......
...@@ -957,22 +957,38 @@ temporarily override a list of interface names and listen on all interfaces. ...@@ -957,22 +957,38 @@ temporarily override a list of interface names and listen on all interfaces.
... ...
] ]
} }
</screen> </screen>
Note that only one of name or code is required, you don't need to
specify both. Space has a default value of "dhcp4", so you can skip this
as well if you define a regular (not encapsulated) DHCPv4 option.
Finally, csv-format defaults to true, so it too can be skipped, unless
you want to specify the option value as hexstring. Therefore the
above example can be simplified to:
<screen>
"Dhcp4": {
"option-data": [
{
<userinput>"name": "domain-name-servers",
"data": "192.0.2.1, 192.0.2.2"</userinput>
},
...
]
} </screen>
</para> </para>
<para> <para>
The <command>name</command> parameter specifies the The <command>name</command> parameter specifies the option name. For a
option name. For a list of currently supported names, see list of currently supported names, see <xref
<xref linkend="dhcp4-std-options-list"/> below. linkend="dhcp4-std-options-list"/> below. The <command>code</command>
The <command>code</command> parameter specifies the option code, which must match one of the parameter specifies the option code, which must match one of the values
values from that list. The next line specifies the option space, which must always from that list. The next line specifies the option space, which must
be set to "dhcp4" as these are standard DHCPv4 options. For always be set to "dhcp4" as these are standard DHCPv4 options. For other
other option spaces, including custom option spaces, see <xref option spaces, including custom option spaces, see <xref
linkend="dhcp4-option-spaces"/>. The next line specifies the format in linkend="dhcp4-option-spaces"/>. The next line specifies the format in
which the data will be entered: use of CSV (comma which the data will be entered: use of CSV (comma separated values) is
separated values) is recommended. The sixth line gives the actual value to recommended. The sixth line gives the actual value to be sent to
be sent to clients. Data is specified as normal text, with clients. Data is specified as normal text, with values separated by commas
values separated by commas if more than one value is if more than one value is allowed.
allowed.
</para> </para>
<para> <para>
...@@ -1043,8 +1059,7 @@ temporarily override a list of interface names and listen on all interfaces. ...@@ -1043,8 +1059,7 @@ temporarily override a list of interface names and listen on all interfaces.
<para> <para>
The currently supported standard DHCPv4 options are The currently supported standard DHCPv4 options are
listed in <xref linkend="dhcp4-std-options-list"/> listed in <xref linkend="dhcp4-std-options-list"/>.
and <xref linkend="dhcp4-std-options-list-part2"/>.
The "Name" and "Code" The "Name" and "Code"
are the values that should be used as a name in the option-data are the values that should be used as a name in the option-data
structures. "Type" designates the format of the data: the meanings of structures. "Type" designates the format of the data: the meanings of
...@@ -1165,32 +1180,6 @@ This rather belong to the DDNS configuration ...@@ -1165,32 +1180,6 @@ This rather belong to the DDNS configuration
<row><entry>default-tcp-ttl</entry><entry>37</entry><entry>uint8</entry><entry>false</entry><entry>false</entry></row> <row><entry>default-tcp-ttl</entry><entry>37</entry><entry>uint8</entry><entry>false</entry><entry>false</entry></row>
<row><entry>tcp-keepalive-interval</entry><entry>38</entry><entry>uint32</entry><entry>false</entry><entry>false</entry></row> <row><entry>tcp-keepalive-interval</entry><entry>38</entry><entry>uint32</entry><entry>false</entry><entry>false</entry></row>
<row><entry>tcp-keepalive-garbage</entry><entry>39</entry><entry>boolean</entry><entry>false</entry><entry>false</entry></row> <row><entry>tcp-keepalive-garbage</entry><entry>39</entry><entry>boolean</entry><entry>false</entry><entry>false</entry></row>
</tbody>
</tgroup>
</table>
</para>
<para>
<table frame="all" id="dhcp4-std-options-list-part2">
<title>List of standard DHCPv4 options (continued)</title>
<tgroup cols='5'>
<colspec colname='name'/>
<colspec colname='code' align='center'/>
<colspec colname='type' align='center'/>
<colspec colname='array' align='center'/>
<colspec colname='always-returned' align='center'/>
<thead>
<row>
<entry>Name</entry>
<entry>Code</entry>
<entry>Type</entry>
<entry>Array?</entry>
<entry>Returned if not requested?</entry>
</row>
</thead>
<tbody>
<row><entry>nis-domain</entry><entry>40</entry><entry>string</entry><entry>false</entry><entry>false</entry></row> <row><entry>nis-domain</entry><entry>40</entry><entry>string</entry><entry>false</entry><entry>false</entry></row>
<row><entry>nis-servers</entry><entry>41</entry><entry>ipv4-address</entry><entry>true</entry><entry>false</entry></row> <row><entry>nis-servers</entry><entry>41</entry><entry>ipv4-address</entry><entry>true</entry><entry>false</entry></row>
<row><entry>ntp-servers</entry><entry>42</entry><entry>ipv4-address</entry><entry>true</entry><entry>false</entry></row> <row><entry>ntp-servers</entry><entry>42</entry><entry>ipv4-address</entry><entry>true</entry><entry>false</entry></row>
...@@ -1414,6 +1403,12 @@ It is merely echoed by the server ...@@ -1414,6 +1403,12 @@ It is merely echoed by the server
<command>"1"</command>. Future versions of Kea will accept all those values <command>"1"</command>. Future versions of Kea will accept all those values
for all boolean parameters.</para> for all boolean parameters.</para>
</note> </note>
<note>
<para>Numbers can be specified in decimal or hexadecimal format.
The hexadecimal format can be either plain (e.g. abcd) or
prefixed with 0x (e.g. 0xabcd).
</para>
</note>
</section> </section>
<section id="dhcp4-vendor-opts"> <section id="dhcp4-vendor-opts">
......
...@@ -982,9 +982,26 @@ temporarily override a list of interface names and listen on all interfaces. ...@@ -982,9 +982,26 @@ temporarily override a list of interface names and listen on all interfaces.
</para> </para>
<para> <para>
Most of the parameters in the "option-data" structure are optional and Most of the parameters in the "option-data" structure are
can be omitted in some circumstances as discussed in the optional and can be omitted in some circumstances as discussed
<xref linkend="dhcp6-option-data-defaults"/>. in the <xref linkend="dhcp6-option-data-defaults"/>. Only one
of name or code is required, so you don't need to specify
both. Space has a default value of "dhcp6", so you can skip
this as well if you define a regular (not encapsulated) DHCPv6
option. Finally, csv-format defaults to true, so it too can
be skipped, unless you want to specify the option value as
hexstring. Therefore the above example can be simplified to:
<screen>
"Dhcp4": {
"option-data": [
{
<userinput>"name": "dns-servers",
"data": "2001:db8::cafe, 2001:db8::babe"</userinput>
},
...
]
} </screen>
</para> </para>
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
#include <boost/dynamic_bitset.hpp> #include <boost/dynamic_bitset.hpp>
#include <sstream>
using namespace std; using namespace std;
using namespace isc::util; using namespace isc::util;
...@@ -496,8 +497,15 @@ OptionDefinition::lexicalCastWithRangeCheck(const std::string& value_str) ...@@ -496,8 +497,15 @@ OptionDefinition::lexicalCastWithRangeCheck(const std::string& value_str)
result = boost::lexical_cast<int64_t>(value_str); result = boost::lexical_cast<int64_t>(value_str);
} catch (const boost::bad_lexical_cast&) { } catch (const boost::bad_lexical_cast&) {
isc_throw(BadDataTypeCast, "unable to convert the value '" // boost::lexical_cast does not handle hexadecimal
<< value_str << "' to integer data type");