BIND 10 trac2312, updated. 863da09e4d4ef50693860dd95948ae5171ba5116 [2312] Implemented toText method for custom options.
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Nov 28 09:02:29 UTC 2012
The branch, trac2312 has been updated
via 863da09e4d4ef50693860dd95948ae5171ba5116 (commit)
via ff2167388ff8a86dfdae23fbd147602b102b0319 (commit)
from 2dd98a113773481b77ca0600c1d1028e2b5fdd72 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 863da09e4d4ef50693860dd95948ae5171ba5116
Author: Marcin Siodelski <marcin at isc.org>
Date: Wed Nov 28 10:02:18 2012 +0100
[2312] Implemented toText method for custom options.
commit ff2167388ff8a86dfdae23fbd147602b102b0319
Author: Marcin Siodelski <marcin at isc.org>
Date: Tue Nov 27 21:53:54 2012 +0100
[2312] Implemented OptionCustom::toText() function.
-----------------------------------------------------------------------
Summary of changes:
src/lib/dhcp/option_custom.cc | 123 ++++++++++++++---
src/lib/dhcp/option_custom.h | 9 ++
src/lib/dhcp/option_data_types.cc | 69 ++++++++++
src/lib/dhcp/option_data_types.h | 50 ++++++-
src/lib/dhcp/option_definition.cc | 272 +++++++++++++++++--------------------
src/lib/dhcp/option_definition.h | 111 +++++----------
6 files changed, 387 insertions(+), 247 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/dhcp/option_custom.cc b/src/lib/dhcp/option_custom.cc
index 6697587..bffadd2 100644
--- a/src/lib/dhcp/option_custom.cc
+++ b/src/lib/dhcp/option_custom.cc
@@ -15,6 +15,7 @@
#include <dhcp/libdhcp++.h>
#include <dhcp/option_data_types.h>
#include <dhcp/option_custom.h>
+#include <util/encode/hex.h>
namespace isc {
namespace dhcp {
@@ -144,6 +145,62 @@ OptionCustom::createBuffers() {
std::swap(buffers_, buffers);
}
+std::string
+OptionCustom::dataFieldToText(const OptionDataType data_type,
+ const uint32_t index) const {
+ std::ostringstream tmp;
+
+ // Get the value of the data field.
+ switch (data_type) {
+ case OPT_BINARY_TYPE:
+ tmp << util::encode::encodeHex(readBinary(index));
+ break;
+ case OPT_BOOLEAN_TYPE:
+ tmp << (readBoolean(index) ? "true" : "false");
+ break;
+ case OPT_INT8_TYPE:
+ tmp << readInteger<int8_t>(index);
+ break;
+ case OPT_INT16_TYPE:
+ tmp << readInteger<int16_t>(index);
+ break;
+ case OPT_INT32_TYPE:
+ tmp << readInteger<int32_t>(index);
+ break;
+ case OPT_UINT8_TYPE:
+ tmp << readInteger<uint8_t>(index);
+ break;
+ case OPT_UINT16_TYPE:
+ tmp << readInteger<uint16_t>(index);
+ break;
+ case OPT_UINT32_TYPE:
+ tmp << readInteger<uint32_t>(index);
+ break;
+ case OPT_IPV4_ADDRESS_TYPE:
+ case OPT_IPV6_ADDRESS_TYPE:
+ {
+ asiolink::IOAddress address("127.0.0.1");
+ readAddress(index, address);
+ tmp << address.toText();
+ break;
+ }
+ case OPT_STRING_TYPE:
+ {
+ std::string s;
+ readString(index, s);
+ tmp << s;
+ break;
+ }
+ default:
+ ;
+ }
+
+ // Append data field type in brackets.
+ tmp << " ( " << OptionDataTypeUtil::getDataTypeName(data_type) << " ) ";
+
+ return (tmp.str());
+}
+
void
OptionCustom::pack4(isc::util::OutputBuffer& buf) {
if (len() > 255) {
@@ -242,20 +299,57 @@ OptionCustom::len() {
return (length);
}
-std::string OptionCustom::toText(int /* =0 */ ) {
+void OptionCustom::setData(const OptionBufferConstIter first,
+ const OptionBufferConstIter last) {
+ // We will copy entire option buffer, so we have to resize data_.
+ data_.resize(std::distance(first, last));
+ std::copy(first, last, data_.begin());
+
+ // Chop the data_ buffer into set of buffers that represent
+ // option fields data.
+ createBuffers();
+}
+
+std::string OptionCustom::toText(int indent /* = 0 */ ) {
std::stringstream tmp;
- /* for (int i = 0; i < indent; i++)
+ for (int i = 0; i < indent; ++i)
tmp << " ";
- tmp << "type=" << type_ << ", len=" << len()-getHeaderLen() << ": ";
+ tmp << "type=" << type_ << ", len=" << len()-getHeaderLen()
+ << ", data fields:" << std::endl;
- for (unsigned int i = 0; i < data_.size(); i++) {
- if (i) {
- tmp << ":";
+ OptionDataType data_type = definition_.getType();
+ if (data_type == OPT_RECORD_TYPE) {
+ const OptionDefinition::RecordFieldsCollection& fields =
+ definition_.getRecordFields();
+
+ // For record types we iterate over fields defined in
+ // option definition and match the appropriate buffer
+ // with them.
+ for (OptionDefinition::RecordFieldsConstIter field = fields.begin();
+ field != fields.end(); ++field) {
+ for (int j = 0; j < indent + 2; ++j) {
+ tmp << " ";
+ }
+ tmp << "#" << distance(fields.begin(), field) << " "
+ << dataFieldToText(*field, distance(fields.begin(), field))
+ << std::endl;
+ }
+ } else {
+ // For non-record types we iterate over all buffers
+ // and print the data type set globally for an option
+ // definition. We take the same code path for arrays
+ // and non-arrays as they only differ in such a way that
+ // non-arrays have just single data field.
+ for (unsigned int i = 0; i < getDataFieldsNum(); ++i) {
+ for (int j = 0; j < indent + 2; ++j) {
+ tmp << " ";
+ }
+ tmp << "#" << i << " "
+ << dataFieldToText(definition_.getType(), i)
+ << std::endl;
}
- tmp << setfill('0') << setw(2) << hex
- << static_cast<unsigned short>(data_[i]);
}
// print suboptions
@@ -263,20 +357,9 @@ std::string OptionCustom::toText(int /* =0 */ ) {
opt != options_.end();
++opt) {
tmp << (*opt).second->toText(indent+2);
- } */
+ }
return tmp.str();
}
-void OptionCustom::setData(const OptionBufferConstIter first,
- const OptionBufferConstIter last) {
- // We will copy entire option buffer, so we have to resize data_.
- data_.resize(std::distance(first, last));
- std::copy(first, last, data_.begin());
-
- // Chop the data_ buffer into set of buffers that represent
- // option fields data.
- createBuffers();
-}
-
} // end of isc::dhcp namespace
} // end of isc namespace
diff --git a/src/lib/dhcp/option_custom.h b/src/lib/dhcp/option_custom.h
index 10b2b79..094466e 100644
--- a/src/lib/dhcp/option_custom.h
+++ b/src/lib/dhcp/option_custom.h
@@ -198,6 +198,15 @@ private:
/// @brief Create collection of buffers representing data field values.
void createBuffers();
+ /// @brief Return a text representation of a data field.
+ ///
+ /// @param data_type data type of a field.
+ /// @param index data field buffer index within a custom option.
+ ///
+ /// @return text representation of a data field.
+ std::string dataFieldToText(const OptionDataType data_type,
+ const uint32_t index) const;
+
/// Option definition used to create an option.
OptionDefinition definition_;
diff --git a/src/lib/dhcp/option_data_types.cc b/src/lib/dhcp/option_data_types.cc
index 146b109..866f275 100644
--- a/src/lib/dhcp/option_data_types.cc
+++ b/src/lib/dhcp/option_data_types.cc
@@ -18,6 +18,54 @@
namespace isc {
namespace dhcp {
+OptionDataTypeUtil::OptionDataTypeUtil() {
+ data_types_["empty"] = OPT_EMPTY_TYPE;
+ data_types_["binary"] = OPT_BINARY_TYPE;
+ data_types_["boolean"] = OPT_BOOLEAN_TYPE;
+ data_types_["int8"] = OPT_INT8_TYPE;
+ data_types_["int16"] = OPT_INT16_TYPE;
+ data_types_["int32"] = OPT_INT32_TYPE;
+ data_types_["uint8"] = OPT_UINT8_TYPE;
+ data_types_["uint16"] = OPT_UINT16_TYPE;
+ data_types_["uint32"] = OPT_UINT32_TYPE;
+ data_types_["ipv4-address"] = OPT_IPV4_ADDRESS_TYPE;
+ data_types_["ipv6-address"] = OPT_IPV6_ADDRESS_TYPE;
+ data_types_["string"] = OPT_STRING_TYPE;
+ data_types_["fqdn"] = OPT_FQDN_TYPE;
+ data_types_["record"] = OPT_RECORD_TYPE;
+
+ data_type_names_[OPT_EMPTY_TYPE] = "empty";
+ data_type_names_[OPT_BINARY_TYPE] = "binary";
+ data_type_names_[OPT_BOOLEAN_TYPE] = "boolean";
+ data_type_names_[OPT_INT8_TYPE] = "int8";
+ data_type_names_[OPT_INT16_TYPE] = "int16";
+ data_type_names_[OPT_INT32_TYPE] = "int32";
+ data_type_names_[OPT_UINT8_TYPE] = "uint8";
+ data_type_names_[OPT_UINT16_TYPE] = "uint16";
+ data_type_names_[OPT_UINT32_TYPE] = "uint32";
+ data_type_names_[OPT_IPV4_ADDRESS_TYPE] = "ipv4-address";
+ data_type_names_[OPT_IPV6_ADDRESS_TYPE] = "ipv6-address";
+ data_type_names_[OPT_STRING_TYPE] = "string";
+ data_type_names_[OPT_FQDN_TYPE] = "fqdn";
+ data_type_names_[OPT_RECORD_TYPE] = "record";
+ data_type_names_[OPT_UNKNOWN_TYPE] = "unknown";
+}
+
+OptionDataType
+OptionDataTypeUtil::getDataType(const std::string& data_type) {
+ return (OptionDataTypeUtil::instance().getDataTypeImpl(data_type));
+}
+
+OptionDataType
+OptionDataTypeUtil::getDataTypeImpl(const std::string& data_type) const {
+ std::map<std::string, OptionDataType>::const_iterator data_type_it =
+ data_types_.find(data_type);
+ if (data_type_it != data_types_.end()) {
+ return (data_type_it->second);
+ }
+ return (OPT_UNKNOWN_TYPE);
+}
+
int
OptionDataTypeUtil::getDataTypeLen(const OptionDataType data_type) {
switch (data_type) {
@@ -41,6 +89,27 @@ OptionDataTypeUtil::getDataTypeLen(const OptionDataType data_type) {
return (0);
}
+const std::string&
+OptionDataTypeUtil::getDataTypeName(const OptionDataType data_type) {
+ return (OptionDataTypeUtil::instance().getDataTypeNameImpl(data_type));
+}
+
+const std::string&
+OptionDataTypeUtil::getDataTypeNameImpl(const OptionDataType data_type) const {
+ std::map<OptionDataType, std::string>::const_iterator data_type_it =
+ data_type_names_.find(data_type);
+ if (data_type_it != data_type_names_.end()) {
+ return (data_type_it->second);
+ }
+ return (data_type_names_.find(OPT_UNKNOWN_TYPE)->second);
+}
+
+OptionDataTypeUtil&
+OptionDataTypeUtil::instance() {
+ static OptionDataTypeUtil instance;
+ return (instance);
+}
+
void
OptionDataTypeUtil::readAddress(const std::vector<uint8_t>& buf,
const short family,
diff --git a/src/lib/dhcp/option_data_types.h b/src/lib/dhcp/option_data_types.h
index d227749..f5efa0f 100644
--- a/src/lib/dhcp/option_data_types.h
+++ b/src/lib/dhcp/option_data_types.h
@@ -174,10 +174,22 @@ struct OptionDataTypeTraits<std::string> {
static const OptionDataType type = OPT_STRING_TYPE;
};
-/// @brief Utility class to write/read data to/from a buffer.
+/// @brief Utility class for option data types.
class OptionDataTypeUtil {
public:
+ /// @brief Return option data type from its name.
+ ///
+ /// @param data_type data type name.
+ /// @return option data type.
+ static OptionDataType getDataType(const std::string& data_type);
+
+ /// @brief Return option data type name from the data type enumerator.
+ ///
+ /// @param data_type option data type.
+ /// @return option data type name.
+ static const std::string& getDataTypeName(const OptionDataType data_type);
+
/// @brief Get data type buffer length.
///
/// This functionm returs the size of a particular data type.
@@ -312,7 +324,43 @@ public:
/// @param [out] buf output buffer.
static void writeString(const std::string& value,
std::vector<uint8_t>& buf);
+private:
+
+ /// The container holding mapping of data type names to
+ /// data types enumerator.
+ std::map<std::string, OptionDataType> data_types_;
+
+ /// The container holding mapping of data types to data
+ /// type names.
+ std::map<OptionDataType, std::string> data_type_names_;
+
+ /// @brief Private constructor.
+ ///
+ /// This constructor is private because this class should
+ /// be used as singleton (through static public functions).
+ OptionDataTypeUtil();
+
+ /// @brief Return instance of OptionDataTypeUtil
+ ///
+ /// This function is used by some of the public static functions
+ /// to create an instance of OptionDataTypeUtil class.
+ /// When instance is called it calls the class'es constructor
+ /// and initializes some of the private data members.
+ ///
+ /// @return instance of OptionDataTypeUtil singleton.
+ static OptionDataTypeUtil& instance();
+ /// @brief Return option data type from its name.
+ ///
+ /// @param data_type data type name.
+ /// @return option data type.
+ OptionDataType getDataTypeImpl(const std::string& data_type) const;
+
+ /// @brief Return option data type name from the data type enumerator.
+ ///
+ /// @param data_type option data type.
+ /// @return option data type name.
+ const std::string& getDataTypeNameImpl(const OptionDataType data_type) const;
};
diff --git a/src/lib/dhcp/option_definition.cc b/src/lib/dhcp/option_definition.cc
index 2b4fddb..b61a4ea 100644
--- a/src/lib/dhcp/option_definition.cc
+++ b/src/lib/dhcp/option_definition.cc
@@ -28,150 +28,6 @@ using namespace isc::util;
namespace isc {
namespace dhcp {
-OptionDefinition::DataTypeUtil::DataTypeUtil() {
- data_types_["empty"] = OPT_EMPTY_TYPE;
- data_types_["binary"] = OPT_BINARY_TYPE;
- data_types_["boolean"] = OPT_BOOLEAN_TYPE;
- data_types_["int8"] = OPT_INT8_TYPE;
- data_types_["int16"] = OPT_INT16_TYPE;
- data_types_["int32"] = OPT_INT32_TYPE;
- data_types_["uint8"] = OPT_UINT8_TYPE;
- data_types_["uint16"] = OPT_UINT16_TYPE;
- data_types_["uint32"] = OPT_UINT32_TYPE;
- data_types_["ipv4-address"] = OPT_IPV4_ADDRESS_TYPE;
- data_types_["ipv6-address"] = OPT_IPV6_ADDRESS_TYPE;
- data_types_["string"] = OPT_STRING_TYPE;
- data_types_["fqdn"] = OPT_FQDN_TYPE;
- data_types_["record"] = OPT_RECORD_TYPE;
-}
-
-OptionDataType
-OptionDefinition::DataTypeUtil::getOptionDataType(const std::string& data_type) {
- std::map<std::string, OptionDataType>::const_iterator data_type_it =
- data_types_.find(data_type);
- if (data_type_it != data_types_.end()) {
- return (data_type_it->second);
- }
- return (OPT_UNKNOWN_TYPE);
-}
-
-template<typename T>
-T OptionDefinition::DataTypeUtil::lexicalCastWithRangeCheck(const std::string& value_str) const {
- // Lexical cast in case of our data types make sense only
- // for uintX_t, intX_t and bool type.
- if (!OptionDataTypeTraits<T>::integer_type &&
- OptionDataTypeTraits<T>::type != OPT_BOOLEAN_TYPE) {
- isc_throw(BadDataTypeCast, "unable to do lexical cast to non-integer and"
- << " non-boolean data type");
- }
- // We use the 64-bit value here because it has wider range than
- // any other type we use here and it allows to detect out of
- // bounds conditions e.g. negative value specified for uintX_t
- // data type. Obviously if the value exceeds the limits of int64
- // this function will not handle that properly.
- int64_t result = 0;
- try {
- result = boost::lexical_cast<int64_t>(value_str);
- } catch (const boost::bad_lexical_cast& ex) {
- // Prepare error message here.
- std::string data_type_str = "boolean";
- if (OptionDataTypeTraits<T>::integer_type) {
- data_type_str = "integer";
- }
- isc_throw(BadDataTypeCast, "unable to do lexical cast to " << data_type_str
- << " data type for value " << value_str << ": " << ex.what());
- }
- // Perform range checks for integer values only (exclude bool values).
- if (OptionDataTypeTraits<T>::integer_type) {
- if (result > numeric_limits<T>::max() ||
- result < numeric_limits<T>::min()) {
- isc_throw(BadDataTypeCast, "unable to do lexical cast for value "
- << value_str << ". This value is expected to be in the range of "
- << numeric_limits<T>::min() << ".." << numeric_limits<T>::max());
- }
- }
- return (static_cast<T>(result));
-}
-
-void
-OptionDefinition::DataTypeUtil::writeToBuffer(const std::string& value,
- const OptionDataType type,
- OptionBuffer& buf) {
- // We are going to write value given by value argument to the buffer.
- // The actual type of the value is given by second argument. Check
- // this argument to determine how to write this value to the buffer.
- switch (type) {
- case OPT_BINARY_TYPE:
- OptionDataTypeUtil::writeBinary(value, buf);
- return;
- case OPT_BOOLEAN_TYPE:
- // We encode the true value as 1 and false as 0 on 8 bits.
- // That way we actually waste 7 bits but it seems to be the
- // simpler way to encode boolean.
- // @todo Consider if any other encode methods can be used.
- OptionDataTypeUtil::writeBool(lexicalCastWithRangeCheck<bool>(value), buf);
- return;
- case OPT_INT8_TYPE:
- OptionDataTypeUtil::writeInt<uint8_t>(lexicalCastWithRangeCheck<int8_t>(value),
- buf);
- return;
- case OPT_INT16_TYPE:
- OptionDataTypeUtil::writeInt<uint16_t>(lexicalCastWithRangeCheck<int16_t>(value),
- buf);
- return;
- case OPT_INT32_TYPE:
- OptionDataTypeUtil::writeInt<uint32_t>(lexicalCastWithRangeCheck<int32_t>(value),
- buf);
- return;
- case OPT_UINT8_TYPE:
- OptionDataTypeUtil::writeInt<uint8_t>(lexicalCastWithRangeCheck<uint8_t>(value),
- buf);
- return;
- case OPT_UINT16_TYPE:
- OptionDataTypeUtil::writeInt<uint16_t>(lexicalCastWithRangeCheck<uint16_t>(value),
- buf);
- return;
- case OPT_UINT32_TYPE:
- OptionDataTypeUtil::writeInt<uint32_t>(lexicalCastWithRangeCheck<uint32_t>(value),
- buf);
- return;
- case OPT_IPV4_ADDRESS_TYPE:
- case OPT_IPV6_ADDRESS_TYPE:
- {
- asiolink::IOAddress address(value);
- if (!address.getAddress().is_v4() &&
- !address.getAddress().is_v6()) {
- isc_throw(BadDataTypeCast, "provided address " << address.toText()
- << " is not a valid "
- << (address.getAddress().is_v4() ? "IPv4" : "IPv6")
- << " address");
- }
- OptionDataTypeUtil::writeAddress(address, buf);
- return;
- }
- case OPT_STRING_TYPE:
- OptionDataTypeUtil::writeString(value, buf);
- return;
- case OPT_FQDN_TYPE:
- {
- // FQDN implementation is not terribly complicated but will require
- // creation of some additional logic (maybe object) that will parse
- // the fqdn into labels.
- isc_throw(isc::NotImplemented, "write of FQDN record into option buffer"
- " is not supported yet");
- return;
- }
- default:
- // We hit this point because invalid option data type has been specified
- // This may be the case because 'empty' or 'record' data type has been
- // specified. We don't throw exception here because it will be thrown
- // at the exit point from this function.
- ;
- }
- isc_throw(isc::BadValue, "attempt to write invalid option data field type"
- " into the option buffer: " << type);
-
-}
OptionDefinition::OptionDefinition(const std::string& name,
const uint16_t code,
@@ -184,7 +40,7 @@ OptionDefinition::OptionDefinition(const std::string& name,
// Data type is held as enum value by this class.
// Use the provided option type string to get the
// corresponding enum value.
- type_ = DataTypeUtil::instance().getOptionDataType(type);
+ type_ = OptionDataTypeUtil::getDataType(type);
}
OptionDefinition::OptionDefinition(const std::string& name,
@@ -199,7 +55,7 @@ OptionDefinition::OptionDefinition(const std::string& name,
void
OptionDefinition::addRecordField(const std::string& data_type_name) {
- OptionDataType data_type = DataTypeUtil::instance().getOptionDataType(data_type_name);
+ OptionDataType data_type = OptionDataTypeUtil::getDataType(data_type_name);
addRecordField(data_type);
}
@@ -291,10 +147,10 @@ OptionDefinition::optionFactory(Option::Universe u, uint16_t type,
if (values.size() == 0) {
isc_throw(InvalidOptionValue, "no option value specified");
}
- DataTypeUtil::instance().writeToBuffer(values[0], type_, buf);
+ writeToBuffer(values[0], type_, buf);
} else if (array_type_ && type_ != OPT_RECORD_TYPE) {
for (size_t i = 0; i < values.size(); ++i) {
- DataTypeUtil::instance().writeToBuffer(values[i], type_, buf);
+ writeToBuffer(values[i], type_, buf);
}
} else if (type_ == OPT_RECORD_TYPE) {
const RecordFieldsCollection& records = getRecordFields();
@@ -304,7 +160,7 @@ OptionDefinition::optionFactory(Option::Universe u, uint16_t type,
<< " provided.");
}
for (size_t i = 0; i < records.size(); ++i) {
- DataTypeUtil::instance().writeToBuffer(values[i], records[i], buf);
+ writeToBuffer(values[i], records[i], buf);
}
}
return (optionFactory(u, type, buf.begin(), buf.end()));
@@ -410,6 +266,124 @@ OptionDefinition::haveIAAddr6Format() const {
return (haveIAx6Format(OPT_IPV6_ADDRESS_TYPE));
}
+template<typename T>
+T OptionDefinition::lexicalCastWithRangeCheck(const std::string& value_str) const {
+ // Lexical cast in case of our data types make sense only
+ // for uintX_t, intX_t and bool type.
+ if (!OptionDataTypeTraits<T>::integer_type &&
+ OptionDataTypeTraits<T>::type != OPT_BOOLEAN_TYPE) {
+ isc_throw(BadDataTypeCast, "unable to do lexical cast to non-integer and"
+ << " non-boolean data type");
+ }
+ // We use the 64-bit value here because it has wider range than
+ // any other type we use here and it allows to detect out of
+ // bounds conditions e.g. negative value specified for uintX_t
+ // data type. Obviously if the value exceeds the limits of int64
+ // this function will not handle that properly.
+ int64_t result = 0;
+ try {
+ result = boost::lexical_cast<int64_t>(value_str);
+ } catch (const boost::bad_lexical_cast& ex) {
+ // Prepare error message here.
+ std::string data_type_str = "boolean";
+ if (OptionDataTypeTraits<T>::integer_type) {
+ data_type_str = "integer";
+ }
+ isc_throw(BadDataTypeCast, "unable to do lexical cast to " << data_type_str
+ << " data type for value " << value_str << ": " << ex.what());
+ }
+ // Perform range checks for integer values only (exclude bool values).
+ if (OptionDataTypeTraits<T>::integer_type) {
+ if (result > numeric_limits<T>::max() ||
+ result < numeric_limits<T>::min()) {
+ isc_throw(BadDataTypeCast, "unable to do lexical cast for value "
+ << value_str << ". This value is expected to be in the range of "
+ << numeric_limits<T>::min() << ".." << numeric_limits<T>::max());
+ }
+ }
+ return (static_cast<T>(result));
+}
+
+void
+OptionDefinition::writeToBuffer(const std::string& value,
+ const OptionDataType type,
+ OptionBuffer& buf) const {
+ // We are going to write value given by value argument to the buffer.
+ // The actual type of the value is given by second argument. Check
+ // this argument to determine how to write this value to the buffer.
+ switch (type) {
+ case OPT_BINARY_TYPE:
+ OptionDataTypeUtil::writeBinary(value, buf);
+ return;
+ case OPT_BOOLEAN_TYPE:
+ // We encode the true value as 1 and false as 0 on 8 bits.
+ // That way we actually waste 7 bits but it seems to be the
+ // simpler way to encode boolean.
+ // @todo Consider if any other encode methods can be used.
+ OptionDataTypeUtil::writeBool(lexicalCastWithRangeCheck<bool>(value), buf);
+ return;
+ case OPT_INT8_TYPE:
+ OptionDataTypeUtil::writeInt<uint8_t>(lexicalCastWithRangeCheck<int8_t>(value),
+ buf);
+ return;
+ case OPT_INT16_TYPE:
+ OptionDataTypeUtil::writeInt<uint16_t>(lexicalCastWithRangeCheck<int16_t>(value),
+ buf);
+ return;
+ case OPT_INT32_TYPE:
+ OptionDataTypeUtil::writeInt<uint32_t>(lexicalCastWithRangeCheck<int32_t>(value),
+ buf);
+ return;
+ case OPT_UINT8_TYPE:
+ OptionDataTypeUtil::writeInt<uint8_t>(lexicalCastWithRangeCheck<uint8_t>(value),
+ buf);
+ return;
+ case OPT_UINT16_TYPE:
+ OptionDataTypeUtil::writeInt<uint16_t>(lexicalCastWithRangeCheck<uint16_t>(value),
+ buf);
+ return;
+ case OPT_UINT32_TYPE:
+ OptionDataTypeUtil::writeInt<uint32_t>(lexicalCastWithRangeCheck<uint32_t>(value),
+ buf);
+ return;
+ case OPT_IPV4_ADDRESS_TYPE:
+ case OPT_IPV6_ADDRESS_TYPE:
+ {
+ asiolink::IOAddress address(value);
+ if (!address.getAddress().is_v4() &&
+ !address.getAddress().is_v6()) {
+ isc_throw(BadDataTypeCast, "provided address " << address.toText()
+ << " is not a valid "
+ << (address.getAddress().is_v4() ? "IPv4" : "IPv6")
+ << " address");
+ }
+ OptionDataTypeUtil::writeAddress(address, buf);
+ return;
+ }
+ case OPT_STRING_TYPE:
+ OptionDataTypeUtil::writeString(value, buf);
+ return;
+ case OPT_FQDN_TYPE:
+ {
+ // FQDN implementation is not terribly complicated but will require
+ // creation of some additional logic (maybe object) that will parse
+ // the fqdn into labels.
+ isc_throw(isc::NotImplemented, "write of FQDN record into option buffer"
+ " is not supported yet");
+ return;
+ }
+ default:
+ // We hit this point because invalid option data type has been specified
+ // This may be the case because 'empty' or 'record' data type has been
+ // specified. We don't throw exception here because it will be thrown
+ // at the exit point from this function.
+ ;
+ }
+ isc_throw(isc::BadValue, "attempt to write invalid option data field type"
+ " into the option buffer: " << type);
+
+}
+
OptionPtr
OptionDefinition::factoryAddrList4(uint16_t type,
OptionBufferConstIter begin,
diff --git a/src/lib/dhcp/option_definition.h b/src/lib/dhcp/option_definition.h
index 18f79d2..3d48ef2 100644
--- a/src/lib/dhcp/option_definition.h
+++ b/src/lib/dhcp/option_definition.h
@@ -131,83 +131,6 @@ public:
/// Const iterator for record data fields.
typedef std::vector<OptionDataType>::const_iterator RecordFieldsConstIter;
-private:
-
- /// @brief Utility class for operations on OptionDataTypes.
- ///
- /// This class is implemented as the singleton because the list of
- /// supported data types need only be loaded only once into memory as it
- /// can persist for all option definitions.
- ///
- /// @todo This class can be extended to return the string value
- /// representing the data type from the enum value.
- class DataTypeUtil {
- public:
-
- /// @brief Return the sole instance of this class.
- ///
- /// @return instance of this class.
- static DataTypeUtil& instance() {
- static DataTypeUtil instance;
- return (instance);
- }
-
- /// @brief Convert type given as string value to option data type.
- ///
- /// @param data_type_name data type string.
- ///
- /// @return option data type.
- OptionDataType getOptionDataType(const std::string& data_type_name);
-
- /// @brief Perform lexical cast of the value and validate its range.
- ///
- /// This function performs lexical cast of a string value to integer
- /// or boolean value and checks if the resulting value is within a
- /// range of a target type. Note that range checks are not performed
- /// on boolean values. The target type should be one of the supported
- /// integer types or bool.
- ///
- /// @param value_str input value given as string.
- /// @tparam T target type for lexical cast.
- ///
- /// @return cast value.
- /// @throw BadDataTypeCast if cast 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 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(const std::string& value, const OptionDataType type,
- OptionBuffer& buf);
-
- private:
- /// @brief Private constructor.
- ///
- /// Constructor initializes the internal data structures, e.g.
- /// mapping between data type name and the corresponding enum.
- /// This constructor is private to ensure that exactly one
- /// instance of this class can be created using \ref instance
- /// function.
- DataTypeUtil();
-
- /// Map of data types, maps name of the type to enum value.
- std::map<std::string, OptionDataType> data_types_;
- };
-
-public:
/// @brief Constructor.
///
/// @param name option name.
@@ -471,6 +394,40 @@ private:
return (type == type_);
}
+ /// @brief Perform lexical cast of the value and validate its range.
+ ///
+ /// This function performs lexical cast of a string value to integer
+ /// or boolean value and checks if the resulting value is within a
+ /// range of a target type. Note that range checks are not performed
+ /// on boolean values. The target type should be one of the supported
+ /// integer types or bool.
+ ///
+ /// @param value_str input value given as string.
+ /// @tparam T target type for lexical cast.
+ ///
+ /// @return cast value.
+ /// @throw BadDataTypeCast if cast 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 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(const std::string& value, const OptionDataType type,
+ OptionBuffer& buf) const;
+
/// @brief Sanity check universe value.
///
/// @param expected_universe expected universe value.
More information about the bind10-changes
mailing list