option_custom.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. // Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef OPTION_CUSTOM_H
  15. #define OPTION_CUSTOM_H
  16. #include <dhcp/option.h>
  17. #include <dhcp/option_definition.h>
  18. #include <util/io_utilities.h>
  19. namespace isc {
  20. namespace dhcp {
  21. /// @brief Option with defined data fields represented as buffers that can
  22. /// be accessed using data field index.
  23. ///
  24. /// This class represents an option which has defined structure: data fields
  25. /// of specific types and order. Those fields can be accessed using indexes,
  26. /// where index 0 represents first data field within an option. The last
  27. /// field can be accessed using index equal to 'number of fields' - 1.
  28. /// Internally, the option data is stored as a collection of OptionBuffer
  29. /// objects, each representing data for a particular data field. This data
  30. /// can be converted to the actual data type using methods implemented
  31. /// within this class. This class is used to represent those options that
  32. /// can't be represented by any other specialized class (this excludes the
  33. /// Option class which is generic and can be used to represent any option).
  34. class OptionCustom : public Option {
  35. public:
  36. /// @brief Constructor, used for options to be sent.
  37. ///
  38. /// This constructor creates an instance of an option from the whole
  39. /// supplied buffer. This constructor is mainly used to create an
  40. /// instances of options to be stored in outgoing DHCP packets.
  41. /// The buffer used to create the instance of an option can be
  42. /// created from the option data specified in server's configuration.
  43. ///
  44. /// @param def option definition.
  45. /// @param u specifies universe (V4 or V6).
  46. /// @param data content of the option.
  47. ///
  48. /// @throw OutOfRange if option buffer is truncated.
  49. ///
  50. /// @todo list all exceptions thrown by ctor.
  51. OptionCustom(const OptionDefinition& def, Universe u, const OptionBuffer& data);
  52. /// @brief Constructor, used for received options.
  53. ///
  54. /// This constructor creates an instance an option from the portion
  55. /// of the buffer specified by iterators. This is mainly useful when
  56. /// parsing received packets. Such packets are represented by a single
  57. /// buffer holding option data and all sub options. Methods that are
  58. /// parsing a packet, supply relevant portions of the packet buffer
  59. /// to this constructor to create option instances out of it.
  60. ///
  61. /// @param def option definition.
  62. /// @param u specifies universe (V4 or V6).
  63. /// @param first iterator to the first element that should be copied.
  64. /// @param last iterator to the next element after the last one
  65. /// to be copied.
  66. ///
  67. /// @throw OutOfRange if option buffer is truncated.
  68. ///
  69. /// @todo list all exceptions thrown by ctor.
  70. OptionCustom(const OptionDefinition& def, Universe u,
  71. OptionBufferConstIter first, OptionBufferConstIter last);
  72. /// @brief Return a number of the data fields.
  73. ///
  74. /// @return number of data fields held by the option.
  75. uint32_t getDataFieldsNum() const { return (buffers_.size()); }
  76. /// @brief Read a buffer as IP address.
  77. ///
  78. /// @param index buffer index.
  79. ///
  80. /// @return IP address read from a buffer.
  81. /// @throw isc::OutOfRange if index is out of range.
  82. asiolink::IOAddress readAddress(const uint32_t index) const;
  83. /// @brief Read a buffer as binary data.
  84. ///
  85. /// @param index buffer index.
  86. ///
  87. /// @throw isc::OutOfRange if index is out of range.
  88. /// @return read buffer holding binary data.
  89. const OptionBuffer& readBinary(const uint32_t index) const;
  90. /// @brief Read a buffer as boolean value.
  91. ///
  92. /// @param index buffer index.
  93. ///
  94. /// @throw isc::OutOfRange if index is out of range.
  95. /// @return read boolean value.
  96. bool readBoolean(const uint32_t index) const;
  97. /// @brief Read a buffer as integer value.
  98. ///
  99. /// @param index buffer index.
  100. /// @tparam integer type of a value being returned.
  101. ///
  102. /// @throw isc::OutOfRange if index is out of range.
  103. /// @return read integer value.
  104. template<typename T>
  105. T readInteger(const uint32_t index) const {
  106. checkIndex(index);
  107. // Check that the requested return type is a supported integer.
  108. if (!OptionDataTypeTraits<T>::integer_type) {
  109. isc_throw(isc::dhcp::InvalidDataType, "specified data type to be returned"
  110. " by readInteger is not supported integer type");
  111. }
  112. // Get the option definition type.
  113. OptionDataType data_type = definition_.getType();
  114. if (data_type == OPT_RECORD_TYPE) {
  115. const OptionDefinition::RecordFieldsCollection& record_fields =
  116. definition_.getRecordFields();
  117. // When we initialized buffers we have already checked that
  118. // the number of these buffers is equal to number of option
  119. // fields in the record so the condition below should be met.
  120. assert(index < record_fields.size());
  121. // Get the data type to be returned.
  122. data_type = record_fields[index];
  123. }
  124. // Requested data type must match the data type in a record.
  125. if (OptionDataTypeTraits<T>::type != data_type) {
  126. isc_throw(isc::dhcp::InvalidDataType,
  127. "unable to read option field with index " << index
  128. << " as integer value. The field's data type"
  129. << data_type << " does not match the integer type"
  130. << "returned by the readInteger function.");
  131. }
  132. // When we created the buffer we have checked that it has a
  133. // valid size so this condition here should be always fulfiled.
  134. assert(buffers_[index].size() == OptionDataTypeTraits<T>::len);
  135. // Read an integer value.
  136. return (OptionDataTypeUtil::readInt<T>(buffers_[index]));
  137. }
  138. /// @brief Read a buffer as string value.
  139. ///
  140. /// @param index buffer index.
  141. ///
  142. /// @return string value read from buffer.
  143. /// @throw isc::OutOfRange if index is out of range.
  144. std::string readString(const uint32_t index) const;
  145. /// @brief Parses received buffer.
  146. ///
  147. /// @param begin iterator to first byte of option data
  148. /// @param end iterator to end of option data (first byte after option end)
  149. virtual void unpack(OptionBufferConstIter begin,
  150. OptionBufferConstIter end);
  151. /// @brief Returns string representation of the option.
  152. ///
  153. /// @param indent number of spaces before printed text.
  154. ///
  155. /// @return string with text representation.
  156. virtual std::string toText(int indent = 0);
  157. /// @brief Returns length of the complete option (data length +
  158. /// DHCPv4/DHCPv6 option header)
  159. ///
  160. /// @return length of the option
  161. virtual uint16_t len();
  162. /// @brief Sets content of this option from buffer.
  163. ///
  164. /// Option will be resized to length of buffer.
  165. ///
  166. /// @param first iterator pointing begining of buffer to copy.
  167. /// @param last iterator pointing to end of buffer to copy.
  168. void setData(const OptionBufferConstIter first,
  169. const OptionBufferConstIter last);
  170. protected:
  171. /// @brief Writes DHCPv4 option in a wire format to a buffer.
  172. ///
  173. /// @param buf output buffer (option will be stored there).
  174. virtual void pack4(isc::util::OutputBuffer& buf);
  175. /// @brief Writes DHCPv6 option in a wire format to a buffer.
  176. ///
  177. /// @param buf output buffer (built options will be stored here)
  178. virtual void pack6(isc::util::OutputBuffer& buf);
  179. private:
  180. /// @brief Check if data field index is valid.
  181. ///
  182. /// @param index Data field index to check.
  183. ///
  184. /// @throw isc::OutOfRange if index is out of range.
  185. void checkIndex(const uint32_t index) const;
  186. /// @brief Create collection of buffers representing data field values.
  187. void createBuffers();
  188. /// @brief Return a text representation of a data field.
  189. ///
  190. /// @param data_type data type of a field.
  191. /// @param index data field buffer index within a custom option.
  192. ///
  193. /// @return text representation of a data field.
  194. std::string dataFieldToText(const OptionDataType data_type,
  195. const uint32_t index) const;
  196. /// Option definition used to create an option.
  197. OptionDefinition definition_;
  198. /// The collection of buffers holding data for option fields.
  199. /// The order of buffers corresponds to the order of option
  200. /// fields.
  201. std::vector<OptionBuffer> buffers_;
  202. };
  203. } // namespace isc::dhcp
  204. } // namespace isc
  205. #endif // OPTION_CUSTOM_H