mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-03 23:45:27 +00:00
[master] Merged trac5617 (RADIUS reselect subnet)
This commit is contained in:
@@ -148,8 +148,11 @@
|
|||||||
"library": "/usr/local/lib/hooks/libdhcp_radius.so",
|
"library": "/usr/local/lib/hooks/libdhcp_radius.so",
|
||||||
|
|
||||||
"parameters": {
|
"parameters": {
|
||||||
// Do not use RFC 4361
|
// If do not use RFC 4361
|
||||||
"extract-duid": false,
|
// "extract-duid": false,
|
||||||
|
|
||||||
|
// If have conflicting subnets
|
||||||
|
// "reselect-subnet-pool": true,
|
||||||
|
|
||||||
// Strip the 0 type added by flex-id
|
// Strip the 0 type added by flex-id
|
||||||
"client-id-pop0": true,
|
"client-id-pop0": true,
|
||||||
|
@@ -301,7 +301,7 @@ Please make sure that your compilation has the following:
|
|||||||
<listitem>radius listed in tier 2 packages</listitem>
|
<listitem>radius listed in tier 2 packages</listitem>
|
||||||
<listitem>FreeRadius client directories printed and pointing to the right
|
<listitem>FreeRadius client directories printed and pointing to the right
|
||||||
directories</listitem>
|
directories</listitem>
|
||||||
<listitem>Boost ersion is at least 1.65.1. The versions available
|
<listitem>Boost version is at least 1.65.1. The versions available
|
||||||
in CentOS 7 (1.48 and and 1.53) are too old.</listitem>
|
in CentOS 7 (1.48 and and 1.53) are too old.</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|
||||||
@@ -322,7 +322,7 @@ Please make sure that your compilation has the following:
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
The RADIUS Hook is a library that has to be loaded by either DHCPv4 or
|
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
|
takes many parameters to actually run. For example, this configuration
|
||||||
could be used:
|
could be used:
|
||||||
|
|
||||||
@@ -403,12 +403,12 @@ Please make sure that your compilation has the following:
|
|||||||
|
|
||||||
<listitem><simpara><command>identifier-type4</command> (default client-id)
|
<listitem><simpara><command>identifier-type4</command> (default client-id)
|
||||||
specifies 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
|
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
|
used the replace-client-id must be set to true and client-id will be used
|
||||||
with client-id-pop0. </simpara></listitem>
|
with client-id-pop0. </simpara></listitem>
|
||||||
|
|
||||||
<listitem><simpara><command>identifier-type6</command> (default duid)
|
<listitem><simpara><command>identifier-type6</command> (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
|
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
|
used the replace-client-id must be set to true and duid will be used with
|
||||||
client-id-pop0. </simpara></listitem>
|
client-id-pop0. </simpara></listitem>
|
||||||
@@ -416,6 +416,15 @@ Please make sure that your compilation has the following:
|
|||||||
<listitem><simpara><command>realm</command> (default "") is the default
|
<listitem><simpara><command>realm</command> (default "") is the default
|
||||||
realm. </simpara></listitem>
|
realm. </simpara></listitem>
|
||||||
|
|
||||||
|
<listitem><simpara><command>reselect-subnet-address</command> (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. </simpara></listitem>
|
||||||
|
|
||||||
|
<listitem><simpara><command>reselect-subnet-pool</command> (default
|
||||||
|
false) uses the Kea client-class / RADIUS Frame-Pool to reselect
|
||||||
|
subnets where no available pool can be found. </simpara></listitem>
|
||||||
|
|
||||||
<listitem><simpara><command>retries</command> (default 3) is the number of
|
<listitem><simpara><command>retries</command> (default 3) is the number of
|
||||||
retries before trying the next server. Note it is not supported for
|
retries before trying the next server. Note it is not supported for
|
||||||
asynchronous communication. </simpara></listitem>
|
asynchronous communication. </simpara></listitem>
|
||||||
@@ -430,6 +439,13 @@ Please make sure that your compilation has the following:
|
|||||||
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para> When <command>reselect-subnet-pool</command> or
|
||||||
|
<command>reselect-subnet-address</command> 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.
|
||||||
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Two services are supported:
|
Two services are supported:
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
|
@@ -503,48 +503,7 @@ Dhcpv4Srv::selectSubnet(const Pkt4Ptr& query, bool& drop,
|
|||||||
|
|
||||||
Subnet4Ptr subnet;
|
Subnet4Ptr subnet;
|
||||||
|
|
||||||
SubnetSelector selector;
|
const SubnetSelector& selector = CfgSubnets4::initSelector(query);
|
||||||
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<OptionCustom>(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<OptionCustom>(sbnsel);
|
|
||||||
if (oc) {
|
|
||||||
selector.option_select_ = oc->readAddress();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CfgMgr& cfgmgr = CfgMgr::instance();
|
CfgMgr& cfgmgr = CfgMgr::instance();
|
||||||
subnet = cfgmgr.getCurrentCfg()->getCfgSubnets4()->selectSubnet(selector);
|
subnet = cfgmgr.getCurrentCfg()->getCfgSubnets4()->selectSubnet(selector);
|
||||||
|
@@ -1306,31 +1306,11 @@ Dhcpv6Srv::sanityCheck(const Pkt6Ptr& pkt, RequirementLevel clientid,
|
|||||||
|
|
||||||
Subnet6Ptr
|
Subnet6Ptr
|
||||||
Dhcpv6Srv::selectSubnet(const Pkt6Ptr& question, bool& drop) {
|
Dhcpv6Srv::selectSubnet(const Pkt6Ptr& question, bool& drop) {
|
||||||
// Initialize subnet selector with the values used to select the subnet.
|
const SubnetSelector& selector = CfgSubnets6::initSelector(question);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
Subnet6Ptr subnet = CfgMgr::instance().getCurrentCfg()->
|
Subnet6Ptr subnet = CfgMgr::instance().getCurrentCfg()->
|
||||||
getCfgSubnets6()->selectSubnet(selector);
|
getCfgSubnets6()->selectSubnet(selector);
|
||||||
|
|
||||||
|
|
||||||
// Let's execute all callouts registered for subnet6_receive
|
// Let's execute all callouts registered for subnet6_receive
|
||||||
if (HooksManager::calloutsPresent(Hooks.hook_index_subnet6_select_)) {
|
if (HooksManager::calloutsPresent(Hooks.hook_index_subnet6_select_)) {
|
||||||
CalloutHandlePtr callout_handle = getCalloutHandle(question);
|
CalloutHandlePtr callout_handle = getCalloutHandle(question);
|
||||||
|
@@ -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
|
// 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
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <dhcp/iface_mgr.h>
|
#include <dhcp/iface_mgr.h>
|
||||||
|
#include <dhcp/option_custom.h>
|
||||||
#include <dhcpsrv/cfg_subnets4.h>
|
#include <dhcpsrv/cfg_subnets4.h>
|
||||||
#include <dhcpsrv/dhcpsrv_log.h>
|
#include <dhcpsrv/dhcpsrv_log.h>
|
||||||
#include <dhcpsrv/lease_mgr_factory.h>
|
#include <dhcpsrv/lease_mgr_factory.h>
|
||||||
@@ -75,6 +76,54 @@ CfgSubnets4::hasSubnetWithServerId(const asiolink::IOAddress& server_id) const {
|
|||||||
return (subnet_it != index.cend());
|
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<OptionCustom>(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<OptionCustom>(sbnsel);
|
||||||
|
if (oc) {
|
||||||
|
selector.option_select_ = oc->readAddress();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (selector);
|
||||||
|
}
|
||||||
|
|
||||||
Subnet4Ptr
|
Subnet4Ptr
|
||||||
CfgSubnets4::selectSubnet4o6(const SubnetSelector& selector) const {
|
CfgSubnets4::selectSubnet4o6(const SubnetSelector& selector) const {
|
||||||
|
|
||||||
|
@@ -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
|
// 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
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <asiolink/io_address.h>
|
#include <asiolink/io_address.h>
|
||||||
#include <cc/cfg_to_element.h>
|
#include <cc/cfg_to_element.h>
|
||||||
|
#include <dhcp/pkt4.h>
|
||||||
#include <dhcpsrv/subnet.h>
|
#include <dhcpsrv/subnet.h>
|
||||||
#include <dhcpsrv/subnet_id.h>
|
#include <dhcpsrv/subnet_id.h>
|
||||||
#include <dhcpsrv/subnet_selector.h>
|
#include <dhcpsrv/subnet_selector.h>
|
||||||
@@ -99,6 +100,14 @@ public:
|
|||||||
/// @return true if there is a subnet with a specified server identifier.
|
/// @return true if there is a subnet with a specified server identifier.
|
||||||
bool hasSubnetWithServerId(const asiolink::IOAddress& server_id) const;
|
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.
|
/// @brief Returns a pointer to the selected subnet.
|
||||||
///
|
///
|
||||||
/// This method tries to retrieve the subnet for the client using various
|
/// This method tries to retrieve the subnet for the client using various
|
||||||
|
@@ -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
|
// 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
|
// 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/.
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
#include <dhcp/dhcp6.h>
|
||||||
|
#include <dhcp/option_custom.h>
|
||||||
#include <dhcpsrv/cfg_subnets6.h>
|
#include <dhcpsrv/cfg_subnets6.h>
|
||||||
#include <dhcpsrv/dhcpsrv_log.h>
|
#include <dhcpsrv/dhcpsrv_log.h>
|
||||||
#include <dhcpsrv/lease_mgr_factory.h>
|
#include <dhcpsrv/lease_mgr_factory.h>
|
||||||
#include <dhcpsrv/subnet_id.h>
|
#include <dhcpsrv/subnet_id.h>
|
||||||
#include <dhcpsrv/addr_utilities.h>
|
#include <dhcpsrv/addr_utilities.h>
|
||||||
#include <stats/stats_mgr.h>
|
#include <stats/stats_mgr.h>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
@@ -66,6 +69,32 @@ CfgSubnets6::getByPrefix(const std::string& subnet_text) const {
|
|||||||
return ((subnet_it != index.cend()) ? (*subnet_it) : ConstSubnet6Ptr());
|
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
|
Subnet6Ptr
|
||||||
CfgSubnets6::selectSubnet(const SubnetSelector& selector) const {
|
CfgSubnets6::selectSubnet(const SubnetSelector& selector) const {
|
||||||
Subnet6Ptr subnet;
|
Subnet6Ptr subnet;
|
||||||
|
@@ -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
|
// 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
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <asiolink/io_address.h>
|
#include <asiolink/io_address.h>
|
||||||
#include <dhcp/option.h>
|
#include <dhcp/option.h>
|
||||||
|
#include <dhcp/pkt6.h>
|
||||||
#include <cc/cfg_to_element.h>
|
#include <cc/cfg_to_element.h>
|
||||||
#include <dhcpsrv/subnet.h>
|
#include <dhcpsrv/subnet.h>
|
||||||
#include <dhcpsrv/subnet_id.h>
|
#include <dhcpsrv/subnet_id.h>
|
||||||
@@ -92,6 +93,14 @@ public:
|
|||||||
/// subnet doesn't exist.
|
/// subnet doesn't exist.
|
||||||
ConstSubnet6Ptr getByPrefix(const std::string& subnet_prefix) const;
|
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.
|
/// @brief Selects a subnet using parameters specified in the selector.
|
||||||
///
|
///
|
||||||
/// This method tries to retrieve the subnet for the client using various
|
/// This method tries to retrieve the subnet for the client using various
|
||||||
|
Reference in New Issue
Block a user