namespace isc {
namespace dhcp {
+/// @brief Implements the logic for the Option6ClientFqdn class.
+///
+/// The purpose of the class is to separate the implementation details
+/// of the Option4ClientFqdn class from the interface. This implementation
+/// uses libdns classes to process FQDNs. At some point it may be
+/// desired to split libdhcp++ from libdns. In such case the
+/// implementation of this class may be changed. The declaration of the
+/// Option6ClientFqdn class holds the pointer to implementation, so
+/// the transition to a different implementation would not affect the
+/// header file.
class Option4ClientFqdnImpl {
public:
+ /// Holds flags carried by the option.
uint8_t flags_;
+ // Holds RCODE1 and RCODE2 values.
Option4ClientFqdn::Rcode rcode1_;
Option4ClientFqdn::Rcode rcode2_;
+ /// Holds the pointer to a domain name carried in the option.
boost::shared_ptr<isc::dns::Name> domain_name_;
+ /// Indicates whether domain name is partial or fully qualified.
Option4ClientFqdn::DomainNameType domain_name_type_;
+ /// @brief Constructor, from domain name.
+ ///
+ /// @param flags A value of the flags option field.
+ /// @param domain_name A domain name carried by the option given in the
+ /// textual format.
+ /// @param domain_name_type A value which indicates whether domain-name
+ /// is partial of fully qualified.
Option4ClientFqdnImpl(const uint8_t flag,
const Option4ClientFqdn::Rcode& rcode,
const std::string& domain_name,
const Option4ClientFqdn::DomainNameType name_type);
+ /// @brief Constructor, from wire data.
+ ///
+ /// @param first An iterator pointing to the begining of the option data
+ /// in the wire format.
+ /// @param last An iterator poiting to the end of the option data in the
+ /// wire format.
Option4ClientFqdnImpl(OptionBufferConstIter first,
OptionBufferConstIter last);
+ /// @brief Copy constructor.
+ ///
+ /// @param source An object being copied.
Option4ClientFqdnImpl(const Option4ClientFqdnImpl& source);
+ /// @brief Assignment operator.
+ ///
+ /// @param source An object which is being assigned.
Option4ClientFqdnImpl& operator=(const Option4ClientFqdnImpl& source);
+ /// @brief Set a new domain name for the option.
+ ///
+ /// @param domain_name A new domain name to be assigned.
+ /// @param name_type A value which indicates whether the domain-name is
+ /// partial or fully qualified.
void setDomainName(const std::string& domain_name,
const Option4ClientFqdn::DomainNameType name_type);
+ /// @brief Check if flags are valid.
+ ///
+ /// In particular, this function checks if the N and S bits are not
+ /// set to 1 in the same time.
+ ///
+ /// @param flags A value carried by the flags field of the option.
+ /// @param check_mbz A boolean value which indicates if this function should
+ /// check if the MBZ bits are set (if true). This parameter should be set
+ /// to false when validating flags in the received message. This is because
+ /// server should ignore MBZ bits in received messages.
+ /// @throw InvalidOption6FqdnFlags if flags are invalid.
static void checkFlags(const uint8_t flags);
+ /// @brief Parse the Option provided in the wire format.
+ ///
+ /// @param first An iterator pointing to the begining of the option data
+ /// in the wire format.
+ /// @param last An iterator poiting to the end of the option data in the
+ /// wire format.
void parseWireData(OptionBufferConstIter first,
OptionBufferConstIter last);
+ /// @brief Parse domain-name encoded in the canonical format.
+ ///
void parseCanonicalDomainName(OptionBufferConstIter first,
OptionBufferConstIter last);
- void
- parseASCIIDomainName(OptionBufferConstIter first,
- OptionBufferConstIter last);
+ /// @brief Parse domain-name emcoded in the deprecated ASCII format.
+ ///
+ /// @param first An iterator pointing to the begining of the option data
+ /// where domain-name is stored.
+ /// @param last An iterator poiting to the end of the option data where
+ /// domain-name is stored.
+ void parseASCIIDomainName(OptionBufferConstIter first,
+ OptionBufferConstIter last);
};
}
Option4ClientFqdnImpl&
+// This assignment operator handles assignment to self, it copies all
+// required values.
+// cppcheck-suppress operatorEqToSelf
Option4ClientFqdnImpl::operator=(const Option4ClientFqdnImpl& source) {
- domain_name_.reset(new isc::dns::Name(*source.domain_name_));
+ if (source.domain_name_) {
+ domain_name_.reset(new isc::dns::Name(*source.domain_name_));
+
+ } else {
+ domain_name_.reset();
+ }
// Assignment is exception safe.
flags_ = source.flags_;
std::string name = isc::util::str::trim(domain_name);
if (name.empty()) {
if (name_type == Option4ClientFqdn::FULL) {
- isc_throw(InvalidOption4ClientFqdnDomainName,
+ isc_throw(InvalidOption4FqdnDomainName,
"fully qualified domain-name must not be empty"
<< " when setting new domain-name for DHCPv4 Client"
<< " FQDN Option");
domain_name_type_ = name_type;
} catch (const Exception& ex) {
- isc_throw(InvalidOption4ClientFqdnDomainName,
+ isc_throw(InvalidOption4FqdnDomainName,
"invalid domain-name value '"
<< domain_name << "' when setting new domain-name for"
<< " DHCPv4 Client FQDN Option");
Option4ClientFqdnImpl::checkFlags(const uint8_t flags) {
// The Must Be Zero (MBZ) bits must not be set.
if ((flags & ~Option4ClientFqdn::FLAG_MASK) != 0) {
- isc_throw(InvalidOption4ClientFqdnFlags,
+ isc_throw(InvalidOption4FqdnFlags,
"invalid DHCPv4 Client FQDN Option flags: 0x"
<< std::hex << static_cast<int>(flags) << std::dec);
}
// MUST be 0. Checking it here.
if ((flags & (Option4ClientFqdn::FLAG_N | Option4ClientFqdn::FLAG_S))
== (Option4ClientFqdn::FLAG_N | Option4ClientFqdn::FLAG_S)) {
- isc_throw(InvalidOption4ClientFqdnFlags,
+ isc_throw(InvalidOption4FqdnFlags,
"both N and S flag of the DHCPv4 Client FQDN Option are set."
<< " According to RFC 4702, if the N bit is 1 the S bit"
<< " MUST be 0");
}
} catch (const Exception& ex) {
- isc_throw(InvalidOption4ClientFqdnDomainName,
+ isc_throw(InvalidOption4FqdnDomainName,
"failed to parse the domain-name in DHCPv4 Client FQDN"
<< " Option: " << ex.what());
}
}
Option4ClientFqdn&
+// This assignment operator handles assignment to self, it uses copy
+// constructor of Option4ClientFqdnImpl to copy all required values.
+// cppcheck-suppress operatorEqToSelf
Option4ClientFqdn::operator=(const Option4ClientFqdn& source) {
Option4ClientFqdnImpl* old_impl = impl_;
impl_ = new Option4ClientFqdnImpl(*source.impl_);
}
bool
-Option4ClientFqdn::getFlag(const Flag flag) const {
- // Caller should query for one of the: E, N, S or O flags. However, there
- // are valid enumerator values which should not be accepted by this function.
- // For example a value of 0x3 is valid (because it belongs to the range between the
- // lowest and highest enumerator). The value 0x3 represents two flags:
- // S and O and would cause ambiguity. Therefore, we selectively check
- // that the flag is equal to one of the explicit enumerator values. If
- // not, throw an exception.
+Option4ClientFqdn::getFlag(const uint8_t flag) const {
+ // Caller should query for one of the: E, N, S or O flags. Any other value
+ /// is invalid and results in the exception.
if (flag != FLAG_S && flag != FLAG_O && flag != FLAG_N && flag != FLAG_E) {
- isc_throw(InvalidOption4ClientFqdnFlags, "invalid DHCPv4 Client FQDN"
+ isc_throw(InvalidOption4FqdnFlags, "invalid DHCPv4 Client FQDN"
<< " Option flag specified, expected E, N, S or O");
}
}
void
-Option4ClientFqdn::setFlag(const Flag flag, const bool set_flag) {
- // Check that flag is in range between 0x1 and 0x7. Note that this
- // allows to set or clear multiple flags concurrently.
+Option4ClientFqdn::setFlag(const uint8_t flag, const bool set_flag) {
+ // Check that flag is in range between 0x1 and 0x7. Although it is
+ // discouraged this check doesn't preclude the caller from setting
+ // multiple flags concurrently.
if (((flag & ~FLAG_MASK) != 0) || (flag == 0)) {
- isc_throw(InvalidOption4ClientFqdnFlags, "invalid DHCPv4 Client FQDN"
+ isc_throw(InvalidOption4FqdnFlags, "invalid DHCPv4 Client FQDN"
<< " Option flag " << std::hex
<< static_cast<int>(flag) << std::dec
<< "is being set. Expected combination of E, N, S and O");
/// @brief Exception thrown when invalid flags have been specified for
/// DHCPv4 Client FQDN %Option.
-class InvalidOption4ClientFqdnFlags : public Exception {
+class InvalidOption4FqdnFlags : public Exception {
public:
- InvalidOption4ClientFqdnFlags(const char* file, size_t line, const char* what) :
+ InvalidOption4FqdnFlags(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) {}
};
/// @brief Exception thrown when invalid domain name is specified.
-class InvalidOption4ClientFqdnDomainName : public Exception {
+class InvalidOption4FqdnDomainName : public Exception {
public:
- InvalidOption4ClientFqdnDomainName(const char* file, size_t line,
+ InvalidOption4FqdnDomainName(const char* file, size_t line,
const char* what) :
isc::Exception(file, line, what) {}
};
/// where:
/// - N flag specifies whether server should (0) or should not (1) perform DNS
/// Update,
-/// - E flag specifies encoding of the Domain Name field. If this flag is set to 1
-/// it indicates canonical wire format without compression. 0 indicates the deprecated
-/// ASCII format.
+/// - E flag specifies encoding of the Domain Name field. If this flag is set
+/// to 1 it indicates canonical wire format without compression. 0 indicates
+/// the deprecated ASCII format.
/// - O flag is set by the server to indicate that it has overridden client's
/// preference set with the S bit.
/// - S flag specifies whether server should (1) or should not (0) perform
/// at the end of their wire representation (or lack of dot at the end, in
/// case of ASCII encoding). It is also accepted to create an instance of
/// this option which has empty domain-name. Clients use empty domain-names
-/// to indicate that server should generate complete fully qualified domain-name.
+/// to indicate that server should generate complete fully qualified
+/// domain-name.
///
/// @warning: The RFC4702 section 2.3.1 states that the clients and servers
/// should use character sets specified in RFC952, section 2.1 for ASCII-encoded
/// domain-names. This class doesn't detect the character set violation for
-/// ASCII-encoded domain-name. It could be implemented in the future but it is not
-/// important now for two reasons:
+/// ASCII-encoded domain-name. It could be implemented in the future but it is
+/// not important now for two reasons:
/// - ASCII encoding is deprecated
/// - clients SHOULD obey restrictions but if they don't, server may still
/// process the option
class Option4ClientFqdn : public Option {
public:
- /// @brief Enumeration holding different flags used in the Client
- /// FQDN %Option.
- enum Flag {
- FLAG_S = 0x01,
- FLAG_O = 0x02,
- FLAG_E = 0x04,
- FLAG_N = 0x08
- };
+ ///
+ /// @name A set of constants used to identify and set bits in the flags field
+ //@{
+ static const uint8_t FLAG_S = 0x01; ///< Bit S
+ static const uint8_t FLAG_O = 0x02; ///< Bit O
+ static const uint8_t FLAG_E = 0x04; ///< Bit E
+ static const uint8_t FLAG_N = 0x08; ///< Bit N
+ //@}
+
+ /// @brief Mask which zeroes MBZ flag bits.
+ static const uint8_t FLAG_MASK = 0xF;
/// @brief Represents the value of one of the RCODE1 or RCODE2 fields.
///
FULL
};
- /// @brief Mask which zeroes MBZ flag bits.
- static const uint8_t FLAG_MASK = 0xF;
-
- /// @brief The size of the fixed fields within DHCPv4 Client Fqdn %Option.
+ /// @brief The size in bytes of the fixed fields within DHCPv4 Client Fqdn
+ /// %Option.
///
/// The fixed fields are:
/// - Flags
/// @brief Constructor, creates option instance using flags and domain name.
///
- /// This constructor is used to create instance of the option which will be
- /// included in outgoing messages.
+ /// This constructor is used to create an instance of the option which will
+ /// be included in outgoing messages.
///
- /// @param flag a combination of flags to be stored in flags field.
+ /// @param flags a combination of flags to be stored in flags field.
/// @param rcode @c Rcode object representing a value for RCODE1 and RCODE2
- /// fields of the option. Both fields are assigned the same value encapsulated
- /// by the parameter.
+ /// fields of the option. Both fields are assigned the same value
+ /// encapsulated by the parameter.
/// @param domain_name a name to be stored in the domain-name field.
/// @param partial_domain_name indicates if the domain name is partial
/// (if true) or full (false).
- explicit Option4ClientFqdn(const uint8_t flag,
+ /// @throw InvalidOption4FqdnFlags if value of the flags field is wrong.
+ /// @throw InvalidOption4FqdnDomainName if the domain-name is invalid.
+ explicit Option4ClientFqdn(const uint8_t flags,
const Rcode& rcode,
const std::string& domain_name,
const DomainNameType domain_name_type = FULL);
/// This constructor creates an instance of the option with empty
/// domain-name. This domain-name is marked partial.
///
- /// @param flag a combination of flags to be stored in flags field.
+ /// @param flags a combination of flags to be stored in flags field.
/// @param rcode @c Rcode object representing a value for RCODE1 and RCODE2
/// fields. Both fields are assigned the same value encapsulated by this
/// parameter.
- Option4ClientFqdn(const uint8_t flag, const Rcode& rcode);
+ /// @throw InvalidOption4FqdnFlags if value of the flags field is invalid.
+ Option4ClientFqdn(const uint8_t flags, const Rcode& rcode);
/// @brief Constructor, creates an option instance from part of the buffer.
///
///
/// @param first the lower bound of the buffer to create option from.
/// @param last the upper bound of the buffer to create option from.
+ /// @throw InvalidOption4FqdnFlags if value of the flags field is invalid.
+ /// @throw InvalidOption4FqdnDomainName if the domain-name carried by the
+ /// option is invalid.
+ /// @throw OutOfRange if the option is truncated.
explicit Option4ClientFqdn(OptionBufferConstIter first,
OptionBufferConstIter last);
/// @brief Checks if the specified flag of the DHCPv4 Client FQDN %Option
/// is set.
///
- /// @param flag an enum value specifying the flag to be checked.
+ /// @param flag A value specifying a bit within flags field to be checked.
+ /// It must be one of the following @c FLAG_S, @c FLAG_E, @c FLAG_O,
+ /// @c FLAG_N.
///
- /// @return true if the bit of the specified flag is set, false otherwise.
- bool getFlag(const Flag flag) const;
+ /// @return true if the bit of the specified flags bit is set, false
+ /// otherwise.
+ /// @throw InvalidOption4ClientFlags if specified flag which value is to be
+ /// returned is invalid (is not one of the FLAG_S, FLAG_N, FLAG_O).
+ bool getFlag(const uint8_t flag) const;
/// @brief Modifies the value of the specified DHCPv4 Client Fqdn %Option
/// flag.
///
- /// @param flag an enum value specifying the flag to be modified.
+ /// @param flag A value specifying a bit within flags field to be set. It
+ /// must be one of the following @c FLAG_S, @c FLAG_E, @c FLAG_O, @c FLAG_N.
/// @param set a boolean value which indicates whether flag should be
/// set (true), or cleared (false).
- void setFlag(const Flag flag, const bool set);
+ /// @throw InvalidOption4ClientFlags if specified flag which value is to be
+ /// set is invalid (is not one of the FLAG_S, FLAG_N, FLAG_O).
+ void setFlag(const uint8_t flag, const bool set);
/// @brief Sets the flag field value to 0.
void resetFlags();
/// @param domain_name domain name field value in the text format.
/// @param domain_name_type type of the domain name: partial or fully
/// qualified.
+ /// @throw InvalidOption4FqdnDomainName if the specified domain-name is
+ /// invalid.
void setDomainName(const std::string& domain_name,
const DomainNameType domain_name_type);
using namespace isc;
using namespace isc::dhcp;
-// Redefine option flags here as uint8_t. They will be used to initialize
-// elements of the arrays that are used in tests below. Note that use of
-// enum values defined in Option4ClientFqdn class may cause compilation issues
-// during uint8_t arrays initialization. That is because the underlying
-// integral type used to represent enums is larger than one byte.
-const uint8_t FLAG_S = 0x01;
-const uint8_t FLAG_O = 0x02;
-const uint8_t FLAG_E = 0x04;
-const uint8_t FLAG_N = 0x08;
-
// This test verifies that constructor accepts empty partial domain-name but
// does not accept empty fully qualified domain name.
TEST(Option4ClientFqdnTest, constructEmptyName) {
// Create an instance of the source option.
boost::scoped_ptr<Option4ClientFqdn> option;
ASSERT_NO_THROW(
- option.reset(new Option4ClientFqdn(FLAG_S | FLAG_E,
+ option.reset(new Option4ClientFqdn(Option4ClientFqdn::FLAG_S |
+ Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_SERVER(),
"",
Option4ClientFqdn::PARTIAL))
EXPECT_EQ(Option4ClientFqdn::PARTIAL, option->getDomainNameType());
// Constructor should not accept empty fully qualified domain name.
- EXPECT_THROW(Option4ClientFqdn(FLAG_S | FLAG_E,
+ EXPECT_THROW(Option4ClientFqdn(Option4ClientFqdn::FLAG_S |
+ Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_CLIENT(),
"",
Option4ClientFqdn::FULL),
- InvalidOption4ClientFqdnDomainName);
+ InvalidOption4FqdnDomainName);
// This check is similar to previous one, but using domain-name comprising
// a single space character. This should be treated as empty domain-name.
- EXPECT_THROW(Option4ClientFqdn(FLAG_S | FLAG_E,
+ EXPECT_THROW(Option4ClientFqdn(Option4ClientFqdn::FLAG_S |
+ Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_CLIENT(),
" ",
Option4ClientFqdn::FULL),
- InvalidOption4ClientFqdnDomainName);
+ InvalidOption4FqdnDomainName);
// Try different constructor.
ASSERT_NO_THROW(
- option.reset(new Option4ClientFqdn(FLAG_O | FLAG_E,
+ option.reset(new Option4ClientFqdn(Option4ClientFqdn::FLAG_O |
+ Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_SERVER()))
);
ASSERT_TRUE(option);
// Create an instance of the source option.
boost::scoped_ptr<Option4ClientFqdn> option;
ASSERT_NO_THROW(
- option.reset(new Option4ClientFqdn(FLAG_S | FLAG_E,
+ option.reset(new Option4ClientFqdn(Option4ClientFqdn::FLAG_S |
+ Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_SERVER(),
"myhost.example.com",
Option4ClientFqdn::FULL))
// Create an option with different parameters.
ASSERT_NO_THROW(
- option.reset(new Option4ClientFqdn(FLAG_O | FLAG_E,
+ option.reset(new Option4ClientFqdn(Option4ClientFqdn::FLAG_O |
+ Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_SERVER(),
"example",
Option4ClientFqdn::PARTIAL))
TEST(Option4ClientFqdnTest, constructFromWire) {
// The E flag sets the domain-name format to canonical.
const uint8_t in_data[] = {
- FLAG_S | FLAG_E, // flags
- 0, // RCODE1
- 0, // RCODE2
- 6, 109, 121, 104, 111, 115, 116, // myhost.
- 7, 101, 120, 97, 109, 112, 108, 101, // example.
- 3, 99, 111, 109, 0 // com.
+ Option4ClientFqdn::FLAG_S | Option4ClientFqdn::FLAG_E, // flags
+ 0, // RCODE1
+ 0, // RCODE2
+ 6, 109, 121, 104, 111, 115, 116, // myhost.
+ 7, 101, 120, 97, 109, 112, 108, 101, // example.
+ 3, 99, 111, 109, 0 // com.
};
size_t in_data_size = sizeof(in_data) / sizeof(in_data[0]);
OptionBuffer in_buf(in_data, in_data + in_data_size);
// is encoded in the ASCII format. The "dot" character at the end
// indicates that the domain-name is fully qualified.
const uint8_t in_data[] = {
- FLAG_S, // flags
+ Option4ClientFqdn::FLAG_S, // flags
0, // RCODE1
0, // RCODE2
109, 121, 104, 111, 115, 116, 46, // myhost.
// in canonical format is carried in the option.
TEST(Option4ClientFqdnTest, constructFromWireInvalidName) {
const uint8_t in_data[] = {
- FLAG_S | FLAG_E, // flags
- 0, // RCODE1
- 0, // RCODE2
- 6, 109, 121, 104, 111, 115, 116, // myhost.
- 7, 101, 120, 97, 109, 112, 108, 101, // example.
- 5, 99, 111, 109, 0 // com. (invalid label length 5)
+ Option4ClientFqdn::FLAG_S | Option4ClientFqdn::FLAG_E, // flags
+ 0, // RCODE1
+ 0, // RCODE2
+ 6, 109, 121, 104, 111, 115, 116, // myhost.
+ 7, 101, 120, 97, 109, 112, 108, 101, // example.
+ 5, 99, 111, 109, 0 // com. (invalid label length 5)
};
size_t in_data_size = sizeof(in_data) / sizeof(in_data[0]);
OptionBuffer in_buf(in_data, in_data + in_data_size);
- EXPECT_THROW(
- Option4ClientFqdn(in_buf.begin(), in_buf.end()),
- InvalidOption4ClientFqdnDomainName
- );
+ EXPECT_THROW(Option4ClientFqdn(in_buf.begin(), in_buf.end()),
+ InvalidOption4FqdnDomainName);
}
// This test verifies that exception is thrown when invalid domain-name
// in ASCII format is carried in the option.
TEST(Option4ClientFqdnTest, constructFromWireInvalidASCIIName) {
const uint8_t in_data[] = {
- FLAG_S, // flags
+ Option4ClientFqdn::FLAG_S, // flags
0, // RCODE1
0, // RCODE2
109, 121, 104, 111, 115, 116, 46, 46, // myhost.. (double dot!)
size_t in_data_size = sizeof(in_data) / sizeof(in_data[0]);
OptionBuffer in_buf(in_data, in_data + in_data_size);
- EXPECT_THROW(
- Option4ClientFqdn(in_buf.begin(), in_buf.end()),
- InvalidOption4ClientFqdnDomainName
- );
+ EXPECT_THROW(Option4ClientFqdn(in_buf.begin(), in_buf.end()),
+ InvalidOption4FqdnDomainName);
}
// This test verifies that the option in the on-wire format with partial
// domain-name encoded in canonical format is parsed correctly.
TEST(Option4ClientFqdnTest, constructFromWirePartial) {
const uint8_t in_data[] = {
- FLAG_N | FLAG_E, // flags
- 255, // RCODE1
- 255, // RCODE2
- 6, 109, 121, 104, 111, 115, 116 // myhost
+ Option4ClientFqdn::FLAG_N | Option4ClientFqdn:: FLAG_E, // flags
+ 255, // RCODE1
+ 255, // RCODE2
+ 6, 109, 121, 104, 111, 115, 116 // myhost
};
size_t in_data_size = sizeof(in_data) / sizeof(in_data[0]);
OptionBuffer in_buf(in_data, in_data + in_data_size);
TEST(Option4ClientFqdnTest, constructFromWirePartialASCII) {
// There is no "dot" character at the end, so the domain-name is partial.
const uint8_t in_data[] = {
- FLAG_N, // flags
+ Option4ClientFqdn::FLAG_N, // flags
255, // RCODE1
255, // RCODE2
109, 121, 104, 111, 115, 116, 46, // myhost.
// assignment test. If these asserts do not fail, we can create options
// for the assignment test, do not surround them with asserts and be sure
// they will not throw.
- ASSERT_NO_THROW(Option4ClientFqdn(FLAG_S | FLAG_E,
+ ASSERT_NO_THROW(Option4ClientFqdn(Option4ClientFqdn::FLAG_S |
+ Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_SERVER(),
"myhost.example.com",
Option4ClientFqdn::FULL));
- ASSERT_NO_THROW(Option4ClientFqdn(FLAG_N | FLAG_E,
+ ASSERT_NO_THROW(Option4ClientFqdn(Option4ClientFqdn::FLAG_N |
+ Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_SERVER(),
"myhost",
Option4ClientFqdn::PARTIAL));
// Create options with the same parameters as tested above.
// Create first option.
- Option4ClientFqdn option(FLAG_S | FLAG_E,
+ Option4ClientFqdn option(Option4ClientFqdn::FLAG_S |
+ Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_SERVER(),
"myhost.example.com",
Option4ClientFqdn::FULL);
ASSERT_EQ(Option4ClientFqdn::FULL, option.getDomainNameType());
// Create a second option.
- Option4ClientFqdn option2(FLAG_N | FLAG_E,
+ Option4ClientFqdn option2(Option4ClientFqdn::FLAG_N |
+ Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_SERVER(),
"myhost",
Option4ClientFqdn::PARTIAL);
EXPECT_FALSE(option2.getFlag(Option4ClientFqdn::FLAG_N));
EXPECT_EQ(option.getDomainName(), option2.getDomainName());
EXPECT_EQ(option.getDomainNameType(), option2.getDomainNameType());
+
+ // Make self-assignment.
+ ASSERT_NO_THROW(option2 = option2);
+ EXPECT_TRUE(option2.getFlag(Option4ClientFqdn::FLAG_S));
+ EXPECT_TRUE(option2.getFlag(Option4ClientFqdn::FLAG_E));
+ EXPECT_FALSE(option2.getFlag(Option4ClientFqdn::FLAG_O));
+ EXPECT_FALSE(option2.getFlag(Option4ClientFqdn::FLAG_N));
+ EXPECT_EQ(option.getDomainName(), option2.getDomainName());
+ EXPECT_EQ(option.getDomainNameType(), option2.getDomainNameType());
}
// This test verifies that constructor will throw an exception if invalid
flags = 0x18;
EXPECT_THROW(Option4ClientFqdn(flags, Option4ClientFqdn::RCODE_CLIENT(),
"myhost.example.com"),
- InvalidOption4ClientFqdnFlags);
+ InvalidOption4FqdnFlags);
// According to RFC 4702, section 2.1. if the N bit is set the S bit MUST
// be zero. If both are set, constructor is expected to throw.
flags = Option4ClientFqdn::FLAG_N | Option4ClientFqdn::FLAG_S;
EXPECT_THROW(Option4ClientFqdn(flags, Option4ClientFqdn::RCODE_CLIENT(),
"myhost.example.com"),
- InvalidOption4ClientFqdnFlags);
+ InvalidOption4FqdnFlags);
}
// This test verifies that constructor which parses option from on-wire format
// Create a buffer which holds flags field only. Set valid flag field at
// at first to make sure that constructor doesn't always throw an exception.
OptionBuffer in_buf(3, 0);
- in_buf[0] = FLAG_S;
+ in_buf[0] = Option4ClientFqdn::FLAG_S;
ASSERT_NO_THROW(Option4ClientFqdn(in_buf.begin(), in_buf.end()));
// Replace the flags with invalid value and verify that constructor throws
// appropriate exception.
- in_buf[0] = FLAG_N | FLAG_S;
+ in_buf[0] = Option4ClientFqdn::FLAG_N | Option4ClientFqdn::FLAG_S;
EXPECT_THROW(Option4ClientFqdn(in_buf.begin(), in_buf.end()),
- InvalidOption4ClientFqdnFlags);
+ InvalidOption4FqdnFlags);
}
// This test verifies that if invalid domain name is used the constructor
// First, check that constructor does not throw when valid domain name
// is specified. That way we eliminate the possibility that constructor
// always throws exception.
- ASSERT_NO_THROW(Option4ClientFqdn(FLAG_E, Option4ClientFqdn::RCODE_CLIENT(),
+ ASSERT_NO_THROW(Option4ClientFqdn(Option4ClientFqdn::FLAG_E,
+ Option4ClientFqdn::RCODE_CLIENT(),
"myhost.example.com"));
// Specify invalid domain name and expect that exception is thrown.
- EXPECT_THROW(Option4ClientFqdn(FLAG_E, Option4ClientFqdn::RCODE_CLIENT(),
+ EXPECT_THROW(Option4ClientFqdn(Option4ClientFqdn::FLAG_E,
+ Option4ClientFqdn::RCODE_CLIENT(),
"my...host.example.com"),
- InvalidOption4ClientFqdnDomainName);
+ InvalidOption4FqdnDomainName);
// Do the same test for the domain-name in ASCII format.
ASSERT_NO_THROW(Option4ClientFqdn(0, Option4ClientFqdn::RCODE_CLIENT(),
EXPECT_THROW(Option4ClientFqdn(0, Option4ClientFqdn::RCODE_CLIENT(),
"my...host.example.com"),
- InvalidOption4ClientFqdnDomainName);
+ InvalidOption4FqdnDomainName);
}
// This test verifies that getFlag throws an exception if flag value other
-// than explicitly defined in the Option4ClientFqdn::Flag is spcified.
+// than N, E, O, S was specified.
TEST(Option4ClientFqdnTest, getFlag) {
boost::scoped_ptr<Option4ClientFqdn> option;
ASSERT_NO_THROW(
- option.reset(new Option4ClientFqdn(FLAG_E,
+ option.reset(new Option4ClientFqdn(Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_CLIENT(),
"myhost.example.com"))
);
ASSERT_TRUE(option);
- // The 0x3 is a valid enumerator value (even though it is not explicitly
- // included in the Option4ClientFqdn::Flag definition). The getFlag()
- // function should not accept it. Only explicit values are accepted.
- EXPECT_THROW(option->getFlag(static_cast<Option4ClientFqdn::Flag>(0x3)),
- InvalidOption4ClientFqdnFlags);
+ // The value of 0x3 (binary 0011) is invalid because it specifies two bits
+ // in the flags field which value is to be checked.
+ EXPECT_THROW(option->getFlag(0x3), InvalidOption4FqdnFlags);
}
// This test verifies that flags can be modified and that incorrect flags
// Set S = 1, this should throw exception because S and N must not
// be set in the same time.
ASSERT_THROW(option->setFlag(Option4ClientFqdn::FLAG_S, true),
- InvalidOption4ClientFqdnFlags);
+ InvalidOption4FqdnFlags);
// Set E = 0
ASSERT_NO_THROW(option->setFlag(Option4ClientFqdn::FLAG_N, false));
// Set N = 1, this should result in exception because S = 1
ASSERT_THROW(option->setFlag(Option4ClientFqdn::FLAG_N, true),
- InvalidOption4ClientFqdnFlags);
+ InvalidOption4FqdnFlags);
// Set O = 0
ASSERT_NO_THROW(option->setFlag(Option4ClientFqdn::FLAG_O, false));
// Try out of bounds settings.
uint8_t flags = 0;
- ASSERT_THROW(option->setFlag(static_cast<Option4ClientFqdn::Flag>(flags),
- true),
- InvalidOption4ClientFqdnFlags);
+ ASSERT_THROW(option->setFlag(flags, true), InvalidOption4FqdnFlags);
flags = 0x18;
- ASSERT_THROW(option->setFlag(static_cast<Option4ClientFqdn::Flag>(flags),
- true),
- InvalidOption4ClientFqdnFlags);
+ ASSERT_THROW(option->setFlag(flags, true), InvalidOption4FqdnFlags);
}
// This test verifies that flags field of the option is set to 0 when resetFlags
TEST(Option4ClientFqdnTest, resetFlags) {
boost::scoped_ptr<Option4ClientFqdn> option;
ASSERT_NO_THROW(
- option.reset(new Option4ClientFqdn(FLAG_S | FLAG_O | FLAG_E,
+ option.reset(new Option4ClientFqdn(Option4ClientFqdn::FLAG_S |
+ Option4ClientFqdn::FLAG_O |
+ Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_CLIENT(),
"myhost.example.com",
Option4ClientFqdn::FULL))
TEST(Option4ClientFqdnTest, setDomainName) {
boost::scoped_ptr<Option4ClientFqdn> option;
ASSERT_NO_THROW(
- option.reset(new Option4ClientFqdn(FLAG_S | FLAG_E,
+ option.reset(new Option4ClientFqdn(Option4ClientFqdn::FLAG_S |
+ Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_SERVER(),
"myhost.example.com",
Option4ClientFqdn::FULL))
// Fully qualified domain-names must not be empty.
EXPECT_THROW(option->setDomainName("", Option4ClientFqdn::FULL),
- InvalidOption4ClientFqdnDomainName);
+ InvalidOption4FqdnDomainName);
EXPECT_THROW(option->setDomainName(" ", Option4ClientFqdn::FULL),
- InvalidOption4ClientFqdnDomainName);
+ InvalidOption4FqdnDomainName);
}
// This test verifies that current domain-name can be reset to empty one.
TEST(Option4ClientFqdnTest, resetDomainName) {
boost::scoped_ptr<Option4ClientFqdn> option;
ASSERT_NO_THROW(
- option.reset(new Option4ClientFqdn(FLAG_S | FLAG_E,
+ option.reset(new Option4ClientFqdn(Option4ClientFqdn::FLAG_S |
+ Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_CLIENT(),
"myhost.example.com",
Option4ClientFqdn::FULL))
// This test verifies on-wire format of the option is correctly created.
TEST(Option4ClientFqdnTest, pack) {
// Create option instance. Check that constructor doesn't throw.
- const uint8_t flags = FLAG_S | FLAG_E;
+ const uint8_t flags = Option4ClientFqdn::FLAG_S | Option4ClientFqdn::FLAG_E;
boost::scoped_ptr<Option4ClientFqdn> option;
ASSERT_NO_THROW(
option.reset(new Option4ClientFqdn(flags,
// Prepare reference data.
const uint8_t ref_data[] = {
- 81, 23, // header
- FLAG_S | FLAG_E, // flags
- 0, // RCODE1
- 0, // RCODE2
- 6, 109, 121, 104, 111, 115, 116, // myhost.
- 7, 101, 120, 97, 109, 112, 108, 101, // example.
- 3, 99, 111, 109, 0 // com.
+ 81, 23, // header
+ Option4ClientFqdn::FLAG_S | Option4ClientFqdn::FLAG_E, // flags
+ 0, // RCODE1
+ 0, // RCODE2
+ 6, 109, 121, 104, 111, 115, 116, // myhost.
+ 7, 101, 120, 97, 109, 112, 108, 101, // example.
+ 3, 99, 111, 109, 0 // com.
};
size_t ref_data_size = sizeof(ref_data) / sizeof(ref_data[0]);
TEST(Option4ClientFqdnTest, packASCII) {
// Create option instance. Check that constructor doesn't throw.
- const uint8_t flags = FLAG_S;
+ const uint8_t flags = Option4ClientFqdn::FLAG_S;
boost::scoped_ptr<Option4ClientFqdn> option;
ASSERT_NO_THROW(
option.reset(new Option4ClientFqdn(flags,
// Prepare reference data.
const uint8_t ref_data[] = {
81, 23, // header
- FLAG_S, // flags
+ Option4ClientFqdn::FLAG_S, // flags
0, // RCODE1
0, // RCODE2
109, 121, 104, 111, 115, 116, 46, // myhost.
// is correctly created.
TEST(Option4ClientFqdnTest, packPartial) {
// Create option instance. Check that constructor doesn't throw.
- const uint8_t flags = FLAG_S | FLAG_E;
+ const uint8_t flags = Option4ClientFqdn::FLAG_S | Option4ClientFqdn::FLAG_E;
boost::scoped_ptr<Option4ClientFqdn> option;
ASSERT_NO_THROW(
option.reset(new Option4ClientFqdn(flags,
// Prepare reference data.
const uint8_t ref_data[] = {
- 81, 10, // header
- FLAG_S | FLAG_E, // flags
- 0, // RCODE1
- 0, // RCODE2
- 6, 109, 121, 104, 111, 115, 116 // myhost
+ 81, 10, // header
+ Option4ClientFqdn::FLAG_S | Option4ClientFqdn::FLAG_E, // flags
+ 0, // RCODE1
+ 0, // RCODE2
+ 6, 109, 121, 104, 111, 115, 116 // myhost
};
size_t ref_data_size = sizeof(ref_data) / sizeof(ref_data[0]);
// Create option instance. Check that constructor doesn't throw.
boost::scoped_ptr<Option4ClientFqdn> option;
ASSERT_NO_THROW(
- option.reset(new Option4ClientFqdn(FLAG_O | FLAG_E,
+ option.reset(new Option4ClientFqdn(Option4ClientFqdn::FLAG_O |
+ Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_CLIENT(),
"myhost",
Option4ClientFqdn::PARTIAL))
EXPECT_EQ(Option4ClientFqdn::PARTIAL, option->getDomainNameType());
const uint8_t in_data[] = {
- FLAG_S | FLAG_E, // flags
- 0, // RCODE1
- 0, // RCODE2
- 6, 109, 121, 104, 111, 115, 116, // myhost.
- 7, 101, 120, 97, 109, 112, 108, 101, // example.
- 3, 99, 111, 109, 0 // com.
+ Option4ClientFqdn::FLAG_S | Option4ClientFqdn::FLAG_E, // flags
+ 0, // RCODE1
+ 0, // RCODE2
+ 6, 109, 121, 104, 111, 115, 116, // myhost.
+ 7, 101, 120, 97, 109, 112, 108, 101, // example.
+ 3, 99, 111, 109, 0 // com.
};
size_t in_data_size = sizeof(in_data) / sizeof(in_data[0]);
OptionBuffer in_buf(in_data, in_data + in_data_size);
// Create option instance. Check that constructor doesn't throw.
boost::scoped_ptr<Option4ClientFqdn> option;
ASSERT_NO_THROW(
- option.reset(new Option4ClientFqdn(FLAG_O | FLAG_E,
+ option.reset(new Option4ClientFqdn(Option4ClientFqdn::FLAG_O |
+ Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_CLIENT(),
"myhost.example.com"))
);
EXPECT_EQ(Option4ClientFqdn::FULL, option->getDomainNameType());
const uint8_t in_data[] = {
- FLAG_S | FLAG_E, // flags
- 0, // RCODE1
- 0, // RCODE2
- 6, 109, 121, 104, 111, 115, 116 // myhost
+ Option4ClientFqdn::FLAG_S | Option4ClientFqdn::FLAG_E, // flags
+ 0, // RCODE1
+ 0, // RCODE2
+ 6, 109, 121, 104, 111, 115, 116 // myhost
};
size_t in_data_size = sizeof(in_data) / sizeof(in_data[0]);
OptionBuffer in_buf(in_data, in_data + in_data_size);
TEST(Option4ClientFqdnTest, unpackTruncated) {
boost::scoped_ptr<Option4ClientFqdn> option;
ASSERT_NO_THROW(
- option.reset(new Option4ClientFqdn(FLAG_O | FLAG_E,
+ option.reset(new Option4ClientFqdn(Option4ClientFqdn::FLAG_O |
+ Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_CLIENT()))
);
ASSERT_TRUE(option);
// toText method is correctly formatted.
TEST(Option4ClientFqdnTest, toText) {
// Create option instance. Check that constructor doesn't throw.
- uint8_t flags = FLAG_N | FLAG_O | FLAG_E;
+ uint8_t flags = Option4ClientFqdn::FLAG_N | Option4ClientFqdn::FLAG_O |
+ Option4ClientFqdn::FLAG_E;
boost::scoped_ptr<Option4ClientFqdn> option;
ASSERT_NO_THROW(
option.reset(new Option4ClientFqdn(flags,
// Create option instance. Check that constructor doesn't throw.
boost::scoped_ptr<Option4ClientFqdn> option;
ASSERT_NO_THROW(
- option.reset(new Option4ClientFqdn(FLAG_E,
+ option.reset(new Option4ClientFqdn(Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_CLIENT(),
"myhost.example.com"))
);
// Let's check that the size will change when domain name of a different
// size is used.
ASSERT_NO_THROW(
- option.reset(new Option4ClientFqdn(FLAG_E,
+ option.reset(new Option4ClientFqdn(Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_CLIENT(),
"example.com"))
);
EXPECT_EQ(18, option->len());
ASSERT_NO_THROW(
- option.reset(new Option4ClientFqdn(FLAG_E,
+ option.reset(new Option4ClientFqdn(Option4ClientFqdn::FLAG_E,
Option4ClientFqdn::RCODE_CLIENT(),
"myhost",
Option4ClientFqdn::PARTIAL))