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 Option6ClientFqdn class from the interface. This implementation
+/// uses b10-libdns classes to process FQDNs. At some point it may be
+/// desired to split b10-libdhcp++ from b10-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 Option6ClientFqdnImpl {
public:
+ /// Holds flags carried by the option.
uint8_t flags_;
+ /// 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.
Option6ClientFqdn::DomainNameType domain_name_type_;
- Option6ClientFqdnImpl(const uint8_t flag,
+ /// @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.
+ Option6ClientFqdnImpl(const uint8_t flags,
const std::string& domain_name,
const Option6ClientFqdn::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.
Option6ClientFqdnImpl(OptionBufferConstIter first,
OptionBufferConstIter last);
+ /// @brief Copy constructor.
+ ///
+ /// @param source An object being copied.
Option6ClientFqdnImpl(const Option6ClientFqdnImpl& source);
+ /// @brief Assignment operator.
+ ///
+ /// @param source An object which is being assigned.
Option6ClientFqdnImpl& operator=(const Option6ClientFqdnImpl& 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 Option6ClientFqdn::DomainNameType name_type);
- static void checkFlags(const uint8_t flags);
-
+ /// @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 InvalidFqdnOptionFlags if flags are invalid.
+ static void checkFlags(const uint8_t flags, const bool check_mbz);
+
+ /// @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);
};
Option6ClientFqdnImpl::
-Option6ClientFqdnImpl(const uint8_t flag,
+Option6ClientFqdnImpl(const uint8_t flags,
const std::string& domain_name,
const Option6ClientFqdn::DomainNameType name_type)
- : flags_(flag),
+ : flags_(flags),
domain_name_(),
domain_name_type_(name_type) {
- // Check if flags are correct.
- checkFlags(flags_);
+ // Check if flags are correct. Also check if MBZ bits are set.
+ checkFlags(flags_, true);
// Set domain name. It may throw an exception if domain name has wrong
// format.
setDomainName(domain_name, name_type);
Option6ClientFqdnImpl::Option6ClientFqdnImpl(OptionBufferConstIter first,
OptionBufferConstIter last) {
parseWireData(first, last);
- // Verify that flags value was correct.
- checkFlags(flags_);
+ // Verify that flags value was correct. Do not check if MBZ bits are
+ // set because we should ignore those bits in received message.
+ checkFlags(flags_, false);
}
Option6ClientFqdnImpl::
}
void
-Option6ClientFqdnImpl::checkFlags(const uint8_t flags) {
+Option6ClientFqdnImpl::checkFlags(const uint8_t flags, const bool check_mbz) {
// The Must Be Zero (MBZ) bits must not be set.
- if ((flags & ~Option6ClientFqdn::FLAG_MASK) != 0) {
+ if (check_mbz && ((flags & ~Option6ClientFqdn::FLAG_MASK) != 0)) {
isc_throw(InvalidFqdnOptionFlags,
"invalid DHCPv6 Client FQDN Option flags: 0x"
<< std::hex << static_cast<int>(flags) << std::dec);
// The domain-name may be empty.
if (std::distance(first, last) < Option6ClientFqdn::FLAG_FIELD_LEN) {
isc_throw(OutOfRange, "DHCPv6 Client FQDN Option ("
- << D6O_CLIENT_FQDN << ") is truncated");
+ << D6O_CLIENT_FQDN << ") is truncated. Minimal option"
+ << " size is " << Option6ClientFqdn::FLAG_FIELD_LEN
+ << ", got option with size " << std::distance(first, last));
}
// Parse flags
}
// Check new flags. If they are valid, apply them.
- Option6ClientFqdnImpl::checkFlags(new_flag);
+ Option6ClientFqdnImpl::checkFlags(new_flag, true);
impl_->flags_ = new_flag;
}