labelsequence.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  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 Name data.
  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 Max possible size of serialized image generated by \c serialize
  44. ///
  45. /// A fixed length buffer of this size can be always passed to
  46. /// \c serialize() safely. (But the application shouldn't use the
  47. /// specific size value; it must use this constant variable).
  48. static const size_t MAX_SERIALIZED_LENGTH =
  49. Name::MAX_WIRE + Name::MAX_LABELS + 1;
  50. /// \brief Constructs a LabelSequence for the given name
  51. ///
  52. /// \note The associated Name MUST remain in scope during the lifetime
  53. /// of this LabelSequence, since getData() refers to data from the
  54. /// Name object (the only data the LabelSequence stores are pointers
  55. /// to the labels in the Name object).
  56. ///
  57. /// \param name The Name to construct a LabelSequence for
  58. explicit LabelSequence(const Name& name):
  59. data_(&name.ndata_[0]),
  60. offsets_(&name.offsets_[0]),
  61. first_label_(0),
  62. last_label_(name.getLabelCount() - 1)
  63. {}
  64. /// \brief Constructor from serialized image.
  65. ///
  66. /// This constructor restores a \c LabelSequence object from a serialized
  67. /// binary image previously generated by \c serialize(). Any other input
  68. /// to this constructor will result in undefined behavior.
  69. ///
  70. /// The binary data passed to this constructor MUST remain in scope and
  71. /// MUST NOT be modified during the lifetime of this LabelSequence.
  72. ///
  73. /// As long as the data were previously generated by a call to
  74. /// \c serialize() on a valid \c LabelSequence object, this constructor
  75. /// should succeed. While any other case is undefined, this constructor
  76. /// may perform some validity checks internally for safety. Nevertheless,
  77. /// applications must not rely on such checks.
  78. ///
  79. /// \param buf Pointer to the serialized image generated by \c serialize().
  80. explicit LabelSequence(const void* buf);
  81. /// \brief Construct 'extendable' LabelSequence
  82. ///
  83. /// This form of LabelSequence copies the data from the given
  84. /// labelsequence into the given external buffer, which is subsequently
  85. /// extendable by calling extend()
  86. ///
  87. /// The data is placed into the given buffer as follows:
  88. /// - binary sequence of name data, starting at position 0,
  89. /// length determined by source LabelSequence
  90. /// - offsets, starting at position Name::MAX_WIRE, length
  91. /// determined by source LabelSequence
  92. /// The offsets are updated to be correct for the potentially partial
  93. /// name data (as stripLeft() and stripRight may have been called on
  94. /// the source LabelSequence).
  95. ///
  96. /// \note The given buf MUST remain in scope during the lifetime of
  97. /// the LabelSequence created here.
  98. /// \note The buffer should never be modified except through
  99. /// calls to extend().
  100. /// \note Also, only associate the buffer with at most one
  101. /// LabelSequence. Behaviour is undefined if two LabelSequences are
  102. /// using the same buffer.
  103. ///
  104. /// \param src LabelSequence to copy the initial data from
  105. /// \param buf external buffer to store this labelsequence's data in
  106. LabelSequence(const LabelSequence& src, uint8_t buf[MAX_SERIALIZED_LENGTH]);
  107. /// \brief Copy constructor.
  108. ///
  109. /// \note The associated data MUST remain in scope during the lifetime
  110. /// of this LabelSequence, since only the pointers are copied.
  111. ///
  112. /// \note No validation is done on the given data upon construction;
  113. /// use with care.
  114. ///
  115. /// \param ls The LabelSequence to construct a LabelSequence from
  116. LabelSequence(const LabelSequence& ls):
  117. data_(ls.data_),
  118. offsets_(ls.offsets_),
  119. first_label_(ls.first_label_),
  120. last_label_(ls.last_label_)
  121. {}
  122. /// \brief Return the wire-format data for this LabelSequence
  123. ///
  124. /// The data is returned as a pointer to (the part of) the original
  125. /// wireformat data, from either the original Name object, or the
  126. /// raw data given in the constructor, and the given len value is
  127. /// set to the number of octets that match this labelsequence.
  128. ///
  129. /// \note The data pointed to is only valid if the original Name
  130. /// object or data is still in scope
  131. ///
  132. /// \param len Pointer to a size_t where the length of the data
  133. /// will be stored (in number of octets)
  134. /// \return Pointer to the wire-format data of this label sequence
  135. const uint8_t* getData(size_t* len) const;
  136. /// \brief Return the length of the wire-format data of this LabelSequence
  137. ///
  138. /// This method returns the number of octets for the data that would
  139. /// be returned by the \c getData() method.
  140. ///
  141. /// Note that the return value of this method is always positive.
  142. /// Note also that if the return value of this method is 1, it means the
  143. /// sequence consists of the null label, i.e., a single "dot", and vice
  144. /// versa.
  145. ///
  146. /// \note The data pointed to is only valid if the original Name
  147. /// object or data is still in scope
  148. ///
  149. /// \return The length of the data of the label sequence in octets.
  150. size_t getDataLength() const;
  151. /// \brief Return the size of serialized image of the \c LabelSequence.
  152. ///
  153. /// This method calculates the size of necessary storage to store
  154. /// serialized image of this \c LabelSequence (which would be dumped by
  155. /// \c serialize()) and returns it. The size is in bytes.
  156. ///
  157. /// \throw none.
  158. ///
  159. /// \return The size of serialized image of the \c LabelSequence.
  160. size_t getSerializedLength() const;
  161. /// \brief Serialize the \c LabelSequence object in to a buffer.
  162. ///
  163. /// This method dumps a serialized image of this \c LabelSequence
  164. /// that would be restored by the corresponding constructor into the
  165. /// given buffer. The buffer size must be at least equal to
  166. /// the value returned by getSerializedLength() (it can be larger than
  167. /// that).
  168. ///
  169. /// Be careful about where the buffer is located; due to the nature
  170. /// of the buffer, it's quite possible that the memory region is being used
  171. /// to construct another active \c LabelSequence. In such a case
  172. /// the serialization would silently break that sequence object, and
  173. /// it will be very difficult to identify the cause. This method
  174. /// has minimal level checks to avoid such disruption: If the serialization
  175. /// would break "this" \c LabelSequence object, it doesn't write anything
  176. /// to the given buffer and throw a \c isc::BadValue exception.
  177. ///
  178. /// In general, it should be safe to call this method on a
  179. /// \c LabelSequence object constructed from a \c Name object or
  180. /// a copy of such \c LabelSequence. When you construct \c LabelSequence
  181. /// from pre-serialized data, calling this method on it can be unsafe.
  182. /// One safe (but a bit less efficient) way in such a case is to make
  183. /// the source \c LabelSequence temporary and immediately create a
  184. /// local copy using an explicit buffer, and call this method on the
  185. /// latter:
  186. /// \code
  187. /// // don't do this, it's not safe (and would result in exception):
  188. /// // LabelSequence(buf).serialize(buf, buf_len);
  189. ///
  190. /// // The following are the safe way:
  191. /// uint8_t ext_buf[LabelSequence::MAX_SERIALIZED_LENGTH];
  192. /// LabelSequence seq(LabelSequence(buf), ext_buf);
  193. /// ... (strip the labels, etc)
  194. /// seq.serialize(buf, buf_len); // it's safe to override buf here
  195. /// \endcode
  196. ///
  197. /// The serialized image would be as follows:
  198. /// - olen: number of offsets (1 byte)
  199. /// - binary sequence of offsets (olen bytes, verbatim copy of offsets_
  200. /// of this size)
  201. /// - binary sequence of name data (length determined by itself, verbatim
  202. /// copy of data_ of the corresponding size)
  203. ///
  204. /// Applications must use the resulting image as opaque value and must not
  205. /// use it for other purposes than input to the corresponding constructor
  206. /// to restore it. Application behavior that assumes the specific
  207. /// organization of the image is not guaranteed.
  208. ///
  209. /// \throw isc::BadValue buf_len is too short (this method never throws
  210. /// otherwise) or the serialization would override internal data of
  211. /// of the source LabelSequence.
  212. ///
  213. /// \param buf Pointer to the placeholder to dump the serialized image
  214. /// \param buf_len The size of available region in \c buf
  215. void serialize(void* buf, size_t buf_len) const;
  216. /// \brief Compares two label sequences for equality.
  217. ///
  218. /// Performs a (optionally case-insensitive) comparison between this
  219. /// LabelSequence and another LabelSequence for equality.
  220. ///
  221. /// \param other The LabelSequence to compare with
  222. /// \param case_sensitive If true, comparison is case-insensitive
  223. /// \return true if The label sequences consist are the same length,
  224. /// and contain the same data.
  225. bool equals(const LabelSequence& other, bool case_sensitive = false) const;
  226. /// \brief Compares two label sequences.
  227. ///
  228. /// Performs a (optionally case-insensitive) comparison between this
  229. /// LabelSequence and another LabelSequence.
  230. ///
  231. /// \param other The LabelSequence to compare with
  232. /// \param case_sensitive If true, comparison is case-insensitive
  233. /// \return a <code>NameComparisonResult</code> object representing the
  234. /// comparison result.
  235. NameComparisonResult compare(const LabelSequence& other,
  236. bool case_sensitive = false) const;
  237. /// \brief Remove labels from the front of this LabelSequence
  238. ///
  239. /// \note No actual memory is changed, this operation merely updates the
  240. /// internal pointers based on the offsets in the Name object.
  241. ///
  242. /// \exception OutOfRange if i is greater than or equal to the number
  243. /// of labels currently pointed to by this LabelSequence
  244. ///
  245. /// \param i The number of labels to remove.
  246. void stripLeft(size_t i);
  247. /// \brief Remove labels from the end of this LabelSequence
  248. ///
  249. /// \note No actual memory is changed, this operation merely updates the
  250. /// internal pointers based on the offsets originally provided.
  251. ///
  252. /// \exception OutOfRange if i is greater than or equal to the number
  253. /// of labels currently pointed to by this LabelSequence
  254. ///
  255. /// \param i The number of labels to remove.
  256. void stripRight(size_t i);
  257. /// \brief Returns the current number of labels for this LabelSequence
  258. ///
  259. /// \return The number of labels
  260. size_t getLabelCount() const {
  261. return (last_label_ - first_label_ + 1);
  262. }
  263. /// \brief Convert the LabelSequence to a string.
  264. ///
  265. /// This method returns a <code>std::string</code> object representing the
  266. /// LabelSequence as a string. The returned string ends with a dot
  267. /// '.' if the label sequence is absolute.
  268. ///
  269. /// This function assumes the underlying data is in proper
  270. /// uncompressed wire format. If it finds an unexpected label
  271. /// character including compression pointer, an exception of class
  272. /// \c BadLabelType will be thrown. In addition, if resource
  273. /// allocation for the result string fails, a corresponding standard
  274. /// exception will be thrown.
  275. ///
  276. /// \return a string representation of the <code>LabelSequence</code>.
  277. std::string toText() const;
  278. /// \brief Extend this LabelSequence with the given labelsequence
  279. ///
  280. /// The given labels are appended to the name data, and internal
  281. /// offset data is updated accordingly.
  282. ///
  283. /// The data from the given LabelSequence is copied into the buffer
  284. /// associated with this LabelSequence; the appended LabelSequence
  285. /// (the 'labels' argument) can be released if it is not needed for
  286. /// other operations anymore.
  287. ///
  288. /// If this LabelSequence is absolute, its root label will be stripped
  289. /// before the given LabelSequence is appended; after extend(),
  290. /// this LabelSequence will be absolute if, and only if, the appended
  291. /// LabelSequence was. A side-effect of this property is that adding
  292. /// the root label to an absolute LabelSequence has no effect (the
  293. /// root label is stripped, then added again).
  294. ///
  295. /// Some minimal checking is done on the data, but internal integrity
  296. /// is not assumed. Do NOT modify the given buffer except through calls
  297. /// to this method, and do NOT call this method if the buffer is
  298. /// associated to another LabelSequence (behaviour of the other
  299. /// LabelSequence is undefined in that scenario).
  300. ///
  301. /// \exception BadValue If the buffer does not appear to be associated
  302. /// with this LabelSequence, or if the maximum wire length or maximum
  303. /// number of labels would be exceeded by this operation
  304. ///
  305. /// \param labels The labels to append to this LabelSequence
  306. /// \param buf The buffer associated with this LabelSequence
  307. void extend(const LabelSequence& labels,
  308. uint8_t buf[MAX_SERIALIZED_LENGTH]);
  309. private:
  310. /// \brief Convert the LabelSequence to a string.
  311. ///
  312. /// This method is a version of the zero-argument toText() method,
  313. /// that accepts a <code>omit_final_dot</code> argument. The
  314. /// returned string ends with a dot '.' if
  315. /// <code>omit_final_dot</code> is <code>false</code>.
  316. ///
  317. /// This method is used as a helper for <code>Name::toText()</code>
  318. /// only.
  319. ///
  320. /// \param omit_final_dot whether to omit the trailing dot in the output.
  321. /// \return a string representation of the <code>LabelSequence</code>.
  322. std::string toText(bool omit_final_dot) const;
  323. public:
  324. /// \brief Calculate a simple hash for the label sequence.
  325. ///
  326. /// This method calculates a hash value for the label sequence as binary
  327. /// data. If \c case_sensitive is false, it ignores the case stored in
  328. /// the labels; specifically, it normalizes the labels by converting all
  329. /// upper case characters to lower case ones and calculates the hash value
  330. /// for the result.
  331. ///
  332. /// This method is intended to provide a lightweight way to store a
  333. /// relatively small number of label sequences in a hash table.
  334. /// For this reason it only takes into account data up to 16 octets
  335. /// (16 was derived from BIND 9's implementation). Also, the function does
  336. /// not provide any unpredictability; a specific sequence will always have
  337. /// the same hash value. It should therefore not be used in the context
  338. /// where an untrusted third party can mount a denial of service attack by
  339. /// forcing the application to create a very large number of label
  340. /// sequences that have the same hash value and expected to be stored in
  341. /// a hash table.
  342. ///
  343. /// \exception None
  344. ///
  345. /// \param case_sensitive
  346. /// \return A hash value for this label sequence.
  347. size_t getHash(bool case_sensitive) const;
  348. /// \brief Checks whether the label sequence is absolute
  349. ///
  350. /// \return true if the last label is the root label
  351. bool isAbsolute() const;
  352. private:
  353. const uint8_t* data_; // wire-format name data
  354. const uint8_t* offsets_; // an array of offsets in data_ for the labels
  355. size_t first_label_; // index of offsets_ for the first label
  356. size_t last_label_; // index of offsets_ for the last label.
  357. // can be equal to first_label_, but must not
  358. // be smaller (the class ensures that)
  359. };
  360. ///
  361. /// \brief Insert the label sequence as a string into stream.
  362. ///
  363. /// This method convert the \c label_sequence into a string and inserts
  364. /// it into the output stream \c os.
  365. ///
  366. /// This function overloads the global operator<< to behave as described in
  367. /// ostream::operator<< but applied to \c LabelSequence objects.
  368. ///
  369. /// \param os A \c std::ostream object on which the insertion operation is
  370. /// performed.
  371. /// \param label_sequence The \c LabelSequence object output by the operation.
  372. /// \return A reference to the same \c std::ostream object referenced by
  373. /// parameter \c os after the insertion operation.
  374. std::ostream&
  375. operator<<(std::ostream& os, const LabelSequence& label_sequence);
  376. } // end namespace dns
  377. } // end namespace isc
  378. #endif
  379. // Local Variables:
  380. // mode: c++
  381. // End: