labelsequence.h 11.8 KB
Newer Older
Jelte Jansen's avatar
Jelte Jansen committed
1
// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
Jelte Jansen's avatar
Jelte Jansen committed
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#ifndef __LABELSEQUENCE_H
#define __LABELSEQUENCE_H 1

#include <dns/name.h>
#include <util/buffer.h>

namespace isc {
namespace dns {

Jelte Jansen's avatar
Jelte Jansen committed
24
/// \brief Light-weight Accessor to data of Name object
Jelte Jansen's avatar
Jelte Jansen committed
25
26
///
/// The purpose of this class is to easily match Names and parts of Names,
Jelte Jansen's avatar
Jelte Jansen committed
27
/// without needing to copy the underlying data on each label strip.
Jelte Jansen's avatar
Jelte Jansen committed
28
///
Jelte Jansen's avatar
Jelte Jansen committed
29
30
/// It can only work on existing Name objects, or data as provided by the
/// Name object or another LabelSequence, and the data or Name MUST
Jelte Jansen's avatar
Jelte Jansen committed
31
32
33
34
/// remain in scope during the entire lifetime of its associated
/// LabelSequence(s).
///
/// Upon creation of a LabelSequence, it records the offsets of the
Jelte Jansen's avatar
Jelte Jansen committed
35
36
/// labels in the wireformat data of the Name. When stripLeft() or
/// stripRight() is called on the LabelSequence, no changes in the
Jelte Jansen's avatar
Jelte Jansen committed
37
/// original data occur, but the internal pointers of the
Jelte Jansen's avatar
Jelte Jansen committed
38
/// LabelSequence are modified.
Jelte Jansen's avatar
Jelte Jansen committed
39
40
41
///
/// LabelSequences can be compared to other LabelSequences, and their
/// data can be requested (which then points to part of the original
Jelte Jansen's avatar
Jelte Jansen committed
42
/// data of the original Name object).
Jelte Jansen's avatar
Jelte Jansen committed
43
class LabelSequence {
44
45
46
    // Name calls the private toText(bool) method of LabelSequence.
    friend std::string Name::toText(bool) const;

Jelte Jansen's avatar
Jelte Jansen committed
47
public:
Jelte Jansen's avatar
Jelte Jansen committed
48
49
50
51
52
53
54
55
    /// \brief Constructs a LabelSequence for the given name
    ///
    /// \note The associated Name MUST remain in scope during the lifetime
    /// of this LabelSequence, since getData() refers to data from the
    /// Name object (the only data the LabelSequence stores are pointers
    /// to the labels in the Name object).
    ///
    /// \param name The Name to construct a LabelSequence for
Jelte Jansen's avatar
Jelte Jansen committed
56
    explicit LabelSequence(const Name& name):
57
58
59
                                     data_(&name.ndata_[0]),
                                     offsets_(&name.offsets_[0]),
                                     offsets_size_(name.offsets_.size()),
Jelte Jansen's avatar
Jelte Jansen committed
60
61
62
                                     first_label_(0),
                                     last_label_(name.getLabelCount())
    {}
Jelte Jansen's avatar
Jelte Jansen committed
63

64
65
66
67
68
69
70
71
    /// \brief Constructs a LabelSequence for the given data
    ///
    /// \note The associated data MUST remain in scope during the lifetime
    /// of this LabelSequence, since only the pointers are copied.
    ///
    /// \note No validation is done on the given data upon construction;
    ///       use with care.
    ///
72
73
74
    /// \exception isc::BadValue if basic checks for the input data, or
    ///            offsets fails.
    ///
Jelte Jansen's avatar
Jelte Jansen committed
75
76
77
    /// \param data The raw data for the domain name, in wire format
    /// \param offsets The offsets of the labels in the domain name data,
    ///        as given by a Name object or another LabelSequence
78
79
80
    /// \param offsets_size The size of the offsets data
    LabelSequence(const uint8_t* data,
                  const uint8_t* offsets,
81
                  size_t offsets_size);
82

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
    /// \brief Copy constructor.
    ///
    /// \note The associated data MUST remain in scope during the lifetime
    /// of this LabelSequence, since only the pointers are copied.
    ///
    /// \note No validation is done on the given data upon construction;
    ///       use with care.
    ///
    /// \param ls The LabelSequence to construct a LabelSequence from
    LabelSequence(const LabelSequence& ls):
                                     data_(ls.data_),
                                     offsets_(ls.offsets_),
                                     offsets_size_(ls.offsets_size_),
                                     first_label_(ls.first_label_),
                                     last_label_(ls.last_label_)
    {}

Jelte Jansen's avatar
Jelte Jansen committed
100
101
    /// \brief Return the wire-format data for this LabelSequence
    ///
Jelte Jansen's avatar
Jelte Jansen committed
102
103
104
    /// The data is returned as a pointer to (the part of) the original
    /// wireformat data, from either the original Name object, or the
    /// raw data given in the constructor, and the given len value is
Jelte Jansen's avatar
Jelte Jansen committed
105
106
107
    /// set to the number of octets that match this labelsequence.
    ///
    /// \note The data pointed to is only valid if the original Name
Jelte Jansen's avatar
Jelte Jansen committed
108
    /// object or data is still in scope
Jelte Jansen's avatar
Jelte Jansen committed
109
110
    ///
    /// \param len Pointer to a size_t where the length of the data
Jelte Jansen's avatar
Jelte Jansen committed
111
    ///        will be stored (in number of octets)
Jelte Jansen's avatar
Jelte Jansen committed
112
    /// \return Pointer to the wire-format data of this label sequence
113
    const uint8_t* getData(size_t* len) const;
Jelte Jansen's avatar
Jelte Jansen committed
114

115
116
117
118
119
120
121
122
123
124
    /// \brief Return the offset data for this LabelSequence
    ///
    /// The offsets are returned in the <code>placeholder</code> array.
    ///
    /// \param len Pointer to a size_t where the number of offsets
    ///        will be stored
    /// \param placeholder Array where the offset data will be returned
    void getOffsetData(size_t* len,
                       uint8_t placeholder[Name::MAX_LABELS]) const;

125
126
127
128
129
130
131
132
133
134
135
    /// \brief Return the length of the wire-format data of this LabelSequence
    ///
    /// This method returns the number of octets for the data that would
    /// be returned by the \c getData() method.
    ///
    /// Note that the return value of this method is always positive.
    /// Note also that if the return value of this method is 1, it means the
    /// sequence consists of the null label, i.e., a single "dot", and vice
    /// versa.
    ///
    /// \note The data pointed to is only valid if the original Name
Jelte Jansen's avatar
Jelte Jansen committed
136
    /// object or data is still in scope
137
138
139
140
    ///
    /// \return The length of the data of the label sequence in octets.
    size_t getDataLength() const;

141
    /// \brief Compares two label sequences for equality.
Jelte Jansen's avatar
Jelte Jansen committed
142
143
    ///
    /// Performs a (optionally case-insensitive) comparison between this
144
    /// LabelSequence and another LabelSequence for equality.
Jelte Jansen's avatar
Jelte Jansen committed
145
146
147
148
149
    ///
    /// \param other The LabelSequence to compare with
    /// \param case_sensitive If true, comparison is case-insensitive
    /// \return true if The label sequences consist are the same length,
    ///         and contain the same data.
Jelte Jansen's avatar
Jelte Jansen committed
150
151
    bool equals(const LabelSequence& other, bool case_sensitive = false) const;

152
153
154
155
156
157
158
159
160
161
162
163
    /// \brief Compares two label sequences.
    ///
    /// Performs a (optionally case-insensitive) comparison between this
    /// LabelSequence and another LabelSequence.
    ///
    /// \param other The LabelSequence to compare with
    /// \param case_sensitive If true, comparison is case-insensitive
    /// \return a <code>NameComparisonResult</code> object representing the
    /// comparison result.
    NameComparisonResult compare(const LabelSequence& other,
                                 bool case_sensitive = false) const;

Jelte Jansen's avatar
Jelte Jansen committed
164
    /// \brief Remove labels from the front of this LabelSequence
Jelte Jansen's avatar
Jelte Jansen committed
165
    ///
Jelte Jansen's avatar
Jelte Jansen committed
166
167
168
    /// \note No actual memory is changed, this operation merely updates the
    /// internal pointers based on the offsets in the Name object.
    ///
169
    /// \exception OutOfRange if i is greater than or equal to the number
Jelte Jansen's avatar
Jelte Jansen committed
170
171
172
    ///           of labels currently pointed to by this LabelSequence
    ///
    /// \param i The number of labels to remove.
Jelte Jansen's avatar
Jelte Jansen committed
173
    void stripLeft(size_t i);
Jelte Jansen's avatar
Jelte Jansen committed
174
175

