labelsequence.h 7.17 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
25
26
/// \brief Light-weight Accessor to Name object
///
/// 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
29
30
31
32
33
///
/// It can only work on existing Name objects, and the Name object MUST
/// 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
34
35
36
37
/// labels in the wireformat data of the Name. When stripLeft() or
/// stripRight() is called on the LabelSequence, no changes in the
/// Name's data occur, but the internal pointers of the
/// LabelSequence are modified.
Jelte Jansen's avatar
Jelte Jansen committed
38
39
40
41
42
///
/// LabelSequences can be compared to other LabelSequences, and their
/// data can be requested (which then points to part of the original
/// data of the associated Name object).
///
Jelte Jansen's avatar
Jelte Jansen committed
43
44
class LabelSequence {
public:
Jelte Jansen's avatar
Jelte Jansen committed
45
46
47
48
49
50
51
52
    /// \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
53
    LabelSequence(const Name& name): name_(name),
Jelte Jansen's avatar
Jelte Jansen committed
54
55
56
                                     first_label_(0),
                                     last_label_(name.getLabelCount())
    {}
Jelte Jansen's avatar
Jelte Jansen committed
57
58
59
60
61
62
63
64
65
66
67

    /// \brief Return the wire-format data for this LabelSequence
    ///
    /// The data, is returned as a pointer to the original wireformat
    /// data of the original Name object, and the given len value is
    /// set to the number of octets that match this labelsequence.
    ///
    /// \note The data pointed to is only valid if the original Name
    /// object is still in scope
    ///
    /// \param len Pointer to a size_t where the length of the data
Jelte Jansen's avatar
Jelte Jansen committed
68
    ///        will be stored (in number of octets)
Jelte Jansen's avatar
Jelte Jansen committed
69
    /// \return Pointer to the wire-format data of this label sequence
Jelte Jansen's avatar
Jelte Jansen committed
70
71
    const char* getData(size_t* len) const;

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
    /// \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
    /// object is still in scope
    ///
    /// \return The length of the data of the label sequence in octets.
    size_t getDataLength() const;

Jelte Jansen's avatar
Jelte Jansen committed
88
89
90
91
92
93
94
95
96
    /// \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 true if The label sequences consist are the same length,
    ///         and contain the same data.
Jelte Jansen's avatar
Jelte Jansen committed
97
98
    bool equals(const LabelSequence& other, bool case_sensitive = false) const;

Jelte Jansen's avatar
Jelte Jansen committed
99
    /// \brief Remove labels from the front of this LabelSequence
Jelte Jansen's avatar
Jelte Jansen committed
100
    ///
Jelte Jansen's avatar
Jelte Jansen committed
101
102
103
104
105
106
107
    /// \note No actual memory is changed, this operation merely updates the
    /// internal pointers based on the offsets in the Name object.
    ///
    /// \exeption OutOfRange if i is greater than or equal to the number
    ///           of labels currently pointed to by this LabelSequence
    ///
    /// \param i The number of labels to remove.
Jelte Jansen's avatar
Jelte Jansen committed
108
    void stripLeft(size_t i);
Jelte Jansen's avatar
Jelte Jansen committed
109
110

    /// \brief Remove labels from the end of this LabelSequence
Jelte Jansen's avatar
Jelte Jansen committed
111
112
    ///
    /// \note No actual memory is changed, this operation merely updates the
Jelte Jansen's avatar
Jelte Jansen committed
113
    /// internal pointers based on the offsets in the Name object.
Jelte Jansen's avatar
Jelte Jansen committed
114
    ///
Jelte Jansen's avatar
Jelte Jansen committed
115
116
    /// \exeption OutOfRange if i is greater than or equal to the number
    ///           of labels currently pointed to by this LabelSequence
Jelte Jansen's avatar
Jelte Jansen committed
117
    ///
Jelte Jansen's avatar
Jelte Jansen committed
118
    /// \param i The number of labels to remove.
Jelte Jansen's avatar
Jelte Jansen committed
119
    void stripRight(size_t i);
Jelte Jansen's avatar
Jelte Jansen committed
120

Jelte Jansen's avatar
Jelte Jansen committed
121
122
123
    /// \brief Returns the current number of labels for this LabelSequence
    ///
    /// \return The number of labels
124
    size_t getLabelCount() const { return (last_label_ - first_label_); }
125

Jelte Jansen's avatar
Jelte Jansen committed
126
127
128
129
130
131
132
133
134
    /// \brief Returns the original Name object associated with this
    ///        LabelSequence
    ///
    /// While the Name should still be in scope during the lifetime of
    /// the LabelSequence, it can still be useful to have access to it,
    /// for instance in helper functions that are only passed the
    /// LabelSequence itself.
    ///
    /// \return Reference to the original Name object
135
    const Name& getName() const { return (name_); }
Jelte Jansen's avatar
Jelte Jansen committed
136

137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
    /// \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
162
163
164
165
166
    /// \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
167
private:
168
    const Name& name_;
Jelte Jansen's avatar
Jelte Jansen committed
169
170
171
172
173
174
175
176
177
    size_t first_label_;
    size_t last_label_;
};


} // end namespace dns
} // end namespace isc

#endif