Commit ea5e0056 authored by Francis Dupont's avatar Francis Dupont

[master] Merged trac5617 (RADIUS reselect subnet)

parents 770dc7bd 9891e5af
......@@ -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,
......
......@@ -301,7 +301,7 @@ Please make sure that your compilation has the following:
<listitem>radius listed in tier 2 packages</listitem>
<listitem>FreeRadius client directories printed and pointing to the right
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>
</itemizedlist>
......@@ -322,7 +322,7 @@ Please make sure that your compilation has the following:
<para>
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:
<listitem><simpara><command>identifier-type4</command> (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. </simpara></listitem>
<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
used the replace-client-id must be set to true and duid will be used with
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
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
retries before trying the next server. Note it is not supported for
asynchronous communication. </simpara></listitem>
......@@ -430,6 +439,13 @@ Please make sure that your compilation has the following:
</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>
Two services are supported:
<itemizedlist>
......
......@@ -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<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();
}
}
}
const SubnetSelector& selector = CfgSubnets4::initSelector(query);
CfgMgr& cfgmgr = CfgMgr::instance();
subnet = cfgmgr.getCurrentCfg()->getCfgSubnets4()->selectSubnet(selector);
......
......@@ -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);
......
// 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 <config.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/option_custom.h>
#include <dhcpsrv/cfg_subnets4.h>
#include <dhcpsrv/dhcpsrv_log.h>
#include <dhcpsrv/lease_mgr_factory.h>
......@@ -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<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
CfgSubnets4::selectSubnet4o6(const SubnetSelector& selector) const {
......
// 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 <asiolink/io_address.h>
#include <cc/cfg_to_element.h>
#include <dhcp/pkt4.h>
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/subnet_id.h>
#include <dhcpsrv/subnet_selector.h>
......@@ -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
......
// 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 <config.h>
#include <dhcp/dhcp6.h>
#include <dhcp/option_custom.h>
#include <dhcpsrv/cfg_subnets6.h>
#include <dhcpsrv/dhcpsrv_log.h>
#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/subnet_id.h>
#include <dhcpsrv/addr_utilities.h>
#include <stats/stats_mgr.h>
#include <boost/foreach.hpp>
#include <string.h>
#include <sstream>
......@@ -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;
......
// 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 <asiolink/io_address.h>
#include <dhcp/option.h>
#include <dhcp/pkt6.h>
#include <cc/cfg_to_element.h>
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/subnet_id.h>
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment