// PERFORMANCE OF THIS SOFTWARE.
#include <dhcpsrv/host.h>
+#include <util/strutil.h>
#include <exceptions/exceptions.h>
namespace isc {
const IdentifierType& identifier_type,
const SubnetID ipv4_subnet_id, const SubnetID ipv6_subnet_id,
const asiolink::IOAddress& ipv4_reservation,
- const std::string& hostname)
+ const std::string& hostname,
+ const std::string& dhcp4_client_classes,
+ const std::string& dhcp6_client_classes)
: hw_address_(), duid_(), ipv4_subnet_id_(ipv4_subnet_id),
ipv6_subnet_id_(ipv6_subnet_id), ipv4_reservation_(ipv4_reservation),
- hostname_(hostname), dhcp4_client_classes_(), dhcp6_client_classes_() {
+ hostname_(hostname), dhcp4_client_classes_(dhcp4_client_classes),
+ dhcp6_client_classes_(dhcp6_client_classes) {
// Initialize HWAddr or DUID
setIdentifier(identifier, identifier_len, identifier_type);
Host::Host(const std::string& identifier, const std::string& identifier_name,
const SubnetID ipv4_subnet_id, const SubnetID ipv6_subnet_id,
const asiolink::IOAddress& ipv4_reservation,
- const std::string& hostname)
+ const std::string& hostname,
+ const std::string& dhcp4_client_classes,
+ const std::string& dhcp6_client_classes)
: hw_address_(), duid_(), ipv4_subnet_id_(ipv4_subnet_id),
ipv6_subnet_id_(ipv6_subnet_id), ipv4_reservation_(ipv4_reservation),
- hostname_(hostname), dhcp4_client_classes_(), dhcp6_client_classes_() {
+ hostname_(hostname), dhcp4_client_classes_(dhcp4_client_classes),
+ dhcp6_client_classes_(dhcp6_client_classes) {
// Initialize HWAddr or DUID
setIdentifier(identifier, identifier_name);
return (ipv6_reservations_.equal_range(type));
}
+void
+Host::addClientClassInternal(ClientClasses& classes,
+ const std::string& class_name) {
+ std::string trimmed = util::str::trim(class_name);
+ if (!class_name.empty()) {
+ classes.insert(ClientClass(class_name));
+ }
+}
} // end of namespace isc::dhcp
} // end of namespace isc
/// this address is set to 0, there is no reservation.
/// @param hostname Hostname to be allocated to both DHCPv4 and DHCPv6
/// clients. This is empty string if hostname is not allocated.
+ /// @param dhcp4_client_classes A string holding DHCPv4 client class names
+ /// separated by commas. The names get trimmed by this constructor.
+ /// @param dhcp6_client_classes A string holding DHCPv6 client class names
+ /// separated by commas. The names get trimmed by this constructor.
///
/// @throw BadValue if the provided values are invalid. In particular,
/// if the identifier is invalid.
const IdentifierType& identifier_type,
const SubnetID ipv4_subnet_id, const SubnetID ipv6_subnet_id,
const asiolink::IOAddress& ipv4_reservation,
- const std::string& hostname = "");
+ const std::string& hostname = "",
+ const std::string& dhcp4_client_classes = "",
+ const std::string& dhcp6_client_classes = "");
/// @brief Constructor.
///
/// this address is set to 0, there is no reservation.
/// @param hostname Hostname to be allocated to both DHCPv4 and DHCPv6
/// clients. This is empty string if hostname is not allocated.
+ /// @param dhcp4_client_classes A string holding DHCPv4 client class names
+ /// separated by commas. The names get trimmed by this constructor.
+ /// @param dhcp6_client_classes A string holding DHCPv6 client class names
+ /// separated by commas. The names get trimmed by this constructor.
///
/// @throw BadValue if the provided values are invalid. In particular,
/// if the identifier is invalid.
Host(const std::string& identifier, const std::string& identifier_name,
const SubnetID ipv4_subnet_id, const SubnetID ipv6_subnet_id,
const asiolink::IOAddress& ipv4_reservation,
- const std::string& hostname = "");
+ const std::string& hostname = "",
+ const std::string& dhcp4_client_classes = "",
+ const std::string& dhcp6_client_classes = "");
/// @brief Replaces currently used identifier with a new identifier.
///
return (hostname_);
}
+ /// @brief Adds new client class for DHCPv4.
+ ///
+ /// @param class_name Class name.
+ void addClientClass4(const std::string& class_name) {
+ addClientClassInternal(dhcp4_client_classes_, class_name);
+ }
+
/// @brief Returns classes which DHCPv4 client is associated with.
const ClientClasses& getClientClasses4() const {
return (dhcp4_client_classes_);
}
+ /// @brief Adds new client class for DHCPv6.
+ ///
+ /// @param class_name Class name.
+ void addClientClass6(const std::string& class_name) {
+ addClientClassInternal(dhcp6_client_classes_, class_name);
+ }
+
/// @brief Returns classes which DHCPv6 client is associated with.
const ClientClasses& getClientClasses6() const {
return (dhcp6_client_classes_);
private:
+ /// @brief Adds new client class for DHCPv4 or DHCPv6.
+ ///
+ /// This method is called internally by the @c addClientClass4 and
+ /// @c addClientClass6 functions. It adds the class of the specified name
+ /// to the supplied class set. The class names are trimmed before they are
+ /// added. Empty class names are ignored.
+ ///
+ /// @param [out] classes Set of classes to which the new class should be
+ /// inserted.
+ /// @param class_name Class name.
+ void addClientClassInternal(ClientClasses& classes,
+ const std::string& class_name);
+
/// @brief Pointer to the hardware address associated with the reservations
/// for the host.
HWAddrPtr hw_address_;
isc::BadValue);
// Empty DUID is also not allowed.
- try {
- Host("", "duid", SubnetID(1), SubnetID(2),
- IOAddress("192.0.2.3"), "somehost.example.org");
- } catch (const std::exception& ex) {
- std::cout << ex.what() << std::endl;
- }
EXPECT_THROW(Host("", "duid", SubnetID(1), SubnetID(2),
IOAddress("192.0.2.3"), "somehost.example.org"),
isc::BadValue);
EXPECT_EQ("10.0.0.1", host->getIPv4Reservation().toText());
}
+// Test that Host constructors initialize client classes from string.
+TEST(HostTest, clientClassesFromConstructor) {
+ boost::scoped_ptr<Host> host;
+ // Prepare the hardware address in binary format.
+ const uint8_t hwaddr_data[] = {
+ 0xaa, 0xab, 0xca, 0xda, 0xbb, 0xee
+ };
+
+ // Try the "from binary" constructor.
+ ASSERT_NO_THROW(host.reset(new Host(hwaddr_data,
+ sizeof(hwaddr_data),
+ Host::IDENT_HWADDR,
+ SubnetID(1), SubnetID(2),
+ IOAddress("192.0.2.3"),
+ "somehost.example.org",
+ "alpha, , beta",
+ "gamma")));
+
+ EXPECT_TRUE(host->getClientClasses4().contains("alpha"));
+ EXPECT_TRUE(host->getClientClasses4().contains("beta"));
+ EXPECT_FALSE(host->getClientClasses4().contains("gamma"));
+ EXPECT_TRUE(host->getClientClasses6().contains("gamma"));
+ EXPECT_FALSE(host->getClientClasses6().contains("alpha"));
+ EXPECT_FALSE(host->getClientClasses6().contains("beta"));
+
+ // Try the "from string" constructor.
+ ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
+ SubnetID(1), SubnetID(2),
+ IOAddress("192.0.2.3"),
+ "somehost.example.org",
+ "alpha, beta, gamma",
+ "beta, gamma")));
+
+ EXPECT_TRUE(host->getClientClasses4().contains("alpha"));
+ EXPECT_TRUE(host->getClientClasses4().contains("beta"));
+ EXPECT_TRUE(host->getClientClasses4().contains("gamma"));
+ EXPECT_FALSE(host->getClientClasses6().contains("alpha"));
+ EXPECT_TRUE(host->getClientClasses6().contains("beta"));
+ EXPECT_TRUE(host->getClientClasses6().contains("gamma"));
+}
+
+// Test that new client classes can be added for the Host.
+TEST(HostTest, addClientClasses) {
+ boost::scoped_ptr<Host> host;
+ ASSERT_NO_THROW(host.reset(new Host("01:02:03:04:05:06", "hw-address",
+ SubnetID(1), SubnetID(2),
+ IOAddress("192.0.2.3"))));
+
+ EXPECT_FALSE(host->getClientClasses4().contains("foo"));
+ EXPECT_FALSE(host->getClientClasses6().contains("foo"));
+ EXPECT_FALSE(host->getClientClasses4().contains("bar"));
+ EXPECT_FALSE(host->getClientClasses6().contains("bar"));
+
+ host->addClientClass4("foo");
+ host->addClientClass6("bar");
+ EXPECT_TRUE(host->getClientClasses4().contains("foo"));
+ EXPECT_FALSE(host->getClientClasses6().contains("foo"));
+ EXPECT_FALSE(host->getClientClasses4().contains("bar"));
+ EXPECT_TRUE(host->getClientClasses6().contains("bar"));
+
+ host->addClientClass4("bar");
+ host->addClientClass6("foo");
+ EXPECT_TRUE(host->getClientClasses4().contains("foo"));
+ EXPECT_TRUE(host->getClientClasses6().contains("foo"));
+ EXPECT_TRUE(host->getClientClasses4().contains("bar"));
+ EXPECT_TRUE(host->getClientClasses6().contains("bar"));
+}
+
} // end of anonymous namespace