Branch data Line data Source code
1 : : // Copyright (C) 2011 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 : :
15 : : #ifndef __DS_LIKE_H
16 : : #define __DS_LIKE_H 1
17 : :
18 : : #include <stdint.h>
19 : :
20 : : #include <iostream>
21 : : #include <sstream>
22 : : #include <string>
23 : : #include <vector>
24 : :
25 : : #include <boost/lexical_cast.hpp>
26 : :
27 : : #include <exceptions/exceptions.h>
28 : :
29 : : #include <dns/messagerenderer.h>
30 : : #include <dns/name.h>
31 : : #include <dns/rdata.h>
32 : : #include <dns/rdataclass.h>
33 : :
34 : : namespace isc {
35 : : namespace dns {
36 : : namespace rdata {
37 : : namespace generic {
38 : : namespace detail {
39 : :
40 : : /// \brief \c rdata::DSLikeImpl class represents the DS-like RDATA for DS
41 : : /// and DLV types.
42 : : ///
43 : : /// This class implements the basic interfaces inherited by the DS and DLV
44 : : /// classes from the abstract \c rdata::Rdata class, and provides trivial
45 : : /// accessors to DS-like RDATA.
46 : 394 : template <class Type, uint16_t typeCode> class DSLikeImpl {
47 : : // Common sequence of toWire() operations used for the two versions of
48 : : // toWire().
49 : : template <typename Output>
50 : : void
51 : : toWireCommon(Output& output) const {
52 : 2 : output.writeUint16(tag_);
53 : 2 : output.writeUint8(algorithm_);
54 : 2 : output.writeUint8(digest_type_);
55 : 2 : output.writeData(&digest_[0], digest_.size());
56 : : }
57 : :
58 : : public:
59 : : /// \brief Constructor from string.
60 : : ///
61 : : /// <b>Exceptions</b>
62 : : ///
63 : : /// \c InvalidRdataText is thrown if the method cannot process the
64 : : /// parameter data for any of the number of reasons.
65 : 386 : DSLikeImpl(const std::string& ds_str) {
66 [ + - + - ]: 748 : std::istringstream iss(ds_str);
[ + - + - ]
67 : : // peekc should be of iss's char_type for isspace to work
68 : : std::istringstream::char_type peekc;
69 : 748 : std::stringbuf digestbuf;
70 : : uint32_t tag, algorithm, digest_type;
71 : :
72 : 748 : iss >> tag >> algorithm >> digest_type;
73 [ + - ][ + + ]: 374 : if (iss.bad() || iss.fail()) {
[ + + ][ + - ]
[ + + ][ + + ]
74 [ + - ][ + - ]: 4 : isc_throw(InvalidRdataText,
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
75 : : "Invalid " << RRType(typeCode) << " text");
76 : : }
77 [ + + ][ + + ]: 372 : if (tag > 0xffff) {
78 [ + - ][ + - ]: 4 : isc_throw(InvalidRdataText,
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
79 : : RRType(typeCode) << " tag out of range");
80 : : }
81 [ + + ][ + + ]: 370 : if (algorithm > 0xff) {
82 [ + - ][ + - ]: 4 : isc_throw(InvalidRdataText,
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
83 : : RRType(typeCode) << " algorithm out of range");
84 : : }
85 [ + + ][ + + ]: 368 : if (digest_type > 0xff) {
86 [ + - ][ + - ]: 4 : isc_throw(InvalidRdataText,
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
87 : : RRType(typeCode) << " digest type out of range");
88 : : }
89 : :
90 [ + - ][ + - ]: 366 : iss.read(&peekc, 1);
91 [ + + + - ]: 730 : if (!iss.good() || !isspace(peekc, iss.getloc())) {
[ + + ][ + + ]
[ + + ]
[ + + + - ]
[ + + ][ + + ]
[ + + ]
92 [ + - ][ + - ]: 8 : isc_throw(InvalidRdataText,
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
93 : : RRType(typeCode) << " presentation format error");
94 : : }
95 : :
96 [ + - ][ + - ]: 362 : iss >> &digestbuf;
97 : :
98 : 362 : tag_ = tag;
99 : 362 : algorithm_ = algorithm;
100 : 362 : digest_type_ = digest_type;
101 [ + - ][ + - ]: 362 : decodeHex(digestbuf.str(), digest_);
[ + - ][ + - ]
102 : 362 : }
103 : :
104 : : /// \brief Constructor from wire-format data.
105 : : ///
106 : : /// \param buffer A buffer storing the wire format data.
107 : : /// \param rdata_len The length of the RDATA in bytes, normally expected
108 : : /// to be the value of the RDLENGTH field of the corresponding RR.
109 : : ///
110 : : /// <b>Exceptions</b>
111 : : ///
112 : : /// \c InvalidRdataLength is thrown if the input data is too short for the
113 : : /// type.
114 : 2 : DSLikeImpl(InputBuffer& buffer, size_t rdata_len) {
115 [ - + ][ - + ]: 2 : if (rdata_len < 4) {
116 [ # # ][ # # ]: 0 : isc_throw(InvalidRdataLength, RRType(typeCode) << " too short");
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
117 : : }
118 : :
119 [ + - ][ + - ]: 2 : tag_ = buffer.readUint16();
120 [ + - ][ + - ]: 2 : algorithm_ = buffer.readUint8();
121 [ + - ][ + - ]: 2 : digest_type_ = buffer.readUint8();
122 : :
123 : 2 : rdata_len -= 4;
124 [ + - ][ + - ]: 2 : digest_.resize(rdata_len);
125 [ + - ][ + - ]: 2 : buffer.readData(&digest_[0], rdata_len);
126 : 2 : }
127 : :
128 : : /// \brief The copy constructor.
129 : : ///
130 : : /// Trivial for now, we could've used the default one.
131 : 30 : DSLikeImpl(const DSLikeImpl& source) {
132 [ + - ][ + - ]: 30 : digest_ = source.digest_;
133 : 30 : tag_ = source.tag_;
134 : 30 : algorithm_ = source.algorithm_;
135 : 30 : digest_type_ = source.digest_type_;
136 : 30 : }
137 : :
138 : : /// \brief Convert the DS-like data to a string.
139 : : ///
140 : : /// \return A \c string object that represents the DS-like data.
141 : : std::string
142 : 36 : toText() const {
143 : : using namespace boost;
144 : : return (lexical_cast<string>(static_cast<int>(tag_)) +
145 : : " " + lexical_cast<string>(static_cast<int>(algorithm_)) +
146 : : " " + lexical_cast<string>(static_cast<int>(digest_type_)) +
147 [ + - ][ + - ]: 36 : " " + encodeHex(digest_));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
148 : : }
149 : :
150 : : /// \brief Render the DS-like data in the wire format to an OutputBuffer
151 : : /// object.
152 : : ///
153 : : /// \param buffer An output buffer to store the wire data.
154 : : void
155 : : toWire(OutputBuffer& buffer) const {
156 : : toWireCommon(buffer);
157 : : }
158 : :
159 : : /// \brief Render the DS-like data in the wire format to an
160 : : /// AbstractMessageRenderer object.
161 : : ///
162 : : /// \param renderer A renderer object to send the wire data to.
163 : : void
164 : : toWire(AbstractMessageRenderer& renderer) const {
165 : : toWireCommon(renderer);
166 : : }
167 : :
168 : : /// \brief Compare two instances of DS-like RDATA.
169 : : ///
170 : : /// It is up to the caller to make sure that \c other is an object of the
171 : : /// same \c DSLikeImpl class.
172 : : ///
173 : : /// \param other the right-hand operand to compare against.
174 : : /// \return < 0 if \c this would be sorted before \c other.
175 : : /// \return 0 if \c this is identical to \c other in terms of sorting
176 : : /// order.
177 : : /// \return > 0 if \c this would be sorted after \c other.
178 : : int
179 : : compare(const DSLikeImpl& other_ds) const {
180 [ + + ][ + + ]: 35 : if (tag_ != other_ds.tag_) {
181 [ + + ][ + + ]: 4 : return (tag_ < other_ds.tag_ ? -1 : 1);
182 : : }
183 [ + + ][ + + ]: 31 : if (algorithm_ != other_ds.algorithm_) {
184 [ + + ][ + + ]: 4 : return (algorithm_ < other_ds.algorithm_ ? -1 : 1);
185 : : }
186 [ + + ][ + + ]: 27 : if (digest_type_ != other_ds.digest_type_) {
187 [ + + ][ + + ]: 4 : return (digest_type_ < other_ds.digest_type_ ? -1 : 1);
188 : : }
189 : :
190 : 23 : size_t this_len = digest_.size();
191 : 23 : size_t other_len = other_ds.digest_.size();
192 : 23 : size_t cmplen = min(this_len, other_len);
193 : 23 : int cmp = memcmp(&digest_[0], &other_ds.digest_[0], cmplen);
194 [ + + ][ + + ]: 23 : if (cmp != 0) {
195 : : return (cmp);
196 : : } else {
197 : : return ((this_len == other_len)
198 [ - + ][ # # ]: 15 : ? 0 : (this_len < other_len) ? -1 : 1);
[ - + ][ # # ]
199 : : }
200 : : }
201 : :
202 : : /// \brief Accessors
203 : : uint16_t
204 : 0 : getTag() const {
205 : 0 : return (tag_);
206 : : }
207 : :
208 : : private:
209 : : // straightforward representation of DS RDATA fields
210 : : uint16_t tag_;
211 : : uint8_t algorithm_;
212 : : uint8_t digest_type_;
213 : : std::vector<uint8_t> digest_;
214 : : };
215 : :
216 : : }
217 : : }
218 : : }
219 : : }
220 : : }
221 : : #endif // __DS_LIKE_H
222 : :
223 : : // Local Variables:
224 : : // mode: c++
225 : : // End:
|