mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 14:05:33 +00:00
[3274] Subnets are now able to store client class information.
This commit is contained in:
@@ -14,6 +14,9 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifndef CLASSIFY_H
|
||||
#define CLASSIFY_H
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
@@ -38,8 +41,27 @@ namespace dhcp {
|
||||
typedef std::string ClientClass;
|
||||
|
||||
/// Container for storing client classes
|
||||
typedef std::set<ClientClass> ClientClasses;
|
||||
///
|
||||
/// Depending on how you look at it, this is either a little more than just
|
||||
/// a set of strings or a client classifier that performs access control.
|
||||
/// For now, it is a simple access list that may contain zero or more
|
||||
/// class names. It is expected to grow in complexity once support for
|
||||
/// client classes becomes more feature rich.
|
||||
class ClientClasses : public std::set<ClientClass> {
|
||||
public:
|
||||
/// @brief returns if class X belongs to the defined classes
|
||||
///
|
||||
/// @param x client class to be checked
|
||||
/// @return true if X belongs to the classes
|
||||
bool
|
||||
contains(const ClientClass& x) const {
|
||||
const_iterator it = find(x);
|
||||
return (it != end());
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* CLASSIFY_H */
|
||||
|
@@ -76,6 +76,21 @@ Subnet::setRelay(const isc::dhcp::Subnet::RelayInfo& relay) {
|
||||
relay_ = relay;
|
||||
}
|
||||
|
||||
bool
|
||||
Subnet::clientSupported(const isc::dhcp::ClientClasses& classes) const {
|
||||
if (white_list_.empty()) {
|
||||
return (true); // There is no class defined for this subnet, so we do
|
||||
// support everyone.
|
||||
}
|
||||
|
||||
return (classes.contains(white_list_));
|
||||
}
|
||||
|
||||
void
|
||||
Subnet::allowClientClass(const isc::dhcp::ClientClass& class_name) {
|
||||
white_list_ = class_name;
|
||||
}
|
||||
|
||||
void
|
||||
Subnet::delOptions() {
|
||||
option_spaces_.clearItems();
|
||||
|
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <asiolink/io_address.h>
|
||||
#include <dhcp/option.h>
|
||||
#include <dhcp/classify.h>
|
||||
#include <dhcpsrv/key_from_key.h>
|
||||
#include <dhcpsrv/option_space_container.h>
|
||||
#include <dhcpsrv/pool.h>
|
||||
@@ -422,6 +423,26 @@ public:
|
||||
/// subnet object disappears.
|
||||
RelayInfo relay_;
|
||||
|
||||
/// @brief checks whether this subnet supports client that belongs to
|
||||
/// specified classes.
|
||||
///
|
||||
/// This method checks whether a client that belongs to given classes can
|
||||
/// use this subnet. For example, if this class is reserved for client
|
||||
/// class "foo" and the client belongs to classes "foo", "bar" and "baz",
|
||||
/// it is supported. On the other hand, client belonging to classes
|
||||
/// "foobar" and "zyxxy" is not supported.
|
||||
///
|
||||
/// @param client_classes list of all classes the client belongs to
|
||||
/// @return true if client can be supported, false otherwise
|
||||
bool
|
||||
clientSupported(const isc::dhcp::ClientClasses& client_classes) const;
|
||||
|
||||
/// @brief adds class class_name to the list of supported classes
|
||||
///
|
||||
/// @param class_name client class to be supported by this subnet
|
||||
void
|
||||
allowClientClass(const isc::dhcp::ClientClass& class_name);
|
||||
|
||||
protected:
|
||||
/// @brief Returns all pools (non-const variant)
|
||||
///
|
||||
@@ -548,6 +569,13 @@ protected:
|
||||
/// @brief Name of the network interface (if connected directly)
|
||||
std::string iface_;
|
||||
|
||||
/// @brief optional definition of a client class
|
||||
///
|
||||
/// If defined, only clients belonging to that class will be allowed to use
|
||||
/// this particular subnet. The default value for this is "", which means
|
||||
/// that any client is allowed, regardless of its class.
|
||||
ClientClass white_list_;
|
||||
|
||||
private:
|
||||
|
||||
/// A collection of option spaces grouping option descriptors.
|
||||
|
@@ -139,6 +139,44 @@ TEST(Subnet4Test, Subnet4_Pool4_checks) {
|
||||
EXPECT_THROW(subnet->addPool(pool3), BadValue);
|
||||
}
|
||||
|
||||
// Tests whether Subnet4 object is able to store and process properly
|
||||
// information about allowed client classes.
|
||||
TEST(Subnet4Test, clientClasses) {
|
||||
// Create the V4 subnet.
|
||||
Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 8, 1, 2, 3));
|
||||
|
||||
// This client does not belong to any class.
|
||||
isc::dhcp::ClientClasses no_class;
|
||||
|
||||
// This client belongs to foo only.
|
||||
isc::dhcp::ClientClasses foo_class;
|
||||
foo_class.insert("foo");
|
||||
|
||||
// This client belongs to bar only. I like that client.
|
||||
isc::dhcp::ClientClasses bar_class;
|
||||
bar_class.insert("bar");
|
||||
|
||||
// This client belongs to foo, bar and baz classes.
|
||||
isc::dhcp::ClientClasses three_classes;
|
||||
three_classes.insert("foo");
|
||||
three_classes.insert("bar");
|
||||
three_classes.insert("baz");
|
||||
|
||||
// No class restrictions defined, any client should be supported
|
||||
EXPECT_TRUE(subnet->clientSupported(no_class));
|
||||
EXPECT_TRUE(subnet->clientSupported(foo_class));
|
||||
EXPECT_TRUE(subnet->clientSupported(bar_class));
|
||||
EXPECT_TRUE(subnet->clientSupported(three_classes));
|
||||
|
||||
// Let's allow only clients belongning to "bar" class.
|
||||
subnet->allowClientClass("bar");
|
||||
|
||||
EXPECT_FALSE(subnet->clientSupported(no_class));
|
||||
EXPECT_FALSE(subnet->clientSupported(foo_class));
|
||||
EXPECT_TRUE(subnet->clientSupported(bar_class));
|
||||
EXPECT_TRUE(subnet->clientSupported(three_classes));
|
||||
}
|
||||
|
||||
TEST(Subnet4Test, addInvalidOption) {
|
||||
// Create the V4 subnet.
|
||||
Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 8, 1, 2, 3));
|
||||
@@ -416,6 +454,44 @@ TEST(Subnet6Test, PoolTypes) {
|
||||
EXPECT_THROW(subnet->addPool(pool5), BadValue);
|
||||
}
|
||||
|
||||
// Tests whether Subnet6 object is able to store and process properly
|
||||
// information about allowed client classes.
|
||||
TEST(Subnet6Test, clientClasses) {
|
||||
// Create the V6 subnet.
|
||||
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
|
||||
|
||||
// This client does not belong to any class.
|
||||
isc::dhcp::ClientClasses no_class;
|
||||
|
||||
// This client belongs to foo only.
|
||||
isc::dhcp::ClientClasses foo_class;
|
||||
foo_class.insert("foo");
|
||||
|
||||
// This client belongs to bar only. I like that client.
|
||||
isc::dhcp::ClientClasses bar_class;
|
||||
bar_class.insert("bar");
|
||||
|
||||
// This client belongs to foo, bar and baz classes.
|
||||
isc::dhcp::ClientClasses three_classes;
|
||||
three_classes.insert("foo");
|
||||
three_classes.insert("bar");
|
||||
three_classes.insert("baz");
|
||||
|
||||
// No class restrictions defined, any client should be supported
|
||||
EXPECT_TRUE(subnet->clientSupported(no_class));
|
||||
EXPECT_TRUE(subnet->clientSupported(foo_class));
|
||||
EXPECT_TRUE(subnet->clientSupported(bar_class));
|
||||
EXPECT_TRUE(subnet->clientSupported(three_classes));
|
||||
|
||||
// Let's allow only clients belongning to "bar" class.
|
||||
subnet->allowClientClass("bar");
|
||||
|
||||
EXPECT_FALSE(subnet->clientSupported(no_class));
|
||||
EXPECT_FALSE(subnet->clientSupported(foo_class));
|
||||
EXPECT_TRUE(subnet->clientSupported(bar_class));
|
||||
EXPECT_TRUE(subnet->clientSupported(three_classes));
|
||||
}
|
||||
|
||||
TEST(Subnet6Test, Subnet6_Pool6_checks) {
|
||||
|
||||
Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
|
||||
|
Reference in New Issue
Block a user