    /// \brief Remove labels from the end of this LabelSequence
Jelte Jansen's avatar
Jelte Jansen committed
176
177
    ///
    /// \note No actual memory is changed, this operation merely updates the
Jelte Jansen's avatar
Jelte Jansen committed
178
    /// internal pointers based on the offsets originally provided.
Jelte Jansen's avatar
Jelte Jansen committed
179
    ///
180
    /// \exception OutOfRange if i is greater than or equal to the number
Jelte Jansen's avatar
Jelte Jansen committed
181
    ///           of labels currently pointed to by this LabelSequence
Jelte Jansen's avatar
Jelte Jansen committed
182
    ///
Jelte Jansen's avatar
Jelte Jansen committed
183
    /// \param i The number of labels to remove.
Jelte Jansen's avatar
Jelte Jansen committed
184
    void stripRight(size_t i);
Jelte Jansen's avatar
Jelte Jansen committed
185

Jelte Jansen's avatar
Jelte Jansen committed
186
187
188
    /// \brief Returns the current number of labels for this LabelSequence
    ///
    /// \return The number of labels
189
    size_t getLabelCount() const { return (last_label_ - first_label_); }
190

191
192
193
194
    /// \brief Convert the LabelSequence to a string.
    ///
    /// This method returns a <code>std::string</code> object representing the
    /// LabelSequence as a string.  The returned string ends with a dot
195
    /// '.' if the label sequence is absolute.
196
    ///
Jelte Jansen's avatar
Jelte Jansen committed
197
    /// This function assumes the underlying data is in proper
198
199
200
201
202
    /// uncompressed wire format.  If it finds an unexpected label
    /// character including compression pointer, an exception of class
    /// \c BadLabelType will be thrown.  In addition, if resource
    /// allocation for the result string fails, a corresponding standard
    /// exception will be thrown.
Jelte Jansen's avatar
Jelte Jansen committed
203
    ///
204
    /// \return a string representation of the <code>LabelSequence</code>.
205
    std::string toText() const;
206

207
private:
208
209
    /// \brief Convert the LabelSequence to a string.
    ///
210
211
212
213
    /// This method is a version of the zero-argument toText() method,
    /// that accepts a <code>omit_final_dot</code> argument. The
    /// returned string ends with a dot '.' if
    /// <code>omit_final_dot</code> is <code>false</code>.
214
    ///
215
216
217
    /// This method is used as a helper for <code>Name::toText()</code>
    /// only.
    ///
218
    /// \param omit_final_dot whether to omit the trailing dot in the output.
219
    /// \return a string representation of the <code>LabelSequence</code>.
220
    std::string toText(bool omit_final_dot) const;
221

222
public:
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
    /// \brief Calculate a simple hash for the label sequence.
    ///
    /// This method calculates a hash value for the label sequence as binary
    /// data.  If \c case_sensitive is false, it ignores the case stored in
    /// the labels; specifically, it normalizes the labels by converting all
    /// upper case characters to lower case ones and calculates the hash value
    /// for the result.
    ///
    /// This method is intended to provide a lightweight way to store a
    /// relatively small number of label sequences in a hash table.
    /// For this reason it only takes into account data up to 16 octets
    /// (16 was derived from BIND 9's implementation).  Also, the function does
    /// not provide any unpredictability; a specific sequence will always have
    /// the same hash value.  It should therefore not be used in the context
    /// where an untrusted third party can mount a denial of service attack by
    /// forcing the application to create a very large number of label
    /// sequences that have the same hash value and expected to be stored in
    /// a hash table.
    ///
    /// \exception None
    ///
    /// \param case_sensitive
    /// \return A hash value for this label sequence.
    size_t getHash(bool case_sensitive) const;

Jelte Jansen's avatar
Jelte Jansen committed
248
249
250
251
252
    /// \brief Checks whether the label sequence is absolute
    ///
    /// \return true if the last label is the root label
    bool isAbsolute() const;

Jelte Jansen's avatar
Jelte Jansen committed
253
private:
254
255
256
    const uint8_t* data_;
    const uint8_t* offsets_;
    size_t offsets_size_;
Jelte Jansen's avatar
Jelte Jansen committed
257
258
259
260
261
    size_t first_label_;
    size_t last_label_;
};


262
263
264
265
266
267
268
269
270
271
272
///
/// \brief Insert the label sequence as a string into stream.
///
/// This method convert the \c label_sequence into a string and inserts
/// it into the output stream \c os.
///
/// This function overloads the global operator<< to behave as described in
/// ostream::operator<< but applied to \c LabelSequence objects.
///
/// \param os A \c std::ostream object on which the insertion operation is
/// performed.
Jelte Jansen's avatar
Jelte Jansen committed
273
/// \param label_sequence The \c LabelSequence object output by the operation.
274
275
276
277
278
/// \return A reference to the same \c std::ostream object referenced by
/// parameter \c os after the insertion operation.
std::ostream&
operator<<(std::ostream& os, const LabelSequence& label_sequence);

Jelte Jansen's avatar
Jelte Jansen committed
279
280
281
282
} // end namespace dns
} // end namespace isc

#endif
283
284
285
286

// Local Variables:
// mode: c++
// End: