Commit 0260a628 authored by Francis Dupont's avatar Francis Dupont
Browse files

[master] Merging trac5374 (new classification) - conflicts resolved, regen needed

parents c8ddecea 44f874d6
......@@ -20,6 +20,7 @@ nobase_dist_doc_DATA += examples/kea4/advanced.json
nobase_dist_doc_DATA += examples/kea4/backends.json
nobase_dist_doc_DATA += examples/kea4/cassandra.json
nobase_dist_doc_DATA += examples/kea4/classify.json
nobase_dist_doc_DATA += examples/kea4/classify2.json
nobase_dist_doc_DATA += examples/kea4/comments.json
nobase_dist_doc_DATA += examples/kea4/dhcpv4-over-dhcpv6.json
nobase_dist_doc_DATA += examples/kea4/hooks.json
......@@ -36,6 +37,7 @@ nobase_dist_doc_DATA += examples/kea6/advanced.json
nobase_dist_doc_DATA += examples/kea6/backends.json
nobase_dist_doc_DATA += examples/kea6/cassandra.json
nobase_dist_doc_DATA += examples/kea6/classify.json
nobase_dist_doc_DATA += examples/kea6/classify2.json
nobase_dist_doc_DATA += examples/kea6/comments.json
nobase_dist_doc_DATA += examples/kea6/dhcpv4-over-dhcpv6.json
nobase_dist_doc_DATA += examples/kea6/duid.json
......
// This is an example configuration file for the DHCPv4 server in Kea.
// The purpose of this example is to showcase how clients can be classified
// with advanced features.
{ "Dhcp4": {
// Kea is told to listen on ethX interface only.
"interfaces-config": {
"interfaces": [ "ethX" ]
},
// Let's use the simplest backend: memfile and use some reasonable values
// for timers. They are of no concern for the classification demonstration.
"lease-database": { "type": "memfile" },
"renew-timer": 1000,
"rebind-timer": 2000,
"valid-lifetime": 4000,
// This list defines several classes that incoming packets can be assigned to.
// One packet can belong to zero or more classes.
"client-classes": [
// This class is required by the second subnet and is evaluated only
// if it is required. The test expression returns true.
// Note it is not possible to depend on VoIP class because it is not yet
// defined.
{
"name": "second_subnet",
"only-if-required": true,
"test": "member('ALL')",
"option-data": [{
"name": "domain-name-servers",
"data": "127.0.0.1"
}]
},
// Let's classify all incoming DISCOVER (message type 1) to a separate
// class.
{
"name": "discovers",
"test": "pkt4.msgtype == 1"
},
// Clients are supposed to set the transaction-id field to a random value.
// Clients that send it with 0 are most likely broken. Let's mark them
// as such.
{
"name": "broken",
"test": "pkt4.transid == 0"
},
// Let's pick VoIP phones. Those that send their class identifiers
// as Aastra, should belong to VoIP class. For a list of all options,
// see www.iana.org/assignments/bootp-dhcp-parameters/.
// In this particular class, we want to set specific values
// of certain DHCPv4 fields. If the incoming packet matches the
// test, those fields will be set in outgoing responses.
// The option 43 is defined to encapsulate suboption in the aastra space.
{
"name": "VoIP",
"test": "substring(option[60].hex,0,6) == 'Aastra'",
"next-server": "192.0.2.254",
"server-hostname": "hal9000",
"boot-file-name": "/dev/null",
"option-def": [ {
"name": "vendor-encapsulated-options",
"code": 43,
"type": "empty",
"encapsulate": "aastra" } ]
},
// Both a VoIP phone (by evaluation or host reservation) and has a host
// reservation.
{
"name": "VoIP_host",
"test": "member('VoIP') and member('KNOWN')",
"server-hostname": "hal9001"
}
],
// The following list defines subnets. For some subnets we defined
// a class that is allowed in that subnet. If not specified,
// everyone is allowed. When a class is specified, only packets belonging
// to that class are allowed for that subnet.
"subnet4": [
{
// This one is for VoIP devices only.
"pools": [ { "pool": "192.0.2.1 - 192.0.2.200" } ],
"subnet": "192.0.2.0/24",
"client-class": "VoIP",
"interface": "ethX"
},
// This one doesn't have any client-class specified, so everyone
// is allowed in. The normal subnet selection rules still apply,
// though. There is also a static class reservation for a client
// using MAC address 1a:1b:1c:1d:1e:1f. This client will always
// be assigned to this class.
{
"pools": [ { "pool": "192.0.3.1 - 192.0.3.200" } ],
"subnet": "192.0.3.0/24",
"reservations": [
{
"hw-address": "1a:1b:1c:1d:1e:1f",
"client-classes": [ "VoIP" ]
} ],
"interface": "ethX",
"require-client-classes": [ "second_subnet" ]
},
// The following list defines a subnet with pools. For some pools
// we defined a class that is allowed in that pool. If not specified
// everyone is allowed. When a class is specified, only packets belonging
// to that class are allowed for that pool.
{
"pools": [
{
// This one is for VoIP devices only.
"pool": "192.0.4.1 - 192.0.4.200",
"client-class": "VoIP"
},
// This one doesn't have any client-class specified, so everyone
// is allowed in.
{
"pool": "192.0.5.1 - 192.0.5.200"
} ],
"subnet": "192.0.4.0/23",
"interface": "ethY"
}
]
},
// The following configures logging. It assumes that messages with at
// least informational level (info, warn, error and fatal) should be
// logged to stdout.
"Logging": {
"loggers": [
{
"name": "kea-dhcp4",
"output_options": [
{
"output": "stdout"
}
],
"severity": "INFO"
}
]
}
}
// This is an example configuration file for the DHCPv4 server in Kea.
// This is an example configuration file for the DHCPv6 server in Kea.
// The purpose of this example is to showcase how clients can be classified.
{ "Dhcp6":
......
// This is an example configuration file for the DHCPv6 server in Kea.
// The purpose of this example is to showcase how clients can be classified.
{ "Dhcp6":
{
// Kea is told to listen on ethX interface only.
"interfaces-config": {
"interfaces": [ "ethX" ]
},
// Let's use the simplest backend: memfile and use some reasonable values
// for timers. They are of no concern for the classification demonstration.
"lease-database": {
"type": "memfile",
"lfc-interval": 3600
},
"renew-timer": 1000,
"rebind-timer": 2000,
"preferred-lifetime": 3000,
"valid-lifetime": 4000,
// This list defines several classes that incoming packets can be assigned to.
// One packet can belong to zero or more classes.
"client-classes": [
// This class is required by the second subnet and is evaluated only
// if it is required. The test expression returns true.
// Note it is not possible to depend on cable-modems class because it
// is not yet defined.
{
"name": "second_subnet",
"only-if-required": true,
"test": "member('ALL')",
"option-data": [{
"name": "dns-servers",
"data": "2001:db8::1"
}]
},
// Let's classify all incoming RENEW (message type 5) to a separate
// class.
{
"name": "renews",
"test": "pkt6.msgtype == 5"
},
// Let's pick cable modems. In this simple example we'll assume the device
// is a cable modem if it sends a vendor option with enterprise-id equal
// to 4491.
{
"name": "cable-modems",
"test": "vendor.enterprise == 4491"
},
// Both a cable modem (by evaluation or host reservation) and has a host
// reservation.
{
"name": "cable-modem-hosts",
"test": "member('cable-modems') and member('KNOWN')"
}
],
// The following list defines subnets. Each subnet consists of at
// least subnet and pool entries.
"subnet6": [
{
"pools": [ { "pool": "2001:db8:1::/80" } ],
"subnet": "2001:db8:1::/64",
"client-class": "cable-modems",
"interface": "ethX"
},
// The following subnet contains a class reservation for a client using
// DUID 01:02:03:04:05:0A:0B:0C:0D:0E. This client will always be assigned
// to this class.
{
"pools": [ { "pool": "2001:db8:2::/80" } ],
"subnet": "2001:db8:2::/64",
"reservations": [
{
"duid": "01:02:03:04:05:0A:0B:0C:0D:0E",
"client-classes": [ "cable-modems" ]
} ],
"interface": "ethX",
"require-client-classes": [ "second_subnet" ]
},
// The following subnet contains a pool with a class constraint: only
// clients which belong to the class are allowed to use this pool.
{
"pools": [
{
"pool": "2001:db8:3::/80",
"client-class": "cable-modems"
} ],
"subnet": "2001:db8:4::/64",
"interface": "ethY"
}
]
},
// The following configures logging. It assumes that messages with at
// least informational level (info, warn, error and fatal) should be
// logged to stdout.
"Logging": {
"loggers": [
{
"name": "kea-dhcp6",
"output_options": [
{
"output": "stdout"
}
],
"debuglevel": 0,
"severity": "INFO"
}
]
}
}
This diff is collapsed.
......@@ -1759,7 +1759,7 @@ It is merely echoed by the server
an old PXEClient vendor:
<screen>
"Dhcp4": {
"client-class": [
"client-classes": [
{
<userinput>"name": "pxeclient",
"test": "option[vendor-class-identifier].text == 'PXEClient'",
......@@ -1802,7 +1802,7 @@ It is merely echoed by the server
},</userinput>
...
],
"client-class": [
"client-classes": [
{
<userinput>"name": "APC",
"test": "(option[vendor-class-identifier].text == 'APC'",
......@@ -2203,13 +2203,15 @@ It is merely echoed by the server
discussion of the classification process see <xref linkend="classify"/>.
</para>
<para>In certain cases it is useful to configure the server to differentiate between
DHCP clients types and treat them accordingly. It is envisaged that client
classification will be used for modifying the behavior of almost any part of
the DHCP message processing. In the current release of Kea, there are four
mechanisms that take advantage of the client classification in DHCPv4: subnet
selection, address pool selection, DHCP options assignment, and, for cable modems,
there are specific options for use with the TFTP server address and boot file field.
<para>
In certain cases it is useful to differentiate between different types of
clients and treat them accordingly. It is envisaged that client
classification will be used for changing the behavior of almost any part of
the DHCP message processing. In the current release of the software however,
there are only some mechanisms that take advantage of client classification:
private options and option 43 deferred unpacking, subnet selection,
pool selection, assignment of different options, and, for cable modems, there
are specific options for use with the TFTP server address and the boot file field.
</para>
<para>
......@@ -2225,24 +2227,38 @@ It is merely echoed by the server
</para>
<para>
Client classification can also be used to restrict access to specific
pools within a subnet. This is useful when to segregate clients belonging
to the same subnet into different address ranges.
When subnets belong to a shared network the classification applies
to subnet selection but not to pools, e.g., a pool in a subnet
limited to a particular class can still be used by clients which do not
belong to the class if the pool they are expected to use is exhausted.
So the limit access based on class information is also available
at the pool level, see <xref linkend="classification-pools"/>,
within a subnet.
This is useful when to segregate clients belonging to the same subnet
into different address ranges.
</para>
<para>
The process of doing classification is conducted in three steps. The first step
The process of doing classification is conducted in several steps. The first step
is to assess an incoming packet and assign it to zero or more classes. The
second step is to choose a subnet, possibly based on the class information.
The third step is to assign options, again possibly based on the class
The third step is to assign classes from host reservations and
evaluate class expressions depending on the "KNOWN" class.
After the list of required classes is built and each class of the list
has its expression evaluated: when it returns true the packet is added
as a member of the class.
The last step is to assign options, again possibly based on the class
information.
More complete and detailed description is available in
<xref linkend="classify"/>.
</para>
<para>
There are two methods of doing classification. The first is automatic and relies
on examining the values in the vendor class options. Information from these
There are two main methods of doing classification. The first is automatic and relies
on examining the values in the vendor class options or existence of a
host reservation. Information from these
options is extracted and a class name is constructed from it and added to
the class list for the packet. The second allows you to specify an expression
the class list for the packet. The second allows for specifying an expression
that is evaluated for each packet. If the result is true the packet is
a member of the class.
</para>
......@@ -2292,9 +2308,14 @@ It is merely echoed by the server
<para>
If there are multiple classes defined and an incoming packet is matched
to multiple classes, the class whose name is alphabetically the first
is used.
to multiple classes, the class which is evaluated first is used.
</para>
<note><para>
In Kea versions prior to 1.4.0 the alphabetical order of class names was used.
Starting from Kea 1.4.0 the classes are ordered as specified in the configuration.
</para></note>
</section>
<section>
......@@ -2380,6 +2401,77 @@ It is merely echoed by the server
}</screen>
</para>
</section>
<section id="dhcp4-required-class">
<title>Required Classification</title>
<para>
In some cases it is useful to limit the scope of a class to
a shared-network, subnet or pool. There are two parameters
which are used to limit the scope of the class by instructing
the server to perform evaluation of test expressions when
required.
</para>
<para>
The first one is the per-class <command>only-if-required</command>
flag which is false by default. When it is set to
<command>true</command> the test expression of the class is not
evaluated at the reception of the incoming packet but later and
only if the class evaluation is required.
</para>
<para>
The second is the <command>require-client-classes</command> which
takes a list of class names and is valid in shared-network,
subnet and pool scope. Classes in these lists are marked as
required and evaluated after selection of this specific
shared-network/subnet/pool and before output option processing.
</para>
<para>
In this example, a class is assigned to the incoming packet
when the specified subnet is used.
<screen>
"Dhcp4": {
"client-classes": [
{<userinput>
"name": "Client_foo",
"test": "member('ALL')",
"only-if-required": true</userinput>
},
...
],
"subnet4": [
{
"subnet": "192.0.2.0/24",
"pools": [ { "pool": "192.0.2.10 - 192.0.2.20" } ],
<userinput>"require-client-classes": [ "Client_foo" ],</userinput>
...
},
...
],
...
}</screen>
</para>
<para>
Required evaluation can be used to express complex dependencies,
for example, subnet membership. It can also be used to reverse the
precedence: if you set an option-data in a subnet it takes
precedence over an option-data in a class. When you move the
option-data to a required class and require it in
the subnet, a class evaluated earlier may take precedence.
</para>
<para>
Required evaluation is also available at shared-network and
pool levels. The order in which required classes are considered is:
shared-network, subnet and pool, i.e. the opposite order
option-data are processed.
</para>
</section>
</section>
<section xml:id="dhcp4-ddns-config">
......@@ -3474,7 +3566,7 @@ It is merely echoed by the server
to configure the server to assign classes to a client based on the content
of the options that this client sends to the server. Host reservations
mechanisms also allow for statically assigning classes to the clients.
The definitions of these classes must exist in the Kea
The definitions of these classes should exist in the Kea
configuration. The following configuration snippet shows how to specify
that a client belongs to classes <command>reserved-class1</command>
and <command>reserved-class2</command>. Those classes are associated with
......@@ -3520,7 +3612,18 @@ It is merely echoed by the server
</screen>
<para>Static class assignments, as shown above, can be used in conjunction
with classification using expressions.</para>
with classification using expressions. The "KNOWN" builtin class is
added to the packet and any class depending on it directly or indirectly
and not only-if-required is evaluated.
</para>
<note>
<para>If you want to force the evaluation of a class expression after
the host reservation lookup, for instance because of a dependency on
"reserved-class1" from the previous example, you should add a
"member('KNOWN')" in the expression.</para>
</note>
</section>
<section id="reservations4-mysql-pgsql-cql">
......@@ -3889,7 +3992,7 @@ for each subnet. Here's an example:
<screen>
"shared-networks": [
{"
{
"name": "kakapo",
<userinput>"relay": {
"ip-address": "192.3.5.6"
......
......@@ -2207,11 +2207,9 @@ should include options from the isc option space:
In certain cases it is useful to differentiate between different types
of clients and treat them accordingly. It is envisaged that client
classification will be used for changing the behavior of almost any part of
the DHCP message processing, including the assignment of leases from different
pools, the assignment of different options (or different values of the same
options) etc. In the current release of the software however, there are
only two mechanisms that take advantage of client classification:
subnet selection and assignment of different options.
the DHCP message processing. In the current release of the software however,
there are only some mechanisms that take advantage of client classification:
subnet selection, pool selection, and assignment of different options.
</para>
<para>
......@@ -2225,26 +2223,38 @@ should include options from the isc option space:
users from playing with their cable modems. For details on how to set up
class restrictions on subnets, see <xref linkend="classification-subnets"/>.
</para>
<para>
Client classification can also be used to restrict access to specific
pools within a subnet. This is useful when to segregate clients belonging
to the same subnet into different address or prefix ranges.
When subnets belong to a shared network the classification applies
to subnet selection but not to pools, e.g., a pool in a subnet
limited to a particular class can still be used by clients which do not
belong to the class if the pool they are expected to use is exhausted.
So the limit access based on class information is also available
at the address/prefix pool level, see <xref
linkend="classification-pools"/> within a subnet.
This is useful when to segregate clients belonging to the same subnet
into different address ranges.
</para>
<para>
The process of doing classification is conducted in three steps. The first step
The process of doing classification is conducted in several steps. The first step
is to assess an incoming packet and assign it to zero or more classes. The
second step is to choose a subnet, possibly based on the class information.
The third step is to assign options again possibly based on the class
The third step is to assign classes from host reservations and
evaluate class expressions depending on the "KNOWN" class.
After the list of required classes is built and each class of the list
has its expression evaluated: when it returns true the packet is added
as a member of the class.
The last step is to assign options again possibly based on the class
information.
More complete and detailed description is available in
<xref linkend="classify"/>.
</para>
<para>
There are two methods of doing classification. The first is automatic and relies
on examining the values in the vendor class options. Information from these
There are two main methods of doing classification. The first is automatic and relies
on examining the values in the vendor class options or existence of a
host reservation. Information from these
options is extracted and a class name is constructed from it and added to
the class list for the packet. The second allows you to specify an expression
the class list for the packet. The second allows for specifying an expression
that is evaluated for each packet. If the result is true the packet is
a member of the class.
</para>
......@@ -2319,6 +2329,81 @@ should include options from the isc option space:
</screen>
</para>
</section>
<section id="dhcp6-required-class">
<title>Required classification</title>
<para>
In some cases it is useful to limit the scope of a class to
a shared-network, subnet or pool. There are two parameters
which are used to limit the scope of the class by instructing
the server to perform evaluation of test expressions when
required.
</para>
<para>
The first one is the per-class <command>only-if-required</command>
flag which is false by default. When it is set to
<command>true</command> the test expression of the class is not
evaluated at the reception of the incoming packet but later and
only if the class evaluation is required.
</para>
<para>
The second is the <command>require-client-classes</command> which
takes a list of class names and is valid in shared-network,
subnet and pool scope. Classes in these lists are marked as
required and evaluated after selection of this specific