mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 05:55:28 +00:00
[master] Merge branch 'trac2313'
Conflicts: src/lib/dhcpsrv/cfgmgr.cc src/lib/dhcpsrv/cfgmgr.h
This commit is contained in:
@@ -14,23 +14,23 @@ CLEANFILES = *.gcno *.gcda
|
||||
|
||||
lib_LTLIBRARIES = libb10-dhcp++.la
|
||||
libb10_dhcp___la_SOURCES =
|
||||
libb10_dhcp___la_SOURCES += dhcp6.h dhcp4.h
|
||||
libb10_dhcp___la_SOURCES += duid.cc duid.h
|
||||
libb10_dhcp___la_SOURCES += iface_mgr.cc iface_mgr.h
|
||||
libb10_dhcp___la_SOURCES += iface_mgr_bsd.cc
|
||||
libb10_dhcp___la_SOURCES += iface_mgr_linux.cc
|
||||
libb10_dhcp___la_SOURCES += iface_mgr_sun.cc
|
||||
libb10_dhcp___la_SOURCES += libdhcp++.cc libdhcp++.h
|
||||
libb10_dhcp___la_SOURCES += option.cc option.h
|
||||
libb10_dhcp___la_SOURCES += option_data_types.cc option_data_types.h
|
||||
libb10_dhcp___la_SOURCES += option_definition.cc option_definition.h
|
||||
libb10_dhcp___la_SOURCES += option_custom.cc option_custom.h
|
||||
libb10_dhcp___la_SOURCES += option4_addrlst.cc option4_addrlst.h
|
||||
libb10_dhcp___la_SOURCES += option6_ia.cc option6_ia.h
|
||||
libb10_dhcp___la_SOURCES += option6_iaaddr.cc option6_iaaddr.h
|
||||
libb10_dhcp___la_SOURCES += option6_addrlst.cc option6_addrlst.h
|
||||
libb10_dhcp___la_SOURCES += option4_addrlst.cc option4_addrlst.h
|
||||
libb10_dhcp___la_SOURCES += option_int.h
|
||||
libb10_dhcp___la_SOURCES += option_int_array.h
|
||||
libb10_dhcp___la_SOURCES += dhcp6.h dhcp4.h
|
||||
libb10_dhcp___la_SOURCES += option.cc option.h
|
||||
libb10_dhcp___la_SOURCES += option_custom.cc option_custom.h
|
||||
libb10_dhcp___la_SOURCES += option_data_types.cc option_data_types.h
|
||||
libb10_dhcp___la_SOURCES += option_definition.cc option_definition.h
|
||||
libb10_dhcp___la_SOURCES += pkt6.cc pkt6.h
|
||||
libb10_dhcp___la_SOURCES += pkt4.cc pkt4.h
|
||||
libb10_dhcp___la_SOURCES += std_option_defs.h
|
||||
|
@@ -43,6 +43,7 @@ libb10_dhcpsrv_la_SOURCES += memfile_lease_mgr.cc memfile_lease_mgr.h
|
||||
if HAVE_MYSQL
|
||||
libb10_dhcpsrv_la_SOURCES += mysql_lease_mgr.cc mysql_lease_mgr.h
|
||||
endif
|
||||
libb10_dhcpsrv_la_SOURCES += option_space.cc option_space.h
|
||||
libb10_dhcpsrv_la_SOURCES += pool.cc pool.h
|
||||
libb10_dhcpsrv_la_SOURCES += subnet.cc subnet.h
|
||||
libb10_dhcpsrv_la_SOURCES += triplet.h
|
||||
|
@@ -29,6 +29,36 @@ CfgMgr::instance() {
|
||||
return (cfg_mgr);
|
||||
}
|
||||
|
||||
void
|
||||
CfgMgr::addOptionSpace4(const OptionSpacePtr& space) {
|
||||
if (!space) {
|
||||
isc_throw(InvalidOptionSpace,
|
||||
"provided option space object is NULL.");
|
||||
}
|
||||
OptionSpaceCollection::iterator it = spaces4_.find(space->getName());
|
||||
if (it != spaces4_.end()) {
|
||||
isc_throw(InvalidOptionSpace, "option space " << space->getName()
|
||||
<< " already added.");
|
||||
}
|
||||
spaces4_.insert(std::pair<std::string,
|
||||
OptionSpacePtr>(space->getName(), space));
|
||||
}
|
||||
|
||||
void
|
||||
CfgMgr::addOptionSpace6(const OptionSpacePtr& space) {
|
||||
if (!space) {
|
||||
isc_throw(InvalidOptionSpace,
|
||||
"provided option space object is NULL.");
|
||||
}
|
||||
OptionSpaceCollection::iterator it = spaces6_.find(space->getName());
|
||||
if (it != spaces6_.end()) {
|
||||
isc_throw(InvalidOptionSpace, "option space " << space->getName()
|
||||
<< " already added.");
|
||||
}
|
||||
spaces6_.insert(std::pair<std::string,
|
||||
OptionSpacePtr>(space->getName(), space));
|
||||
}
|
||||
|
||||
void
|
||||
CfgMgr::addOptionDef(const OptionDefinitionPtr& def,
|
||||
const std::string& option_space) {
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include <asiolink/io_address.h>
|
||||
#include <dhcp/option.h>
|
||||
#include <dhcp/option_definition.h>
|
||||
#include <dhcpsrv/option_space.h>
|
||||
#include <dhcpsrv/pool.h>
|
||||
#include <dhcpsrv/subnet.h>
|
||||
#include <util/buffer.h>
|
||||
@@ -65,7 +66,6 @@ namespace dhcp {
|
||||
/// Parameter inheritance is likely to be implemented in configuration handling
|
||||
/// routines, so there is no storage capability in a global scope for
|
||||
/// subnet-specific parameters.
|
||||
///
|
||||
/// @todo: Implement Subnet4 support (ticket #2237)
|
||||
/// @todo: Implement option definition support
|
||||
/// @todo: Implement parameter inheritance
|
||||
@@ -113,6 +113,36 @@ public:
|
||||
OptionDefinitionPtr getOptionDef(const std::string& option_space,
|
||||
const uint16_t option_code) const;
|
||||
|
||||
/// @brief Adds new DHCPv4 option space to the collection.
|
||||
///
|
||||
/// @param space option space to be added.
|
||||
///
|
||||
/// @throw isc::dhcp::InvalidOptionSpace invalid option space
|
||||
/// has been specified.
|
||||
void addOptionSpace4(const OptionSpacePtr& space);
|
||||
|
||||
/// @brief Adds new DHCPv6 option space to the collection.
|
||||
///
|
||||
/// @param space option space to be added.
|
||||
///
|
||||
/// @throw isc::dhcp::InvalidOptionSpace invalid option space
|
||||
/// has been specified.
|
||||
void addOptionSpace6(const OptionSpacePtr& space);
|
||||
|
||||
/// @brief Return option spaces for DHCPv4.
|
||||
///
|
||||
/// @return A collection of option spaces.
|
||||
const OptionSpaceCollection& getOptionSpaces4() const {
|
||||
return (spaces4_);
|
||||
}
|
||||
|
||||
/// @brief Return option spaces for DHCPv6.
|
||||
///
|
||||
/// @return A collection of option spaces.
|
||||
const OptionSpaceCollection& getOptionSpaces6() const {
|
||||
return (spaces6_);
|
||||
}
|
||||
|
||||
/// @brief get IPv6 subnet by address
|
||||
///
|
||||
/// Finds a matching subnet, based on an address. This can be used
|
||||
@@ -230,6 +260,12 @@ private:
|
||||
/// The map key holds an option space name.
|
||||
OptionDefsMap option_def_spaces_;
|
||||
|
||||
/// @brief Container for defined DHCPv6 option spaces.
|
||||
OptionSpaceCollection spaces6_;
|
||||
|
||||
/// @brief Container for defined DHCPv4 option spaces.
|
||||
OptionSpaceCollection spaces4_;
|
||||
|
||||
};
|
||||
|
||||
} // namespace isc::dhcp
|
||||
|
71
src/lib/dhcpsrv/option_space.cc
Normal file
71
src/lib/dhcpsrv/option_space.cc
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright (C) 2012, 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <dhcpsrv/option_space.h>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
OptionSpace::OptionSpace(const std::string& name, const bool vendor_space)
|
||||
: name_(name), vendor_space_(vendor_space) {
|
||||
// Check that provided option space name is valid.
|
||||
if (!validateName(name_)) {
|
||||
isc_throw(InvalidOptionSpace, "Invalid option space name "
|
||||
<< name_);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
OptionSpace::validateName(const std::string& name) {
|
||||
|
||||
using namespace boost::algorithm;
|
||||
|
||||
// Allowed characters are: lower or upper case letters, digits,
|
||||
// underscores and hyphens. Empty option spaces are not allowed.
|
||||
if (all(name, boost::is_from_range('a', 'z') ||
|
||||
boost::is_from_range('A', 'Z') ||
|
||||
boost::is_digit() ||
|
||||
boost::is_any_of("-_")) &&
|
||||
!name.empty() &&
|
||||
// Hyphens and underscores are not allowed at the beginning
|
||||
// and at the end of the option space name.
|
||||
!all(find_head(name, 1), boost::is_any_of("-_")) &&
|
||||
!all(find_tail(name, 1), boost::is_any_of("-_"))) {
|
||||
return (true);
|
||||
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
OptionSpace6::OptionSpace6(const std::string& name)
|
||||
: OptionSpace(name),
|
||||
enterprise_number_(0) {
|
||||
}
|
||||
|
||||
OptionSpace6::OptionSpace6(const std::string& name,
|
||||
const uint32_t enterprise_number)
|
||||
: OptionSpace(name, true),
|
||||
enterprise_number_(enterprise_number) {
|
||||
}
|
||||
|
||||
void
|
||||
OptionSpace6::setVendorSpace(const uint32_t enterprise_number) {
|
||||
enterprise_number_ = enterprise_number;
|
||||
OptionSpace::setVendorSpace();
|
||||
}
|
||||
|
||||
} // end of isc::dhcp namespace
|
||||
} // end of isc namespace
|
189
src/lib/dhcpsrv/option_space.h
Normal file
189
src/lib/dhcpsrv/option_space.h
Normal file
@@ -0,0 +1,189 @@
|
||||
// Copyright (C) 2012, 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#ifndef OPTION_SPACE_H
|
||||
#define OPTION_SPACE_H
|
||||
|
||||
#include <exceptions/exceptions.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <map>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
/// @brief Exception to be thrown when invalid option space
|
||||
/// is specified.
|
||||
class InvalidOptionSpace : public Exception {
|
||||
public:
|
||||
InvalidOptionSpace(const char* file, size_t line, const char* what) :
|
||||
isc::Exception(file, line, what) { };
|
||||
};
|
||||
|
||||
/// OptionSpace forward declaration.
|
||||
class OptionSpace;
|
||||
/// A pointer to OptionSpace object.
|
||||
typedef boost::shared_ptr<OptionSpace> OptionSpacePtr;
|
||||
/// A collection of option spaces.
|
||||
typedef std::map<std::string, OptionSpacePtr> OptionSpaceCollection;
|
||||
|
||||
/// @brief DHCP option space.
|
||||
///
|
||||
/// This class represents single option space. The option spaces are used
|
||||
/// to group DHCP options having unique option codes. The special type
|
||||
/// of the option space is so called "vendor specific option space".
|
||||
/// It groups sub-options being sent within Vendor Encapsulated Options.
|
||||
/// For DHCPv4 it is the option with code 43. The option spaces are
|
||||
/// assigned to option instances represented by isc::dhcp::Option and
|
||||
/// other classes derived from it. Each particular option may belong to
|
||||
/// multiple option spaces.
|
||||
/// This class may be used to represent any DHCPv4 option space. If the
|
||||
/// option space is to group DHCPv4 Vendor Encapsulated Options then
|
||||
/// "vendor space" flag must be set using \ref OptionSpace::setVendorSpace
|
||||
/// or the argument passed to the constructor. In theory, this class can
|
||||
/// be also used to represent non-vendor specific DHCPv6 option space
|
||||
/// but this is discouraged. For DHCPv6 option spaces the OptionSpace6
|
||||
/// class should be used instead.
|
||||
///
|
||||
/// @note this class is intended to be used to represent DHCPv4 option
|
||||
/// spaces only. However, it hasn't been called OptionSpace4 (that would
|
||||
/// suggest that it is specific to DHCPv4) because it can be also
|
||||
/// used to represent some DHCPv6 option spaces and is a base class
|
||||
/// for \ref OptionSpace6. Thus, if one declared the container as follows:
|
||||
/// @code
|
||||
/// std::vector<OptionSpace4> container;
|
||||
/// @endcode
|
||||
/// it would suggest that the container holds DHCPv4 option spaces while
|
||||
/// it could hold both DHCPv4 and DHCPv6 option spaces as the OptionSpace6
|
||||
/// object could be upcast to OptionSpace4. This confusion does not appear
|
||||
/// when OptionSpace is used as a name for the base class.
|
||||
class OptionSpace {
|
||||
public:
|
||||
|
||||
/// @brief Constructor.
|
||||
///
|
||||
/// @param name option space name.
|
||||
/// @param vendor_space boolean value that indicates that the object
|
||||
/// describes the vendor specific option space.
|
||||
///
|
||||
/// @throw isc::dhcp::InvalidOptionSpace if given option space name
|
||||
/// contains invalid characters or is empty. This constructor uses
|
||||
/// \ref validateName function to check that the specified name is
|
||||
/// correct.
|
||||
OptionSpace(const std::string& name, const bool vendor_space = false);
|
||||
|
||||
/// @brief Return option space name.
|
||||
///
|
||||
/// @return option space name.
|
||||
const std::string& getName() const { return (name_); }
|
||||
|
||||
/// @brief Mark option space as non-vendor space.
|
||||
void clearVendorSpace() {
|
||||
vendor_space_ = false;
|
||||
}
|
||||
|
||||
/// @brief Check if option space is vendor specific.
|
||||
///
|
||||
/// @return boolean value that indicates if the object describes
|
||||
/// the vendor specific option space.
|
||||
bool isVendorSpace() const { return (vendor_space_); }
|
||||
|
||||
/// @brief Mark option space as vendor specific.
|
||||
void setVendorSpace() {
|
||||
vendor_space_ = true;
|
||||
}
|
||||
|
||||
/// @brief Checks that the provided option space name is valid.
|
||||
///
|
||||
/// It is expected that option space name consists of upper or
|
||||
/// lower case letters or digits. Also, it may contain underscores
|
||||
/// or dashes. Other characters are prohibited. The empty option
|
||||
/// space names are invalid.
|
||||
///
|
||||
/// @param name option space name to be validated.
|
||||
///
|
||||
/// @return true if the option space is valid, else it returns false.
|
||||
static bool validateName(const std::string& name);
|
||||
|
||||
private:
|
||||
std::string name_; ///< Holds option space name.
|
||||
|
||||
bool vendor_space_; ///< Is this the vendor space?
|
||||
|
||||
};
|
||||
|
||||
/// @brief DHCPv6 option space with enterprise number assigned.
|
||||
///
|
||||
/// This class extends the base class with the support for enterprise numbers.
|
||||
/// The enterprise numbers are assigned by IANA to various organizations
|
||||
/// and they are carried as uint32_t integers in DHCPv6 Vendor Specific
|
||||
/// Information Options (VSIO). For more information refer to RFC3315.
|
||||
/// All option spaces that group VSIO options must have enterprise number
|
||||
/// set. It can be set using a constructor or \ref setVendorSpace function.
|
||||
/// The extra functionality of this class (enterprise numbers) allows to
|
||||
/// represent DHCPv6 vendor-specific option spaces but this class is also
|
||||
/// intended to be used for all other DHCPv6 option spaces. That way all
|
||||
/// DHCPv6 option spaces can be stored in the container holding OptionSpace6
|
||||
/// objects. Also, it is easy to mark vendor-specific option space as non-vendor
|
||||
/// specific option space (and the other way around) without a need to cast
|
||||
/// between OptionSpace and OptionSpace6 types.
|
||||
class OptionSpace6 : public OptionSpace {
|
||||
public:
|
||||
|
||||
/// @brief Constructor for non-vendor-specific options.
|
||||
///
|
||||
/// This constructor marks option space as non-vendor specific.
|
||||
///
|
||||
/// @param name option space name.
|
||||
///
|
||||
/// @throw isc::dhcp::InvalidOptionSpace if given option space name
|
||||
/// contains invalid characters or is empty. This constructor uses
|
||||
/// \ref OptionSpace::validateName function to check that the specified
|
||||
/// name is correct.
|
||||
OptionSpace6(const std::string& name);
|
||||
|
||||
/// @brief Constructor for vendor-specific options.
|
||||
///
|
||||
/// This constructor marks option space as vendor specific and sets
|
||||
/// enterprise number to a given value.
|
||||
///
|
||||
/// @param name option space name.
|
||||
/// @param enterprise_number enterprise number.
|
||||
///
|
||||
/// @throw isc::dhcp::InvalidOptionSpace if given option space name
|
||||
/// contains invalid characters or is empty. This constructor uses
|
||||
/// \ref OptionSpace::validateName function to check that the specified
|
||||
/// name is correct.
|
||||
OptionSpace6(const std::string& name, const uint32_t enterprise_number);
|
||||
|
||||
/// @brief Return enterprise number for the option space.
|
||||
///
|
||||
/// @return enterprise number.
|
||||
uint32_t getEnterpriseNumber() const { return (enterprise_number_); }
|
||||
|
||||
/// @brief Mark option space as vendor specific.
|
||||
///
|
||||
/// @param enterprise_number enterprise number.
|
||||
void setVendorSpace(const uint32_t enterprise_number);
|
||||
|
||||
private:
|
||||
|
||||
uint32_t enterprise_number_; ///< IANA assigned enterprise number.
|
||||
};
|
||||
|
||||
} // namespace isc::dhcp
|
||||
} // namespace isc
|
||||
|
||||
#endif // OPTION_SPACE_H
|
@@ -37,6 +37,7 @@ libdhcpsrv_unittests_SOURCES += memfile_lease_mgr_unittest.cc
|
||||
if HAVE_MYSQL
|
||||
libdhcpsrv_unittests_SOURCES += mysql_lease_mgr_unittest.cc
|
||||
endif
|
||||
libdhcpsrv_unittests_SOURCES += option_space_unittest.cc
|
||||
libdhcpsrv_unittests_SOURCES += pool_unittest.cc
|
||||
libdhcpsrv_unittests_SOURCES += schema_copy.h
|
||||
libdhcpsrv_unittests_SOURCES += subnet_unittest.cc
|
||||
|
@@ -281,4 +281,70 @@ TEST_F(CfgMgrTest, subnet6) {
|
||||
EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("4000::123")));
|
||||
}
|
||||
|
||||
// This test verifies that new DHCPv4 option spaces can be added to
|
||||
// the configuration manager and that duplicated option space is
|
||||
// rejected.
|
||||
TEST_F(CfgMgrTest, optionSpace4) {
|
||||
CfgMgr& cfg_mgr = CfgMgr::instance();
|
||||
|
||||
// Create some option spaces.
|
||||
OptionSpacePtr space1(new OptionSpace("isc", false));
|
||||
OptionSpacePtr space2(new OptionSpace("xyz", true));
|
||||
|
||||
// Add option spaces with different names and expect they
|
||||
// are accepted.
|
||||
ASSERT_NO_THROW(cfg_mgr.addOptionSpace4(space1));
|
||||
ASSERT_NO_THROW(cfg_mgr.addOptionSpace4(space2));
|
||||
|
||||
// Validate that the option spaces have been added correctly.
|
||||
const OptionSpaceCollection& spaces = cfg_mgr.getOptionSpaces4();
|
||||
|
||||
ASSERT_EQ(2, spaces.size());
|
||||
EXPECT_FALSE(spaces.find("isc") == spaces.end());
|
||||
EXPECT_FALSE(spaces.find("xyz") == spaces.end());
|
||||
|
||||
// Create another option space with the name that duplicates
|
||||
// the existing option space.
|
||||
OptionSpacePtr space3(new OptionSpace("isc", true));
|
||||
// Expect that the duplicate option space is rejected.
|
||||
ASSERT_THROW(
|
||||
cfg_mgr.addOptionSpace4(space3), isc::dhcp::InvalidOptionSpace
|
||||
);
|
||||
|
||||
// @todo decode if a duplicate vendor space is allowed.
|
||||
}
|
||||
|
||||
// This test verifies that new DHCPv6 option spaces can be added to
|
||||
// the configuration manager and that duplicated option space is
|
||||
// rejected.
|
||||
TEST_F(CfgMgrTest, optionSpace6) {
|
||||
CfgMgr& cfg_mgr = CfgMgr::instance();
|
||||
|
||||
// Create some option spaces.
|
||||
OptionSpacePtr space1(new OptionSpace("isc", false));
|
||||
OptionSpacePtr space2(new OptionSpace("xyz", true));
|
||||
|
||||
// Add option spaces with different names and expect they
|
||||
// are accepted.
|
||||
ASSERT_NO_THROW(cfg_mgr.addOptionSpace6(space1));
|
||||
ASSERT_NO_THROW(cfg_mgr.addOptionSpace6(space2));
|
||||
|
||||
// Validate that the option spaces have been added correctly.
|
||||
const OptionSpaceCollection& spaces = cfg_mgr.getOptionSpaces6();
|
||||
|
||||
ASSERT_EQ(2, spaces.size());
|
||||
EXPECT_FALSE(spaces.find("isc") == spaces.end());
|
||||
EXPECT_FALSE(spaces.find("xyz") == spaces.end());
|
||||
|
||||
// Create another option space with the name that duplicates
|
||||
// the existing option space.
|
||||
OptionSpacePtr space3(new OptionSpace("isc", true));
|
||||
// Expect that the duplicate option space is rejected.
|
||||
ASSERT_THROW(
|
||||
cfg_mgr.addOptionSpace6(space3), isc::dhcp::InvalidOptionSpace
|
||||
);
|
||||
|
||||
// @todo decide if a duplicate vendor space is allowed.
|
||||
}
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
150
src/lib/dhcpsrv/tests/option_space_unittest.cc
Normal file
150
src/lib/dhcpsrv/tests/option_space_unittest.cc
Normal file
@@ -0,0 +1,150 @@
|
||||
// Copyright (C) 2012, 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <dhcpsrv/option_space.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace isc::dhcp;
|
||||
using namespace isc;
|
||||
|
||||
namespace {
|
||||
|
||||
// The purpose of this test is to verify that the constructor
|
||||
// creates an object with members initialized to correct values.
|
||||
TEST(OptionSpaceTest, constructor) {
|
||||
// Create some option space.
|
||||
OptionSpace space("isc", true);
|
||||
EXPECT_EQ("isc", space.getName());
|
||||
EXPECT_TRUE(space.isVendorSpace());
|
||||
|
||||
// Create another object with different values
|
||||
// to check that the values will change.
|
||||
OptionSpace space2("abc", false);
|
||||
EXPECT_EQ("abc", space2.getName());
|
||||
EXPECT_FALSE(space2.isVendorSpace());
|
||||
|
||||
// Verify that constructor throws exception if invalid
|
||||
// option space name is provided.
|
||||
EXPECT_THROW(OptionSpace("invalid%space.name"), InvalidOptionSpace);
|
||||
}
|
||||
|
||||
// The purpose of this test is to verify that the vendor-space flag
|
||||
// can be overriden.
|
||||
TEST(OptionSpaceTest, setVendorSpace) {
|
||||
OptionSpace space("isc", true);
|
||||
EXPECT_EQ("isc", space.getName());
|
||||
EXPECT_TRUE(space.isVendorSpace());
|
||||
|
||||
// Override the vendor space flag.
|
||||
space.clearVendorSpace();
|
||||
EXPECT_FALSE(space.isVendorSpace());
|
||||
}
|
||||
|
||||
// The purpose of this test is to verify that the static function
|
||||
// to validate the option space name works correctly.
|
||||
TEST(OptionSpaceTest, validateName) {
|
||||
// Positive test scenarios: letters, digits, dashes, underscores
|
||||
// lower/upper case allowed.
|
||||
EXPECT_TRUE(OptionSpace::validateName("abc"));
|
||||
EXPECT_TRUE(OptionSpace::validateName("dash-allowed"));
|
||||
EXPECT_TRUE(OptionSpace::validateName("two-dashes-allowed"));
|
||||
EXPECT_TRUE(OptionSpace::validateName("underscore_allowed"));
|
||||
EXPECT_TRUE(OptionSpace::validateName("underscore_three_times_allowed"));
|
||||
EXPECT_TRUE(OptionSpace::validateName("digits0912"));
|
||||
EXPECT_TRUE(OptionSpace::validateName("1234"));
|
||||
EXPECT_TRUE(OptionSpace::validateName("UPPER_CASE_allowed"));
|
||||
|
||||
// Negative test scenarions: empty strings, dots, spaces are not
|
||||
// allowed
|
||||
EXPECT_FALSE(OptionSpace::validateName(""));
|
||||
EXPECT_FALSE(OptionSpace::validateName(" "));
|
||||
EXPECT_FALSE(OptionSpace::validateName(" isc "));
|
||||
EXPECT_FALSE(OptionSpace::validateName("isc "));
|
||||
EXPECT_FALSE(OptionSpace::validateName(" isc"));
|
||||
EXPECT_FALSE(OptionSpace::validateName("isc with-space"));
|
||||
|
||||
// Hyphens and underscores are not allowed at the beginning
|
||||
// and at the end of the option space name.
|
||||
EXPECT_FALSE(OptionSpace::validateName("-isc"));
|
||||
EXPECT_FALSE(OptionSpace::validateName("isc-"));
|
||||
EXPECT_FALSE(OptionSpace::validateName("_isc"));
|
||||
EXPECT_FALSE(OptionSpace::validateName("isc_"));
|
||||
|
||||
// Test other special characters
|
||||
const char specials[] = { '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
|
||||
'+', '=', '[', ']', '{', '}', ';', ':', '"', '\'',
|
||||
'\\', '|', '<','>', ',', '.', '?', '~', '`' };
|
||||
for (int i = 0; i < sizeof(specials); ++i) {
|
||||
std::ostringstream stream;
|
||||
// Concatenate valid option space name: "abc" with an invalid character.
|
||||
// That way we get option space names like: "abc!", "abc$" etc. It is
|
||||
// expected that the validating function fails form them.
|
||||
stream << "abc" << specials[i];
|
||||
EXPECT_FALSE(OptionSpace::validateName(stream.str()))
|
||||
<< "Test failed for special character '" << specials[i] << "'.";
|
||||
}
|
||||
}
|
||||
|
||||
// The purpose of this test is to verify that the constructors of the
|
||||
// OptionSpace6 class set the class members to correct values.
|
||||
TEST(OptionSpace6Test, constructor) {
|
||||
// Create some option space and do not specify enterprise number.
|
||||
// In such case the vendor space flag is expected to be
|
||||
// set to false.
|
||||
OptionSpace6 space1("abcd");
|
||||
EXPECT_EQ("abcd", space1.getName());
|
||||
EXPECT_FALSE(space1.isVendorSpace());
|
||||
|
||||
// Create an option space and specify an enterprise number. In this
|
||||
// case the vendor space flag is expected to be set to true and the
|
||||
// enterprise number should be set to a desired value.
|
||||
OptionSpace6 space2("abcd", 2145);
|
||||
EXPECT_EQ("abcd", space2.getName());
|
||||
EXPECT_TRUE(space2.isVendorSpace());
|
||||
EXPECT_EQ(2145, space2.getEnterpriseNumber());
|
||||
|
||||
// Verify that constructors throw an exception when invalid option
|
||||
// space name has been specified.
|
||||
EXPECT_THROW(OptionSpace6("isc dhcp"), InvalidOptionSpace);
|
||||
EXPECT_THROW(OptionSpace6("isc%dhcp", 2145), InvalidOptionSpace);
|
||||
}
|
||||
|
||||
// The purpose of this test is to verify an option space can be marked
|
||||
// vendor option space and enterprise number can be set.
|
||||
TEST(OptionSpace6Test, setVendorSpace) {
|
||||
OptionSpace6 space("isc");
|
||||
EXPECT_EQ("isc", space.getName());
|
||||
EXPECT_FALSE(space.isVendorSpace());
|
||||
|
||||
// Mark it vendor option space and set enterprise id.
|
||||
space.setVendorSpace(1234);
|
||||
EXPECT_TRUE(space.isVendorSpace());
|
||||
EXPECT_EQ(1234, space.getEnterpriseNumber());
|
||||
|
||||
// Override the enterprise number to make sure and make sure that
|
||||
// the new number is returned by the object.
|
||||
space.setVendorSpace(2345);
|
||||
EXPECT_TRUE(space.isVendorSpace());
|
||||
EXPECT_EQ(2345, space.getEnterpriseNumber());
|
||||
|
||||
// Clear the vendor option space flag.
|
||||
space.clearVendorSpace();
|
||||
EXPECT_FALSE(space.isVendorSpace());
|
||||
}
|
||||
|
||||
|
||||
}; // end of anonymous namespace
|
Reference in New Issue
Block a user