option6_int_array.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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 OPTION6_INT_ARRAY_H_
  15. #define OPTION6_INT_ARRAY_H_
  16. #include <dhcp/libdhcp++.h>
  17. #include <dhcp/option.h>
  18. #include <dhcp/option_data_types.h>
  19. #include <util/io_utilities.h>
  20. #include <stdint.h>
  21. #include <limits>
  22. namespace isc {
  23. namespace dhcp {
  24. /// This template class represents DHCPv6 option with array of
  25. /// integer values. The type of the elements in the array can be
  26. /// any of the following:
  27. /// - uint8_t,
  28. /// - uint16_t,
  29. /// - uint32_t,
  30. /// - int8_t,
  31. /// - int16_t,
  32. /// - int32_t.
  33. ///
  34. /// @warning Since this option may convey variable number of integer
  35. /// values, sub-options are should not be added in this option as
  36. /// there is no way to distinguish them from other data. The API will
  37. /// allow addition of sub-options but they will be ignored during
  38. /// packing and unpacking option data.
  39. ///
  40. /// @param T data field type (see above).
  41. template<typename T>
  42. class Option6IntArray: public Option {
  43. public:
  44. /// @brief Constructor.
  45. ///
  46. /// Creates option with empty values vector.
  47. ///
  48. /// @param type option type.
  49. Option6IntArray(uint16_t type)
  50. : Option(Option::V6, type),
  51. values_(0) {
  52. if (!OptionDataTypes<T>::valid) {
  53. isc_throw(dhcp::InvalidDataType, "non-integer type");
  54. }
  55. }
  56. /// @brief Constructor.
  57. ///
  58. /// @param type option type.
  59. /// @param buf buffer with option data (must not be empty).
  60. ///
  61. /// @throw isc::OutOfRange if provided buffer is empty or its length
  62. /// is not multiple of size of the data type in bytes.
  63. Option6IntArray(uint16_t type, const OptionBuffer& buf)
  64. : Option(Option::V6, type) {
  65. if (!OptionDataTypes<T>::valid) {
  66. isc_throw(dhcp::InvalidDataType, "non-integer type");
  67. }
  68. unpack(buf.begin(), buf.end());
  69. }
  70. /// @brief Constructor.
  71. ///
  72. /// This constructor creates option from a buffer. This construtor
  73. /// may throw exception if \ref unpack function throws during buffer
  74. /// parsing.
  75. ///
  76. /// @param type option type.
  77. /// @param begin iterator to first byte of option data.
  78. /// @param end iterator to end of option data (first byte after option end).
  79. ///
  80. /// @throw isc::OutOfRange if provided buffer is empty or its length
  81. /// is not multiple of size of the data type in bytes.
  82. Option6IntArray(uint16_t type, OptionBufferConstIter begin,
  83. OptionBufferConstIter end)
  84. : Option(Option::V6, type) {
  85. if (!OptionDataTypes<T>::valid) {
  86. isc_throw(dhcp::InvalidDataType, "non-integer type");
  87. }
  88. unpack(begin, end);
  89. }
  90. /// Writes option in wire-format to buf, returns pointer to first unused
  91. /// byte after stored option.
  92. ///
  93. /// @param [out] buf buffer (option will be stored here)
  94. ///
  95. /// @throw isc::BadValue if invalid option type has been provided.
  96. void pack(isc::util::OutputBuffer& buf) {
  97. buf.writeUint16(type_);
  98. buf.writeUint16(len() - OPTION6_HDR_LEN);
  99. for (int i = 0; i < values_.size(); ++i) {
  100. // Depending on the data type length we use different utility functions
  101. // writeUint16 or writeUint32 which write the data in the network byte
  102. // order to the provided buffer. The same functions can be safely used
  103. // for either unsiged or signed integers so there is not need to create
  104. // special cases for intX_t types.
  105. switch (OptionDataTypes<T>::len) {
  106. case 1:
  107. buf.writeUint8(values_[i]);
  108. break;
  109. case 2:
  110. buf.writeUint16(values_[i]);
  111. break;
  112. case 4:
  113. buf.writeUint32(values_[i]);
  114. break;
  115. default:
  116. isc_throw(dhcp::InvalidDataType, "non-integer type");
  117. }
  118. }
  119. // We don't pack sub-options here because we have array-type option.
  120. // We don't allow sub-options in array-type options as there is no
  121. // way to distinguish them from the data fields on option reception.
  122. }
  123. /// @brief Parses received buffer
  124. ///
  125. /// Parses received buffer and returns offset to the first unused byte after
  126. /// parsed option.
  127. ///
  128. /// @param begin iterator to first byte of option data
  129. /// @param end iterator to end of option data (first byte after option end)
  130. virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end) {
  131. if (distance(begin, end) == 0) {
  132. isc_throw(OutOfRange, "option " << getType() << " empty");
  133. }
  134. if (distance(begin, end) % sizeof(T) != 0) {
  135. isc_throw(OutOfRange, "option " << getType() << " truncated");
  136. }
  137. values_.clear();
  138. while (begin != end) {
  139. // Depending on the data type length we use different utility functions
  140. // readUint16 or readUint32 which read the data laid in the network byte
  141. // order from the provided buffer. The same functions can be safely used
  142. // for either unsiged or signed integers so there is not need to create
  143. // special cases for intX_t types.
  144. switch (OptionDataTypes<T>::len) {
  145. case 1:
  146. values_.push_back(*begin);
  147. break;
  148. case 2:
  149. values_.push_back(isc::util::readUint16(&(*begin)));
  150. break;
  151. case 4:
  152. values_.push_back(isc::util::readUint32(&(*begin)));
  153. break;
  154. default:
  155. isc_throw(dhcp::InvalidDataType, "non-integer type");
  156. }
  157. begin += sizeof(T);
  158. }
  159. // We do not unpack sub-options here because we have array-type option.
  160. // Such option have variable number of data fields, thus there is no
  161. // way to assess where sub-options start.
  162. }
  163. /// @brief Return collection of option values.
  164. ///
  165. /// @return collection of values.
  166. const std::vector<T>& getValues() const { return (values_); }
  167. /// @brief Set option values.
  168. ///
  169. /// @param values collection of values to be set for option.
  170. void setValues(const std::vector<T>& values) { values_ = values; }
  171. /// @brief returns complete length of option
  172. ///
  173. /// Returns length of this option, including option header and suboptions
  174. ///
  175. /// @return length of this option
  176. virtual uint16_t len() {
  177. uint16_t length = OPTION6_HDR_LEN + values_.size() * sizeof(T);
  178. // length of all suboptions
  179. for (Option::OptionCollection::iterator it = options_.begin();
  180. it != options_.end();
  181. ++it) {
  182. length += (*it).second->len();
  183. }
  184. return (length);
  185. }
  186. private:
  187. std::vector<T> values_;
  188. };
  189. } // isc::dhcp namespace
  190. } // isc namespace
  191. #endif /* OPTION6_INT_ARRAY_H_ */