123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- // Copyright (C) 2012-2015 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_INT_H
- #define OPTION_INT_H
- #include <dhcp/libdhcp++.h>
- #include <dhcp/option.h>
- #include <dhcp/option_data_types.h>
- #include <util/io_utilities.h>
- #include <stdint.h>
- #include <sstream>
- namespace isc {
- namespace dhcp {
- template<typename T>
- class OptionInt;
- /// @defgroup option_int_defs Typedefs for OptionInt class.
- ///
- /// @brief Classes that represent options comprising an integer.
- ///
- /// @{
- typedef OptionInt<uint8_t> OptionUint8;
- typedef boost::shared_ptr<OptionUint8> OptionUint8Ptr;
- typedef OptionInt<uint16_t> OptionUint16;
- typedef boost::shared_ptr<OptionUint16> OptionUint16Ptr;
- typedef OptionInt<uint32_t> OptionUint32;
- typedef boost::shared_ptr<OptionUint32> OptionUint32Ptr;
- /// @}
- /// This template class represents DHCP option with single value.
- /// This value is of integer type and can be any of the following:
- /// - uint8_t,
- /// - uint16_t,
- /// - uint32_t,
- /// - int8_t,
- /// - int16_t,
- /// - int32_t.
- ///
- /// @param T data field type (see above).
- template<typename T>
- class OptionInt: public Option {
- public:
- /// @brief Constructor.
- ///
- /// @param u universe (V4 or V6)
- /// @param type option type.
- /// @param value option value.
- ///
- /// @throw isc::dhcp::InvalidDataType if data field type provided
- /// as template parameter is not a supported integer type.
- /// @todo Extend constructor to set encapsulated option space name.
- OptionInt(Option::Universe u, uint16_t type, T value)
- : Option(u, type), value_(value) {
- if (!OptionDataTypeTraits<T>::integer_type) {
- isc_throw(dhcp::InvalidDataType, "non-integer type");
- }
- setEncapsulatedSpace(u == Option::V4 ? "dhcp4" : "dhcp6");
- }
- /// @brief Constructor.
- ///
- /// This constructor creates option from a buffer. This constructor
- /// may throw exception if \ref unpack function throws during buffer
- /// parsing.
- ///
- /// @param u universe (V4 or V6)
- /// @param type option type.
- /// @param begin iterator to first byte of option data.
- /// @param end iterator to end of option data (first byte after option end).
- ///
- /// @throw isc::OutOfRange if provided buffer is shorter than data size.
- /// @throw isc::dhcp::InvalidDataType if data field type provided
- /// as template parameter is not a supported integer type.
- /// @todo Extend constructor to set encapsulated option space name.
- OptionInt(Option::Universe u, uint16_t type, OptionBufferConstIter begin,
- OptionBufferConstIter end)
- : Option(u, type) {
- if (!OptionDataTypeTraits<T>::integer_type) {
- isc_throw(dhcp::InvalidDataType, "non-integer type");
- }
- setEncapsulatedSpace(u == Option::V4 ? "dhcp4" : "dhcp6");
- unpack(begin, end);
- }
- /// Writes option in wire-format to buf, returns pointer to first unused
- /// byte after stored option.
- ///
- /// @param [out] buf buffer (option will be stored here)
- ///
- /// @throw isc::dhcp::InvalidDataType if size of a data field type is not
- /// equal to 1, 2 or 4 bytes. The data type is not checked in this function
- /// because it is checked in a constructor.
- void pack(isc::util::OutputBuffer& buf) const {
- // Pack option header.
- packHeader(buf);
- // Depending on the data type length we use different utility functions
- // writeUint16 or writeUint32 which write the data in the network byte
- // order to the provided buffer. The same functions can be safely used
- // for either unsigned or signed integers so there is not need to create
- // special cases for intX_t types.
- switch (OptionDataTypeTraits<T>::len) {
- case 1:
- buf.writeUint8(value_);
- break;
- case 2:
- buf.writeUint16(value_);
- break;
- case 4:
- buf.writeUint32(value_);
- break;
- default:
- isc_throw(dhcp::InvalidDataType, "non-integer type");
- }
- packOptions(buf);
- }
- /// @brief Parses received buffer
- ///
- /// Parses received buffer and returns offset to the first unused byte after
- /// parsed option.
- ///
- /// @param begin iterator to first byte of option data
- /// @param end iterator to end of option data (first byte after option end)
- ///
- /// @throw isc::OutOfRange if provided buffer is shorter than data size.
- /// @throw isc::dhcp::InvalidDataType if size of a data field type is not
- /// equal to 1, 2 or 4 bytes. The data type is not checked in this function
- /// because it is checked in a constructor.
- virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end) {
- if (distance(begin, end) < sizeof(T)) {
- isc_throw(OutOfRange, "Option " << getType() << " truncated");
- }
- // @todo consider what to do if buffer is longer than data type.
- // Depending on the data type length we use different utility functions
- // readUint16 or readUint32 which read the data laid in the network byte
- // order from the provided buffer. The same functions can be safely used
- // for either unsigned or signed integers so there is not need to create
- // special cases for intX_t types.
- int data_size_len = OptionDataTypeTraits<T>::len;
- switch (data_size_len) {
- case 1:
- value_ = *begin;
- break;
- case 2:
- value_ = isc::util::readUint16(&(*begin),
- std::distance(begin, end));
- break;
- case 4:
- value_ = isc::util::readUint32(&(*begin),
- std::distance(begin, end));
- break;
- default:
- isc_throw(dhcp::InvalidDataType, "non-integer type");
- }
- // Use local variable to set a new value for this iterator.
- // When using OptionDataTypeTraits<T>::len directly some versions
- // of clang complain about unresolved reference to
- // OptionDataTypeTraits structure during linking.
- begin += data_size_len;
- unpackOptions(OptionBuffer(begin, end));
- }
- /// @brief Set option value.
- ///
- /// @param value new option value.
- void setValue(T value) { value_ = value; }
- /// @brief Return option value.
- ///
- /// @return option value.
- T getValue() const { return value_; }
- /// @brief returns complete length of option
- ///
- /// Returns length of this option, including option header and suboptions
- ///
- /// @return length of this option
- virtual uint16_t len() const {
- // Calculate the length of the header.
- uint16_t length = (getUniverse() == Option::V4) ? OPTION4_HDR_LEN : OPTION6_HDR_LEN;
- // The data length is equal to size of T.
- length += sizeof(T);;
- // length of all suboptions
- for (OptionCollection::const_iterator it = options_.begin();
- it != options_.end();
- ++it) {
- length += (*it).second->len();
- }
- return (length);
- }
- /// @brief Returns option carrying an integer value in the textual
- /// format.
- ///
- /// The returned value also includes the suboptions if present.
- ///
- /// @param indent Number of spaces to be inserted before the text.
- virtual std::string toText(int indent = 0) const {
- std::stringstream output;
- output << headerToText(indent) << ": ";
- // For 1 byte long data types we need to cast to the integer
- // because they are usually implemented as "char" types, in
- // which case the character rather than number would be printed.
- if (OptionDataTypeTraits<T>::len == 1) {
- output << static_cast<int>(getValue());
- } else {
- output << getValue();
- }
- // Append data type name.
- output << " ("
- << OptionDataTypeUtil::getDataTypeName(OptionDataTypeTraits<T>::type)
- << ")";
- // Append suboptions.
- output << suboptionsToText(indent + 2);
- return (output.str());
- }
- private:
- T value_; ///< Value conveyed by the option.
- };
- } // isc::dhcp namespace
- } // isc namespace
- #endif // OPTION_INT_H
|