diff --git a/doc/examples/kea4/hooks-radius.json b/doc/examples/kea4/hooks-radius.json
index 9d2afc30df..0f52d4e77f 100644
--- a/doc/examples/kea4/hooks-radius.json
+++ b/doc/examples/kea4/hooks-radius.json
@@ -148,8 +148,11 @@
"library": "/usr/local/lib/hooks/libdhcp_radius.so",
"parameters": {
- // Do not use RFC 4361
- "extract-duid": false,
+ // If do not use RFC 4361
+ // "extract-duid": false,
+
+ // If have conflicting subnets
+ // "reselect-subnet-pool": true,
// Strip the 0 type added by flex-id
"client-id-pop0": true,
diff --git a/doc/guide/hooks-radius.xml b/doc/guide/hooks-radius.xml
index d8f190649e..9550f3c368 100644
--- a/doc/guide/hooks-radius.xml
+++ b/doc/guide/hooks-radius.xml
@@ -301,7 +301,7 @@ Please make sure that your compilation has the following:
radius listed in tier 2 packages
FreeRadius client directories printed and pointing to the right
directories
- Boost ersion is at least 1.65.1. The versions available
+ Boost version is at least 1.65.1. The versions available
in CentOS 7 (1.48 and and 1.53) are too old.
@@ -322,7 +322,7 @@ Please make sure that your compilation has the following:
The RADIUS Hook is a library that has to be loaded by either DHCPv4 or
- DHCPv6 Kea servers. Compared to other avaiable hook libraries, this one
+ DHCPv6 Kea servers. Compared to other available hook libraries, this one
takes many parameters to actually run. For example, this configuration
could be used:
@@ -403,12 +403,12 @@ Please make sure that your compilation has the following:
identifier-type4 (default client-id)
specifies the identifier type to build the User-Name attribute. It should
- be the same than host identifier and when the flex-id hook librairy is
+ be the same than host identifier and when the flex-id hook library is
used the replace-client-id must be set to true and client-id will be used
with client-id-pop0.
identifier-type6 (default duid)
- pecifies the identifier type to build the User-Name attribute. It should
+ specifies the identifier type to build the User-Name attribute. It should
be the same than host identifier and when the flex-id hook librairy is
used the replace-client-id must be set to true and duid will be used with
client-id-pop0.
@@ -416,6 +416,15 @@ Please make sure that your compilation has the following:
realm (default "") is the default
realm.
+ reselect-subnet-address (default
+ false) uses the Kea reserved address / RADIUS Framed-IP-Address or
+ Framed-IPv6-Address to reselect subnets where the address is not in
+ the subnet range.
+
+ reselect-subnet-pool (default
+ false) uses the Kea client-class / RADIUS Frame-Pool to reselect
+ subnets where no available pool can be found.
+
retries (default 3) is the number of
retries before trying the next server. Note it is not supported for
asynchronous communication.
@@ -430,6 +439,13 @@ Please make sure that your compilation has the following:
+ When reselect-subnet-pool or
+ reselect-subnet-address is set to true at the
+ reception of RADIUS Access-Accept the selected subnet is checked
+ against the client-class name or the reserved address and if it does
+ not matched another subnet is selected among matching subnets.
+
+
Two services are supported:
diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc
index cd988f1746..6b8f365e97 100644
--- a/src/bin/dhcp4/dhcp4_srv.cc
+++ b/src/bin/dhcp4/dhcp4_srv.cc
@@ -503,48 +503,7 @@ Dhcpv4Srv::selectSubnet(const Pkt4Ptr& query, bool& drop,
Subnet4Ptr subnet;
- SubnetSelector selector;
- selector.ciaddr_ = query->getCiaddr();
- selector.giaddr_ = query->getGiaddr();
- selector.local_address_ = query->getLocalAddr();
- selector.remote_address_ = query->getRemoteAddr();
- selector.client_classes_ = query->classes_;
- selector.iface_name_ = query->getIface();
-
- // If the link-selection sub-option is present, extract its value.
- // "The link-selection sub-option is used by any DHCP relay agent
- // that desires to specify a subnet/link for a DHCP client request
- // that it is relaying but needs the subnet/link specification to
- // be different from the IP address the DHCP server should use
- // when communicating with the relay agent." (RFC 3527)
- //
- // Try first Relay Agent Link Selection sub-option
- OptionPtr rai = query->getOption(DHO_DHCP_AGENT_OPTIONS);
- if (rai) {
- OptionCustomPtr rai_custom =
- boost::dynamic_pointer_cast(rai);
- if (rai_custom) {
- OptionPtr link_select =
- rai_custom->getOption(RAI_OPTION_LINK_SELECTION);
- if (link_select) {
- OptionBuffer link_select_buf = link_select->getData();
- if (link_select_buf.size() == sizeof(uint32_t)) {
- selector.option_select_ =
- IOAddress::fromBytes(AF_INET, &link_select_buf[0]);
- }
- }
- }
- } else {
- // Or Subnet Selection option
- OptionPtr sbnsel = query->getOption(DHO_SUBNET_SELECTION);
- if (sbnsel) {
- OptionCustomPtr oc =
- boost::dynamic_pointer_cast(sbnsel);
- if (oc) {
- selector.option_select_ = oc->readAddress();
- }
- }
- }
+ const SubnetSelector& selector = CfgSubnets4::initSelector(query);
CfgMgr& cfgmgr = CfgMgr::instance();
subnet = cfgmgr.getCurrentCfg()->getCfgSubnets4()->selectSubnet(selector);
diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc
index 3af19693d8..30066b1b0e 100644
--- a/src/bin/dhcp6/dhcp6_srv.cc
+++ b/src/bin/dhcp6/dhcp6_srv.cc
@@ -1306,31 +1306,11 @@ Dhcpv6Srv::sanityCheck(const Pkt6Ptr& pkt, RequirementLevel clientid,
Subnet6Ptr
Dhcpv6Srv::selectSubnet(const Pkt6Ptr& question, bool& drop) {
- // Initialize subnet selector with the values used to select the subnet.
- SubnetSelector selector;
- selector.iface_name_ = question->getIface();
- selector.remote_address_ = question->getRemoteAddr();
- selector.first_relay_linkaddr_ = IOAddress("::");
- selector.client_classes_ = question->classes_;
-
- // Initialize fields specific to relayed messages.
- if (!question->relay_info_.empty()) {
- BOOST_REVERSE_FOREACH(Pkt6::RelayInfo relay, question->relay_info_) {
- if (!relay.linkaddr_.isV6Zero() &&
- !relay.linkaddr_.isV6LinkLocal()) {
- selector.first_relay_linkaddr_ = relay.linkaddr_;
- break;
- }
- }
- selector.interface_id_ =
- question->getAnyRelayOption(D6O_INTERFACE_ID,
- Pkt6::RELAY_GET_FIRST);
- }
+ const SubnetSelector& selector = CfgSubnets6::initSelector(question);
Subnet6Ptr subnet = CfgMgr::instance().getCurrentCfg()->
getCfgSubnets6()->selectSubnet(selector);
-
// Let's execute all callouts registered for subnet6_receive
if (HooksManager::calloutsPresent(Hooks.hook_index_subnet6_select_)) {
CalloutHandlePtr callout_handle = getCalloutHandle(question);
diff --git a/src/lib/dhcpsrv/cfg_subnets4.cc b/src/lib/dhcpsrv/cfg_subnets4.cc
index 21c188ae30..4d12e83e08 100644
--- a/src/lib/dhcpsrv/cfg_subnets4.cc
+++ b/src/lib/dhcpsrv/cfg_subnets4.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -6,6 +6,7 @@
#include
#include
+#include
#include
#include
#include
@@ -75,6 +76,54 @@ CfgSubnets4::hasSubnetWithServerId(const asiolink::IOAddress& server_id) const {
return (subnet_it != index.cend());
}
+SubnetSelector
+CfgSubnets4::initSelector(const Pkt4Ptr& query) {
+ SubnetSelector selector;
+ selector.ciaddr_ = query->getCiaddr();
+ selector.giaddr_ = query->getGiaddr();
+ selector.local_address_ = query->getLocalAddr();
+ selector.remote_address_ = query->getRemoteAddr();
+ selector.client_classes_ = query->classes_;
+ selector.iface_name_ = query->getIface();
+
+ // If the link-selection sub-option is present, extract its value.
+ // "The link-selection sub-option is used by any DHCP relay agent
+ // that desires to specify a subnet/link for a DHCP client request
+ // that it is relaying but needs the subnet/link specification to
+ // be different from the IP address the DHCP server should use
+ // when communicating with the relay agent." (RFC 3527)
+ //
+ // Try first Relay Agent Link Selection sub-option
+ OptionPtr rai = query->getOption(DHO_DHCP_AGENT_OPTIONS);
+ if (rai) {
+ OptionCustomPtr rai_custom =
+ boost::dynamic_pointer_cast(rai);
+ if (rai_custom) {
+ OptionPtr link_select =
+ rai_custom->getOption(RAI_OPTION_LINK_SELECTION);
+ if (link_select) {
+ OptionBuffer link_select_buf = link_select->getData();
+ if (link_select_buf.size() == sizeof(uint32_t)) {
+ selector.option_select_ =
+ IOAddress::fromBytes(AF_INET, &link_select_buf[0]);
+ }
+ }
+ }
+ } else {
+ // Or Subnet Selection option
+ OptionPtr sbnsel = query->getOption(DHO_SUBNET_SELECTION);
+ if (sbnsel) {
+ OptionCustomPtr oc =
+ boost::dynamic_pointer_cast(sbnsel);
+ if (oc) {
+ selector.option_select_ = oc->readAddress();
+ }
+ }
+ }
+
+ return (selector);
+}
+
Subnet4Ptr
CfgSubnets4::selectSubnet4o6(const SubnetSelector& selector) const {
diff --git a/src/lib/dhcpsrv/cfg_subnets4.h b/src/lib/dhcpsrv/cfg_subnets4.h
index 86758172a5..521ffa0a32 100644
--- a/src/lib/dhcpsrv/cfg_subnets4.h
+++ b/src/lib/dhcpsrv/cfg_subnets4.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -9,6 +9,7 @@
#include
#include
+#include
#include
#include
#include
@@ -99,6 +100,14 @@ public:
/// @return true if there is a subnet with a specified server identifier.
bool hasSubnetWithServerId(const asiolink::IOAddress& server_id) const;
+ /// @brief Build selector from a client's message.
+ ///
+ /// @note: code moved from server.
+ ///
+ /// @param query client's message.
+ /// @return filled selector.
+ static SubnetSelector initSelector(const Pkt4Ptr& query);
+
/// @brief Returns a pointer to the selected subnet.
///
/// This method tries to retrieve the subnet for the client using various
diff --git a/src/lib/dhcpsrv/cfg_subnets6.cc b/src/lib/dhcpsrv/cfg_subnets6.cc
index 9db6aa4fee..0d058b3954 100644
--- a/src/lib/dhcpsrv/cfg_subnets6.cc
+++ b/src/lib/dhcpsrv/cfg_subnets6.cc
@@ -1,16 +1,19 @@
-// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include
+#include
+#include
#include
#include
#include
#include
#include
#include
+#include
#include
#include
@@ -66,6 +69,32 @@ CfgSubnets6::getByPrefix(const std::string& subnet_text) const {
return ((subnet_it != index.cend()) ? (*subnet_it) : ConstSubnet6Ptr());
}
+SubnetSelector
+CfgSubnets6::initSelector(const Pkt6Ptr& query) {
+ // Initialize subnet selector with the values used to select the subnet.
+ SubnetSelector selector;
+ selector.iface_name_ = query->getIface();
+ selector.remote_address_ = query->getRemoteAddr();
+ selector.first_relay_linkaddr_ = IOAddress("::");
+ selector.client_classes_ = query->classes_;
+
+ // Initialize fields specific to relayed messages.
+ if (!query->relay_info_.empty()) {
+ BOOST_REVERSE_FOREACH(Pkt6::RelayInfo relay, query->relay_info_) {
+ if (!relay.linkaddr_.isV6Zero() &&
+ !relay.linkaddr_.isV6LinkLocal()) {
+ selector.first_relay_linkaddr_ = relay.linkaddr_;
+ break;
+ }
+ }
+ selector.interface_id_ =
+ query->getAnyRelayOption(D6O_INTERFACE_ID,
+ Pkt6::RELAY_GET_FIRST);
+ }
+
+ return (selector);
+}
+
Subnet6Ptr
CfgSubnets6::selectSubnet(const SubnetSelector& selector) const {
Subnet6Ptr subnet;
diff --git a/src/lib/dhcpsrv/cfg_subnets6.h b/src/lib/dhcpsrv/cfg_subnets6.h
index 5e03152275..84003101a7 100644
--- a/src/lib/dhcpsrv/cfg_subnets6.h
+++ b/src/lib/dhcpsrv/cfg_subnets6.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -9,6 +9,7 @@
#include
#include
+#include
#include
#include
#include
@@ -92,6 +93,14 @@ public:
/// subnet doesn't exist.
ConstSubnet6Ptr getByPrefix(const std::string& subnet_prefix) const;
+ /// @brief Build selector from a client's message.
+ ///
+ /// @note: code moved from server.
+ ///
+ /// @param query client's message.
+ /// @return filled selector.
+ static SubnetSelector initSelector(const Pkt6Ptr& query);
+
/// @brief Selects a subnet using parameters specified in the selector.
///
/// This method tries to retrieve the subnet for the client using various