Browse Source

[master] Merge branch 'trac2313'

Conflicts:
	src/lib/dhcpsrv/cfgmgr.cc
	src/lib/dhcpsrv/cfgmgr.h
Marcin Siodelski 12 years ago
parent
commit
37a27e19be

+ 6 - 6
src/lib/dhcp/Makefile.am

@@ -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

+ 1 - 0
src/lib/dhcpsrv/Makefile.am

@@ -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

+ 30 - 0
src/lib/dhcpsrv/cfgmgr.cc

@@ -30,6 +30,36 @@ CfgMgr::instance() {
 }
 
 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) {
     // @todo we need better validation of the provided option space name here.

+ 37 - 1
src/lib/dhcpsrv/cfgmgr.h

@@ -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 - 0
src/lib/dhcpsrv/option_space.cc

@@ -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 - 0
src/lib/dhcpsrv/option_space.h

@@ -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

+ 1 - 0
src/lib/dhcpsrv/tests/Makefile.am

@@ -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

+ 66 - 0
src/lib/dhcpsrv/tests/cfgmgr_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 - 0
src/lib/dhcpsrv/tests/option_space_unittest.cc

@@ -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