summaryrefslogtreecommitdiffstats
path: root/src/lib/dhcp/option_definition.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/dhcp/option_definition.h')
-rw-r--r--src/lib/dhcp/option_definition.h869
1 files changed, 869 insertions, 0 deletions
diff --git a/src/lib/dhcp/option_definition.h b/src/lib/dhcp/option_definition.h
new file mode 100644
index 0000000..a9316ac
--- /dev/null
+++ b/src/lib/dhcp/option_definition.h
@@ -0,0 +1,869 @@
+// Copyright (C) 2012-2021 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef OPTION_DEFINITION_H
+#define OPTION_DEFINITION_H
+
+#include <dhcp/option.h>
+#include <dhcp/option_data_types.h>
+#include <dhcp/option_space_container.h>
+#include <cc/stamped_element.h>
+#include <cc/user_context.h>
+
+#include <boost/multi_index/hashed_index.hpp>
+#include <boost/multi_index/mem_fun.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/sequenced_index.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/shared_ptr.hpp>
+#include <map>
+#include <string>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Exception to be thrown when invalid option value has been
+/// specified for a particular option definition.
+class InvalidOptionValue : public Exception {
+public:
+ InvalidOptionValue(const char* file, size_t line, const char* what) :
+ isc::Exception(file, line, what) { };
+};
+
+/// @brief Exception to be thrown when option definition is invalid.
+class MalformedOptionDefinition : public Exception {
+public:
+ MalformedOptionDefinition(const char* file, size_t line, const char* what) :
+ isc::Exception(file, line, what) { };
+};
+
+/// @brief Exception to be thrown when the particular option definition
+/// duplicates existing option definition.
+class DuplicateOptionDefinition : public Exception {
+public:
+ DuplicateOptionDefinition(const char* file, size_t line, const char* what) :
+ isc::Exception(file, line, what) { };
+};
+
+/// @brief Forward declaration to OptionDefinition.
+class OptionDefinition;
+
+/// @brief Pointer to option definition object.
+typedef boost::shared_ptr<OptionDefinition> OptionDefinitionPtr;
+
+/// @brief Forward declaration to OptionInt.
+///
+/// This forward declaration is needed to access the OptionInt class without
+/// having to include the option_int.h header file. It is required because
+/// this header includes libdhcp++.h, and including option_int.h would cause
+/// circular inclusion between libdhcp++.h, option_definition.h and
+/// option6_int.h.
+template<typename T>
+class OptionInt;
+
+/// @brief Forward declaration to OptionIntArray.
+///
+/// This forward declaration is needed to access the OptionIntArray class
+/// without having to include the option_int_array.h header file. It is
+/// required because this header includes libdhcp++.h, and including
+/// option_int_array.h would cause circular inclusion between libdhcp++.h,
+/// option_definition.h and option_int_array.h.
+template<typename T>
+class OptionIntArray;
+
+/// @brief Base class representing a DHCP option definition.
+///
+/// This is a base class representing a DHCP option definition, which describes
+/// the format of the option. In particular, it defines:
+/// - option name,
+/// - option code,
+/// - option space,
+/// - data fields order and their types,
+/// - sub options space that the particular option encapsulates.
+///
+/// The option type specifies the data type(s) which an option conveys. If
+/// this is a single value the option type points to the data type of the
+/// value. For example, DHCPv6 option 8 comprises a two-byte option code, a
+/// two-byte option length and two-byte field that carries a uint16 value
+/// (RFC 8415 - http://ietf.org/rfc/rfc8415.txt). In such a case, the option
+/// type is defined as "uint16". Length and string tuples are a length
+/// on one (DHCPv4) or two (DHCPv6) bytes followed by a string of
+/// the given length.
+///
+/// When the option has a more complex structure, the option type may be
+/// defined as "array", "record" or even "array of records".
+///
+/// Array types should be used when the option contains multiple contiguous
+/// data values of the same type laid. For example, DHCPv6 option 6 includes
+/// multiple fields holding uint16 codes of requested DHCPv6 options (RFC 8415).
+/// Such an option can be represented with this class by setting the option
+/// type to "uint16" and the array indicator (array_type) to true. The number
+/// of elements in the array is effectively unlimited (although it is actually
+/// limited by the maximal DHCPv6 option length).
+///
+/// Should the option comprise data fields of different types, the "record"
+/// option type is used. In such cases the data field types within the record
+/// are specified using \ref OptionDefinition::addRecordField.
+///
+/// When the OptionDefinition object has been successfully created, it can be
+/// queried to return the appropriate option factory function for the specified
+/// specified option format. There are a number of "standard" factory functions
+/// that cover well known (common) formats. If the particular format does not
+/// match any common format the generic factory function is returned.
+///
+/// The following data type strings are supported:
+/// - "empty" (option does not contain data fields)
+/// - "boolean"
+/// - "int8"
+/// - "int16"
+/// - "int32"
+/// - "uint8"
+/// - "uint16"
+/// - "uint32"
+/// - "ipv4-address" (IPv4 Address)
+/// - "ipv6-address" (IPv6 Address)
+/// - "ipv6-prefix" (IPv6 variable length prefix)
+/// - "psid" (PSID length / value)
+/// - "string"
+/// - "fqdn" (fully qualified name)
+/// - "tuple" (length and string)
+/// - "record" (set of data fields of different types)
+///
+/// @todo Extend the comment to describe "generic factories".
+/// @todo Extend this class with more factory functions.
+/// @todo Derive from UserContext without breaking the multi index.
+class OptionDefinition : public data::StampedElement {
+public:
+
+ /// List of fields within the record.
+ typedef std::vector<OptionDataType> RecordFieldsCollection;
+ /// Const iterator for record data fields.
+ typedef std::vector<OptionDataType>::const_iterator RecordFieldsConstIter;
+
+ /// @brief Constructor.
+ ///
+ /// @param name option name.
+ /// @param code option code.
+ /// @param space option space.
+ /// @param type option data type as string.
+ /// @param array_type array indicator, if true it indicates that the
+ /// option fields are the array.
+ explicit OptionDefinition(const std::string& name,
+ const uint16_t code,
+ const std::string& space,
+ const std::string& type,
+ const bool array_type = false);
+
+ /// @brief Constructor.
+ ///
+ /// @param name option name.
+ /// @param code option code.
+ /// @param space option space.
+ /// @param type option data type.
+ /// @param array_type array indicator, if true it indicates that the
+ /// option fields are the array.
+ explicit OptionDefinition(const std::string& name,
+ const uint16_t code,
+ const std::string& space,
+ const OptionDataType type,
+ const bool array_type = false);
+
+ /// @brief Constructor.
+ ///
+ /// This constructor sets the name of the option space that is
+ /// encapsulated by this option. The encapsulated option space
+ /// identifies sub-options that are carried within this option.
+ /// This constructor does not allow to set array indicator
+ /// because options comprising an array of data fields must
+ /// not be used with sub-options.
+ ///
+ /// @param name option name.
+ /// @param code option code.
+ /// @param space option space.
+ /// @param type option data type given as string.
+ /// @param encapsulated_space name of the option space being
+ /// encapsulated by this option.
+ explicit OptionDefinition(const std::string& name,
+ const uint16_t code,
+ const std::string& space,
+ const std::string& type,
+ const char* encapsulated_space);
+
+ /// @brief Constructor.
+ ///
+ /// This constructor sets the name of the option space that is
+ /// encapsulated by this option. The encapsulated option space
+ /// identifies sub-options that are carried within this option.
+ /// This constructor does not allow to set array indicator
+ /// because options comprising an array of data fields must
+ /// not be used with sub-options.
+ ///
+ /// @param name option name.
+ /// @param code option code.
+ /// @param space option space.
+ /// @param type option data type.
+ /// @param encapsulated_space name of the option space being
+ /// encapsulated by this option.
+ explicit OptionDefinition(const std::string& name,
+ const uint16_t code,
+ const std::string& space,
+ const OptionDataType type,
+ const char* encapsulated_space);
+
+ /// @brief Factory function creating an instance of the @c OptionDefinition.
+ ///
+ /// This function should be used to create an instance of the option
+ /// definition within a hooks library in cases when the library may be
+ /// unloaded before the object is destroyed. This ensures that the
+ /// ownership of the object by the Kea process is retained.
+ ///
+ /// @param name option name.
+ /// @param code option code.
+ /// @param space option space.
+ /// @param type option data type as string.
+ /// @param array_type array indicator, if true it indicates that the
+ /// option fields are the array.
+ ///
+ /// @return Pointer to the @c OptionDefinition instance.
+ static OptionDefinitionPtr create(const std::string& name,
+ const uint16_t code,
+ const std::string& space,
+ const std::string& type,
+ const bool array_type = false);
+
+ /// @brief Factory function creating an instance of the @c OptionDefinition.
+ ///
+ /// This function should be used to create an instance of the option
+ /// definition within a hooks library in cases when the library may be
+ /// unloaded before the object is destroyed. This ensures that the
+ /// ownership of the object by the Kea process is retained.
+ ///
+ /// @param name option name.
+ /// @param code option code.
+ /// @param space option space.
+ /// @param type option data type.
+ /// @param array_type array indicator, if true it indicates that the
+ /// option fields are the array.
+ ///
+ /// @return Pointer to the @c OptionDefinition instance.
+ static OptionDefinitionPtr create(const std::string& name,
+ const uint16_t code,
+ const std::string& space,
+ const OptionDataType type,
+ const bool array_type = false);
+
+ /// @brief Factory function creating an instance of the @c OptionDefinition.
+ ///
+ /// This function should be used to create an instance of the option
+ /// definition within a hooks library in cases when the library may be
+ /// unloaded before the object is destroyed. This ensures that the
+ /// ownership of the object by the Kea process is retained.
+ ///
+ /// @param name option name.
+ /// @param code option code.
+ /// @param space option space.
+ /// @param type option data type given as string.
+ /// @param encapsulated_space name of the option space being
+ /// encapsulated by this option.
+ ///
+ /// @return Pointer to the @c OptionDefinition instance.
+ static OptionDefinitionPtr create(const std::string& name,
+ const uint16_t code,
+ const std::string& space,
+ const std::string& type,
+ const char* encapsulated_space);
+
+ /// @brief Factory function creating an instance of the @c OptionDefinition.
+ ///
+ /// This function should be used to create an instance of the option
+ /// definition within a hooks library in cases when the library may be
+ /// unloaded before the object is destroyed. This ensures that the
+ /// ownership of the object by the Kea process is retained.
+ ///
+ /// @param name option name.
+ /// @param code option code.
+ /// @param space option space.
+ /// @param type option data type.
+ /// @param encapsulated_space name of the option space being
+ /// encapsulated by this option.
+ ///
+ /// @return Pointer to the @c OptionDefinition instance.
+ static OptionDefinitionPtr create(const std::string& name,
+ const uint16_t code,
+ const std::string& space,
+ const OptionDataType type,
+ const char* encapsulated_space);
+
+ /// @name Comparison functions and operators.
+ ///
+ //@{
+ /// @brief Check if option definition is equal to other.
+ ///
+ /// @param other Option definition to compare to.
+ ///
+ /// @return true if two option definitions are equal, false otherwise.
+ bool equals(const OptionDefinition& other) const;
+
+ /// @brief Equality operator.
+ ///
+ /// @param other Option definition to compare to.
+ ///
+ /// @return true if two option definitions are equal, false otherwise.
+ bool operator==(const OptionDefinition& other) const {
+ return (equals(other));
+ }
+
+ /// @brief Inequality operator.
+ ///
+ /// @param other Option definition to compare to.
+ ///
+ /// @return true if option definitions are not equal, false otherwise.
+ bool operator!=(const OptionDefinition& other) const {
+ return (!equals(other));
+ }
+ //@}
+
+ /// @brief Adds data field to the record.
+ ///
+ /// @param data_type_name name of the data type for the field.
+ ///
+ /// @throw isc::InvalidOperation if option type is not set to RECORD_TYPE.
+ /// @throw isc::BadValue if specified invalid data type.
+ void addRecordField(const std::string& data_type_name);
+
+ /// @brief Adds data field to the record.
+ ///
+ /// @param data_type data type for the field.
+ ///
+ /// @throw isc::InvalidOperation if option type is not set to RECORD_TYPE.
+ /// @throw isc::BadValue if specified invalid data type.
+ void addRecordField(const OptionDataType data_type);
+
+ /// @brief Return array type indicator.
+ ///
+ /// The method returns the bool value to indicate whether the option is a
+ /// a single value or an array of values.
+ ///
+ /// @return true if option comprises an array of values.
+ bool getArrayType() const { return (array_type_); }
+
+ /// @brief Return option code.
+ ///
+ /// @return option code.
+ uint16_t getCode() const { return (code_); }
+
+ /// @brief Return name of the encapsulated option space.
+ ///
+ /// @return name of the encapsulated option space.
+ std::string getEncapsulatedSpace() const {
+ return (encapsulated_space_);
+ }
+
+ /// @brief Return option name.
+ ///
+ /// @return option name.
+ std::string getName() const { return (name_); }
+
+ /// @brief Return list of record fields.
+ ///
+ /// @return list of record fields.
+ const RecordFieldsCollection& getRecordFields() const {
+ return (record_fields_);
+ }
+
+ /// @brief Returns option space name.
+ ///
+ /// @return Option space name.
+ std::string getOptionSpaceName() const {
+ return (option_space_name_);
+ }
+
+ /// @brief Return option data type.
+ ///
+ /// @return option data type.
+ OptionDataType getType() const { return (type_); };
+
+ /// @brief Returns const pointer to the user context
+ data::ConstElementPtr getContext() const {
+ return (user_context_.getContext());
+ }
+
+ /// @brief Sets user context.
+ /// @param ctx user context to be stored.
+ void setContext(const data::ConstElementPtr& ctx) {
+ user_context_.setContext(ctx);
+ }
+
+ /// @brief Merge unparse a user_context object.
+ ///
+ /// Add user-context to map, but only if defined. Omit if it was not.
+ /// Extract comment so it will be pretty-printed first.
+ ///
+ /// @param map A pointer to map where the user context will be unparsed.
+ void contextToElement(data::ElementPtr map) const {
+ user_context_.contextToElement(map);
+ }
+
+ /// @brief Check if the option definition is valid.
+ ///
+ /// Note that it is a responsibility of the code that created
+ /// the OptionDefinition object to validate that it is valid.
+ /// This function will not be called internally anywhere in this
+ /// class to verify that the option definition is valid. Using
+ /// invalid option definition to create an instance of the
+ /// DHCP option leads to undefined behavior.
+ ///
+ /// @throw MalformedOptionDefinition option definition is invalid.
+ void validate() const;
+
+ /// @brief Option factory.
+ ///
+ /// This function creates an instance of DHCP option using
+ /// provided chunk of buffer. This function may be used to
+ /// create option which is to be sent in the outgoing packet.
+ ///
+ /// @warning calling this function on invalid option definition
+ /// yields undefined behavior. Use \ref validate to test that
+ /// the option definition is valid.
+ ///
+ /// @param u option universe (V4 or V6).
+ /// @param type option type.
+ /// @param begin beginning of the option buffer.
+ /// @param end end of the option buffer.
+ ///
+ /// @return instance of the DHCP option.
+ /// @throw InvalidOptionValue if data for the option is invalid.
+ OptionPtr optionFactory(Option::Universe u, uint16_t type,
+ OptionBufferConstIter begin,
+ OptionBufferConstIter end) const;
+
+ /// @brief Option factory.
+ ///
+ /// This function creates an instance of DHCP option using
+ /// whole provided buffer. This function may be used to
+ /// create option which is to be sent in the outgoing packet.
+ ///
+ /// @warning calling this function on invalid option definition
+ /// yields undefined behavior. Use \ref validate to test that
+ /// the option definition is valid.
+ ///
+ /// @param u option universe (V4 or V6).
+ /// @param type option type.
+ /// @param buf option buffer.
+ ///
+ /// @return instance of the DHCP option.
+ /// @throw InvalidOptionValue if data for the option is invalid.
+ OptionPtr optionFactory(Option::Universe u, uint16_t type,
+ const OptionBuffer& buf = OptionBuffer()) const;
+
+ /// @brief Option factory.
+ ///
+ /// This function creates an instance of DHCP option using the vector
+ /// of strings which carry data values for option data fields.
+ /// The order of values in the vector corresponds to the order of data
+ /// fields in the option. The supplied string values are cast to
+ /// their actual data types which are determined based on the
+ /// option definition. If cast fails due to type mismatch, an exception
+ /// is thrown. This factory function can be used to create option
+ /// instance when user specified option value in the <b>comma separated
+ /// values</b> format in the configuration database. Provided string
+ /// must be tokenized into the vector of string values and this vector
+ /// can be supplied to this function.
+ ///
+ /// @warning calling this function on invalid option definition
+ /// yields undefined behavior. Use \ref validate to test that
+ /// the option definition is valid.
+ ///
+ /// @param u option universe (V4 or V6).
+ /// @param type option type.
+ /// @param values a vector of values to be used to set data for an option.
+ ///
+ /// @return instance of the DHCP option.
+ /// @throw InvalidOptionValue if data for the option is invalid.
+ OptionPtr optionFactory(Option::Universe u, uint16_t type,
+ const std::vector<std::string>& values) const;
+
+ /// @brief Factory to create option with address list.
+ ///
+ /// @param type option type.
+ /// @param begin iterator pointing to the beginning of the buffer
+ /// with a list of IPv4 addresses.
+ /// @param end iterator pointing to the end of the buffer with
+ /// a list of IPv4 addresses.
+ ///
+ /// @throw isc::OutOfRange if length of the provided option buffer
+ /// is not multiple of IPV4 address length.
+ static OptionPtr factoryAddrList4(uint16_t type,
+ OptionBufferConstIter begin,
+ OptionBufferConstIter end);
+
+ /// @brief Factory to create option with address list.
+ ///
+ /// @param type option type.
+ /// @param begin iterator pointing to the beginning of the buffer
+ /// with a list of IPv6 addresses.
+ /// @param end iterator pointing to the end of the buffer with
+ /// a list of IPv6 addresses.
+ ///
+ /// @throw isc::OutOfaRange if length of provided option buffer
+ /// is not multiple of IPV6 address length.
+ static OptionPtr factoryAddrList6(uint16_t type,
+ OptionBufferConstIter begin,
+ OptionBufferConstIter end);
+
+ /// @brief Empty option factory.
+ ///
+ /// @param u universe (V6 or V4).
+ /// @param type option type.
+ static OptionPtr factoryEmpty(Option::Universe u, uint16_t type);
+
+ /// @brief Factory to create generic option.
+ ///
+ /// @param u universe (V6 or V4).
+ /// @param type option type.
+ /// @param begin iterator pointing to the beginning of the buffer.
+ /// @param end iterator pointing to the end of the buffer.
+ static OptionPtr factoryGeneric(Option::Universe u, uint16_t type,
+ OptionBufferConstIter begin,
+ OptionBufferConstIter end);
+
+ /// @brief Factory for IA-type of option.
+ ///
+ /// @param type option type.
+ /// @param begin iterator pointing to the beginning of the buffer.
+ /// @param end iterator pointing to the end of the buffer.
+ ///
+ /// @throw isc::OutOfRange if provided option buffer is too short or
+ /// too long. Expected size is 12 bytes.
+ static OptionPtr factoryIA6(uint16_t type,
+ OptionBufferConstIter begin,
+ OptionBufferConstIter end);
+
+ /// @brief Factory for IAADDR-type of option.
+ ///
+ /// @param type option type.
+ /// @param begin iterator pointing to the beginning of the buffer.
+ /// @param end iterator pointing to the end of the buffer.
+ ///
+ /// @throw isc::OutOfRange if provided option buffer is too short or
+ /// too long. Expected size is 24 bytes.
+ static OptionPtr factoryIAAddr6(uint16_t type,
+ OptionBufferConstIter begin,
+ OptionBufferConstIter end);
+
+ /// @brief Factory for IAPREFIX-type of option.
+ ///
+ /// @param type option type.
+ /// @param begin iterator pointing to the beginning of the buffer.
+ /// @param end iterator pointing to the end of the buffer.
+ ///
+ /// @throw isc::OutOfRange if provided option buffer is too short.
+ /// Expected minimum size is 25 bytes.
+ static OptionPtr factoryIAPrefix6(uint16_t type,
+ OptionBufferConstIter begin,
+ OptionBufferConstIter end);
+
+ /// @brief Factory to create option with tuple list.
+ ///
+ /// @param u option universe (V4 or V6).
+ /// @param type option type.
+ /// @param begin iterator pointing to the beginning of the buffer
+ /// with a list of tuples.
+ /// @param end iterator pointing to the end of the buffer with
+ /// a list of tuples.
+ ///
+ /// @return instance of the DHCP option.
+ static OptionPtr factoryOpaqueDataTuples(Option::Universe u,
+ uint16_t type,
+ OptionBufferConstIter begin,
+ OptionBufferConstIter end);
+
+ /// @brief Factory function to create option with integer value.
+ ///
+ /// @param u universe (V4 or V6).
+ /// @param type option type.
+ /// @param encapsulated_space An option space being encapsulated by the
+ /// options created by this factory function. The options which belong to
+ /// encapsulated option space are sub options of this option.
+ /// @param begin iterator pointing to the beginning of the buffer.
+ /// @param end iterator pointing to the end of the buffer.
+ /// @tparam T type of the data field (must be one of the uintX_t or intX_t).
+ ///
+ /// @throw isc::OutOfRange if provided option buffer length is invalid.
+ template<typename T>
+ static OptionPtr factoryInteger(Option::Universe u, uint16_t type,
+ const std::string& encapsulated_space,
+ OptionBufferConstIter begin,
+ OptionBufferConstIter end) {
+ OptionPtr option(new OptionInt<T>(u, type, 0));
+ option->setEncapsulatedSpace(encapsulated_space);
+ option->unpack(begin, end);
+ return (option);
+ }
+
+ /// @brief Factory function to create option with array of integer values.
+ ///
+ /// @param u universe (V4 or V6).
+ /// @param type option type.
+ /// @param begin iterator pointing to the beginning of the buffer.
+ /// @param end iterator pointing to the end of the buffer.
+ /// @tparam T type of the data field (must be one of the uintX_t or intX_t).
+ ///
+ /// @throw isc::OutOfRange if provided option buffer length is invalid.
+ template<typename T>
+ static OptionPtr factoryIntegerArray(Option::Universe u,
+ uint16_t type,
+ OptionBufferConstIter begin,
+ OptionBufferConstIter end) {
+ OptionPtr option(new OptionIntArray<T>(u, type, begin, end));
+ return (option);
+ }
+
+private:
+
+ /// @brief Check if the option has format of CompressedFqdnList options.
+ bool haveCompressedFqdnListFormat() const;
+
+ /// @brief Factory function to create option with a compressed FQDN list.
+ ///
+ /// @param u universe (V4 or V6).
+ /// @param type option type.
+ /// @param begin iterator pointing to the beginning of the buffer.
+ /// @param end iterator pointing to the end of the buffer.
+ ///
+ /// @return instance of the DHCP option where FQDNs are uncompressed.
+ /// @throw InvalidOptionValue if data for the option is invalid.
+ OptionPtr factoryFqdnList(Option::Universe u,
+ OptionBufferConstIter begin,
+ OptionBufferConstIter end) const;
+
+ /// @brief Creates an instance of an option having special format.
+ ///
+ /// The option with special formats are encapsulated by the dedicated
+ /// classes derived from @c Option class. In particular these are:
+ /// - IA_NA
+ /// - IAADDR
+ /// - FQDN
+ /// - VIVSO.
+ ///
+ /// @param u A universe (V4 or V6).
+ /// @param begin beginning of the option buffer.
+ /// @param end end of the option buffer.
+ ///
+ /// @return An instance of the option having special format or NULL if
+ /// such an option can't be created because an option with the given
+ /// option code hasn't got the special format.
+ OptionPtr factorySpecialFormatOption(Option::Universe u,
+ OptionBufferConstIter begin,
+ OptionBufferConstIter end) const;
+
+ /// @brief Check if specified type matches option definition type.
+ ///
+ /// @return true if specified type matches option definition type.
+ inline bool haveType(const OptionDataType type) const {
+ return (type == type_);
+ }
+
+ /// @brief Check if specified type matches option definition space.
+ ///
+ /// @return true if specified type matches option definition space.
+ inline bool haveSpace(const std::string& space) const {
+ return (space == option_space_name_);
+ }
+
+ /// @brief Converts a string value to a boolean value.
+ ///
+ /// This function converts the value represented as string to a boolean
+ /// value. The following conversions are acceptable:
+ /// - "true" => true
+ /// - "false" => false
+ /// - "1" => true
+ /// - "0" => false
+ /// The first two conversions are case insensitive, so as conversions from
+ /// strings such as "TRUE", "trUE" etc. will be accepted. Note that the
+ /// only acceptable integer values, carried as strings are: "0" and "1".
+ /// For other values, e.g. "2", "3" etc. an exception will be thrown
+ /// during conversion.
+ ///
+ /// @param value_str Input value.
+ ///
+ /// @return boolean representation of the string specified as the parameter.
+ /// @throw isc::dhcp::BadDataTypeCast if failed to perform the conversion.
+ bool convertToBool(const std::string& value_str) const;
+
+ /// @brief Perform lexical cast of the value and validate its range.
+ ///
+ /// This function performs lexical cast of a string value to integer
+ /// value and checks if the resulting value is within a range of a
+ /// target type. The target type should be one of the supported
+ /// integer types. Hexadecimal input is supported.
+ ///
+ /// @param value_str input value given as string.
+ /// @tparam T target integer type for lexical cast.
+ ///
+ /// @return Integer value after conversion from the string.
+ /// @throw isc::dhcp::BadDataTypeCast if conversion was not successful.
+ template<typename T>
+ T lexicalCastWithRangeCheck(const std::string& value_str) const;
+
+ /// @brief Write the string value into the provided buffer.
+ ///
+ /// This method writes the given value to the specified buffer.
+ /// The provided string value may represent data of different types.
+ /// The actual data type is specified with the second argument.
+ /// Based on a value of this argument, this function will first
+ /// try to cast the string value to the particular data type and
+ /// if it is successful it will store the data in the buffer
+ /// in a binary format.
+ ///
+ /// @param u option universe (V4 or V6).
+ /// @param value string representation of the value to be written.
+ /// @param type the actual data type to be stored.
+ /// @param [in, out] buf buffer where the value is to be stored.
+ ///
+ /// @throw BadDataTypeCast if data write was unsuccessful.
+ void writeToBuffer(Option::Universe u, const std::string& value,
+ const OptionDataType type, OptionBuffer& buf) const;
+
+ /// Option name.
+ std::string name_;
+ /// Option code.
+ uint16_t code_;
+ /// Option data type.
+ OptionDataType type_;
+ /// Indicates whether option is a single value or array.
+ bool array_type_;
+ /// Name of the space being encapsulated by this option.
+ std::string encapsulated_space_;
+ /// Collection of data fields within the record.
+ RecordFieldsCollection record_fields_;
+ /// User context
+ data::UserContext user_context_;
+ /// Option space name
+ std::string option_space_name_;
+};
+
+
+/// @brief Multi index container for DHCP option definitions.
+///
+/// This container allows to search for DHCP option definition
+/// using two indexes:
+/// - sequenced: used to access elements in the order they have
+/// been added to the container
+/// - option code: used to search definitions of options
+/// with a specified option code (aka option type).
+/// Note that this container can hold multiple options with the
+/// same code. For this reason, the latter index can be used to
+/// obtain a range of options for a particular option code.
+///
+/// @todo: need an index to search options using option space name
+/// once option spaces are implemented.
+typedef boost::multi_index_container<
+ // Container comprises elements of OptionDefinition type.
+ OptionDefinitionPtr,
+ // Here we start enumerating various indexes.
+ boost::multi_index::indexed_by<
+ // Sequenced index allows accessing elements in the same way
+ // as elements in std::list. Sequenced is an index #0.
+ boost::multi_index::sequenced<>,
+ // Start definition of index #1.
+ boost::multi_index::hashed_non_unique<
+ // Use option type as the index key. The type is held
+ // in OptionDefinition object so we have to call
+ // OptionDefinition::getCode to retrieve this key
+ // for each element. The option code is non-unique so
+ // multiple elements with the same option code can
+ // be returned by this index.
+ boost::multi_index::const_mem_fun<
+ OptionDefinition,
+ uint16_t,
+ &OptionDefinition::getCode
+ >
+ >,
+ // Start definition of index #2
+ boost::multi_index::hashed_non_unique<
+ // Use option name as the index key. This value is
+ // returned by the @c OptionDefinition::getName
+ // method.
+ boost::multi_index::const_mem_fun<
+ OptionDefinition,
+ std::string,
+ &OptionDefinition::getName
+ >
+ >,
+ // Start definition of index #3
+ boost::multi_index::ordered_non_unique<
+ // Use option definition modification time as the index key.
+ // This value is returned by the BaseStampedElement::getModificationTime
+ boost::multi_index::const_mem_fun<
+ data::BaseStampedElement,
+ boost::posix_time::ptime,
+ &data::StampedElement::getModificationTime
+ >
+ >,
+ // Start definition of index #4.
+ // Use StampedElement::getId as a key.
+ boost::multi_index::hashed_non_unique<
+ boost::multi_index::tag<OptionIdIndexTag>,
+ boost::multi_index::const_mem_fun<data::BaseStampedElement, uint64_t,
+ &data::BaseStampedElement::getId>
+ >
+ >
+> OptionDefContainer;
+
+/// Pointer to an option definition container.
+typedef boost::shared_ptr<OptionDefContainer> OptionDefContainerPtr;
+
+/// Container that holds option definitions for various option spaces.
+typedef std::map<std::string, OptionDefContainerPtr> OptionDefContainers;
+
+/// Container that holds various vendor option containers
+typedef std::map<uint32_t, OptionDefContainerPtr> VendorOptionDefContainers;
+
+/// Type of the index #1 - option type.
+typedef OptionDefContainer::nth_index<1>::type OptionDefContainerTypeIndex;
+/// Pair of iterators to represent the range of options definitions
+/// having the same option type value. The first element in this pair
+/// represents the beginning of the range, the second element
+/// represents the end.
+typedef std::pair<OptionDefContainerTypeIndex::const_iterator,
+ OptionDefContainerTypeIndex::const_iterator> OptionDefContainerTypeRange;
+
+/// Type of the index #2 - option name.
+typedef OptionDefContainer::nth_index<2>::type OptionDefContainerNameIndex;
+/// Pair of iterators to represent the range of options definitions
+/// having the same option name. The first element in this pair
+/// represents the beginning of the range, the second element
+/// represents the end.
+typedef std::pair<OptionDefContainerNameIndex::const_iterator,
+ OptionDefContainerNameIndex::const_iterator> OptionDefContainerNameRange;
+
+/// Base type of option definition space container.
+typedef OptionSpaceContainer<
+ OptionDefContainer, OptionDefinitionPtr, std::string
+> BaseOptionDefSpaceContainer;
+
+/// @brief Class of option definition space container.
+class OptionDefSpaceContainer : public BaseOptionDefSpaceContainer {
+public:
+
+ /// @brief Adds a new option definition to the container.
+ ///
+ /// The option definition already contains the option space.
+ ///
+ /// @note: this method hides the parent one so it becomes hard to get
+ /// a mismatch between the option definition and the space container.
+ ///
+ /// @param def reference to the option definition being added.
+ void addItem(const OptionDefinitionPtr& def) {
+ BaseOptionDefSpaceContainer::addItem(def, def->getOptionSpaceName());
+ }
+};
+
+} // namespace isc::dhcp
+} // namespace isc
+
+#endif // OPTION_DEFINITION_H