labelsequence.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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 __LABELSEQUENCE_H
  15. #define __LABELSEQUENCE_H 1
  16. #include <dns/name.h>
  17. #include <util/buffer.h>
  18. namespace isc {
  19. namespace dns {
  20. /// \brief Light-weight Accessor to data of Name object
  21. ///
  22. /// The purpose of this class is to easily match Names and parts of Names,
  23. /// without needing to copy the underlying data on each label strip.
  24. ///
  25. /// It can only work on existing Name objects, or data as provided by the
  26. /// Name object or another LabelSequence, and the data or Name MUST
  27. /// remain in scope during the entire lifetime of its associated
  28. /// LabelSequence(s).
  29. ///
  30. /// Upon creation of a LabelSequence, it records the offsets of the
  31. /// labels in the wireformat data of the Name. When stripLeft() or
  32. /// stripRight() is called on the LabelSequence, no changes in the
  33. /// original data occur, but the internal pointers of the
  34. /// LabelSequence are modified.
  35. ///
  36. /// LabelSequences can be compared to other LabelSequences, and their
  37. /// data can be requested (which then points to part of the original
  38. /// data of the original Name object).
  39. class LabelSequence {
  40. // Name calls the private toText(bool) method of LabelSequence.
  41. friend std::string Name::toText(bool) const;
  42. public:
  43. /// \brief Constructs a LabelSequence for the given name
  44. ///
  45. /// \note The associated Name MUST remain in scope during the lifetime
  46. /// of this LabelSequence, since getData() refers to data from the
  47. /// Name object (the only data the LabelSequence stores are pointers
  48. /// to the labels in the Name object).
  49. ///
  50. /// \param name The Name to construct a LabelSequence for
  51. explicit LabelSequence(const Name& name):
  52. data_(&name.ndata_[0]),
  53. offsets_(&name.offsets_[0]),
  54. offsets_size_(name.offsets_.size()),
  55. first_label_(0),
  56. last_label_(name.getLabelCount())
  57. {}
  58. /// \brief Constructs a LabelSequence for the given data
  59. ///
  60. /// \note The associated data MUST remain in scope during the lifetime
  61. /// of this LabelSequence, since only the pointers are copied.
  62. ///
  63. /// \note No validation is done on the given data upon construction;
  64. /// use with care.
  65. ///
  66. /// \exception isc::BadValue if basic checks for the input data, or
  67. /// offsets fails.
  68. ///
  69. /// \param data The raw data for the domain name, in wire format
  70. /// \param offsets The offsets of the labels in the domain name data,
  71. /// as given by a Name object or another LabelSequence
  72. /// \param offsets_size The size of the offsets data
  73. LabelSequence(const uint8_t* data,
  74. const uint8_t* offsets,
  75. size_t offsets_size);
  76. /// \brief Copy constructor.
  77. ///
  78. /// \note The associated data MUST remain in scope during the lifetime
  79. /// of this LabelSequence, since only the pointers are copied.
  80. ///
  81. /// \note No validation is done on the given data upon construction;
  82. /// use with care.
  83. ///
  84. /// \param ls The LabelSequence to construct a LabelSequence from
  85. LabelSequence(const LabelSequence& ls):
  86. data_(ls.data_),
  87. offsets_(ls.offsets_),
  88. offsets_size_(ls.offsets_size_),
  89. first_label_(ls.first_label_),
  90. last_label_(ls.last_label_)
  91. {}
  92. /// \brief Return the wire-format data for this LabelSequence
  93. ///
  94. /// The data is returned as a pointer to (the part of) the original
  95. /// wireformat data, from either the original Name object, or the
  96. /// raw data given in the constructor, and the given len value is
  97. /// set to the number of octets that match this labelsequence.
  98. ///
  99. /// \note The data pointed to is only valid if the original Name
  100. /// object or data is still in scope
  101. ///
  102. /// \param len Pointer to a size_t where the length of the data
  103. /// will be stored (in number of octets)
  104. /// \return Pointer to the wire-format data of this label sequence
  105. const uint8_t* getData(size_t* len) const;
  106. /// \brief Return the offset data for this LabelSequence
  107. ///
  108. /// The offsets are returned in the <code>placeholder</code> array.
  109. ///
  110. /// \param len Pointer to a size_t where the number of offsets
  111. /// will be stored
  112. /// \param placeholder Array where the offset data will be returned
  113. void getOffsetData(size_t* len,
  114. uint8_t placeholder[Name::MAX_LABELS]) const;
  115. /// \brief Return the length of the wire-format data of this LabelSequence
  116. ///
  117. /// This method returns the number of octets for the data that would
  118. /// be returned by the \c getData() method.
  119. ///
  120. /// Note that the return value of this method is always positive.
  121. /// Note also that if the return value of this method is 1, it means the
  122. /// sequence consists of the null label, i.e., a single "dot", and vice
  123. /// versa.
  124. ///
  125. /// \note The data pointed to is only valid if the original Name
  126. /// object or data is still in scope
  127. ///
  128. /// \return The length of the data of the label sequence in octets.
  129. size_t getDataLength() const;
  130. /// \brief Compares two label sequences for equality.
  131. ///
  132. /// Performs a (optionally case-insensitive) comparison between this
  133. /// LabelSequence and another LabelSequence for equality.
  134. ///
  135. /// \param other The LabelSequence to compare with
  136. /// \param case_sensitive If true, comparison is case-insensitive
  137. /// \return true if The label sequences consist are the same length,
  138. /// and contain the same data.
  139. bool equals(const LabelSequence& other, bool case_sensitive = false) const;
  140. /// \brief Compares two label sequences.
  141. ///
  142. /// Performs a (optionally case-insensitive) comparison between this
  143. /// LabelSequence and another LabelSequence.
  144. ///
  145. /// \param other The LabelSequence to compare with
  146. /// \param case_sensitive If true, comparison is case-insensitive
  147. /// \return a <code>NameComparisonResult</code> object representing the
  148. /// comparison result.
  149. NameComparisonResult compare(const LabelSequence& other,
  150. bool case_sensitive = false) const;
  151. /// \brief Remove labels from the front of this LabelSequence
  152. ///
  153. /// \note No actual memory is changed, this operation merely updates the
  154. /// internal pointers based on the offsets in the Name object.
  155. ///
  156. /// \exception OutOfRange if i is greater than or equal to the number
  157. /// of labels currently pointed to by this LabelSequence
  158. ///
  159. /// \param i The number of labels to remove.
  160. void stripLeft(size_t i);
  161. /// \brief Remove labels from the end of this LabelSequence
  162. ///
  163. /// \note No actual memory is changed, this operation merely updates the
  164. /// internal pointers based on the offsets originally provided.
  165. ///
  166. /// \exception OutOfRange if i is greater than or equal to the number
  167. /// of labels currently pointed to by this LabelSequence
  168. ///
  169. /// \param i The number of labels to remove.
  170. void stripRight(size_t i);
  171. /// \brief Returns the current number of labels for this LabelSequence
  172. ///
  173. /// \return The number of labels
  174. size_t getLabelCount() const { return (last_label_ - first_label_); }
  175. /// \brief Convert the LabelSequence to a string.
  176. ///
  177. /// This method returns a <code>std::string</code> object representing the
  178. /// LabelSequence as a string. The returned string ends with a dot
  179. /// '.' if the label sequence is absolute.
  180. ///
  181. /// This function assumes the underlying data is in proper
  182. /// uncompressed wire format. If it finds an unexpected label
  183. /// character including compression pointer, an exception of class
  184. /// \c BadLabelType will be thrown. In addition, if resource
  185. /// allocation for the result string fails, a corresponding standard
  186. /// exception will be thrown.
  187. ///
  188. /// \return a string representation of the <code>LabelSequence</code>.
  189. std::string toText() const;
  190. private:
  191. /// \brief Convert the LabelSequence to a string.
  192. ///
  193. /// This method is a version of the zero-argument toText() method,
  194. /// that accepts a <code>omit_final_dot</code> argument. The
  195. /// returned string ends with a dot '.' if
  196. /// <code>omit_final_dot</code> is <code>false</code>.
  197. ///
  198. /// This method is used as a helper for <code>Name::toText()</code>
  199. /// only.
  200. ///
  201. /// \param omit_final_dot whether to omit the trailing dot in the output.
  202. /// \return a string representation of the <code>LabelSequence</code>.
  203. std::string toText(bool omit_final_dot) const;
  204. public:
  205. /// \brief Calculate a simple hash for the label sequence.
  206. ///
  207. /// This method calculates a hash value for the label sequence as binary
  208. /// data. If \c case_sensitive is false, it ignores the case stored in
  209. /// the labels; specifically, it normalizes the labels by converting all
  210. /// upper case characters to lower case ones and calculates the hash value
  211. /// for the result.
  212. ///
  213. /// This method is intended to provide a lightweight way to store a
  214. /// relatively small number of label sequences in a hash table.
  215. /// For this reason it only takes into account data up to 16 octets
  216. /// (16 was derived from BIND 9's implementation). Also, the function does
  217. /// not provide any unpredictability; a specific sequence will always have
  218. /// the same hash value. It should therefore not be used in the context
  219. /// where an untrusted third party can mount a denial of service attack by
  220. /// forcing the application to create a very large number of label
  221. /// sequences that have the same hash value and expected to be stored in
  222. /// a hash table.
  223. ///
  224. /// \exception None
  225. ///
  226. /// \param case_sensitive
  227. /// \return A hash value for this label sequence.
  228. size_t getHash(bool case_sensitive) const;
  229. /// \brief Checks whether the label sequence is absolute
  230. ///
  231. /// \return true if the last label is the root label
  232. bool isAbsolute() const;
  233. private:
  234. const uint8_t* data_;
  235. const uint8_t* offsets_;
  236. size_t offsets_size_;
  237. size_t first_label_;
  238. size_t last_label_;
  239. };
  240. ///
  241. /// \brief Insert the label sequence as a string into stream.
  242. ///
  243. /// This method convert the \c label_sequence into a string and inserts
  244. /// it into the output stream \c os.
  245. ///
  246. /// This function overloads the global operator<< to behave as described in
  247. /// ostream::operator<< but applied to \c LabelSequence objects.
  248. ///
  249. /// \param os A \c std::ostream object on which the insertion operation is
  250. /// performed.
  251. /// \param label_sequence The \c LabelSequence object output by the operation.
  252. /// \return A reference to the same \c std::ostream object referenced by
  253. /// parameter \c os after the insertion operation.
  254. std::ostream&
  255. operator<<(std::ostream& os, const LabelSequence& label_sequence);
  256. } // end namespace dns
  257. } // end namespace isc
  258. #endif
  259. // Local Variables:
  260. // mode: c++
  261. // End: