Branch data Line data Source code
1 : : // Copyright (C) 2010 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 __RDATA_H
16 : : #define __RDATA_H 1
17 : :
18 : : #include <stdint.h>
19 : :
20 : : #include <boost/shared_ptr.hpp>
21 : :
22 : : #include <exceptions/exceptions.h>
23 : :
24 : : namespace isc {
25 : : namespace util {
26 : : class InputBuffer;
27 : : class OutputBuffer;
28 : : }
29 : : namespace dns {
30 : : class AbstractMessageRenderer;
31 : : class RRType;
32 : : class RRClass;
33 : : class Name;
34 : :
35 : : namespace rdata {
36 : :
37 : : ///
38 : : /// \brief A standard DNS module exception that is thrown if RDATA parser
39 : : /// encounters an invalid or inconsistent data length.
40 : : ///
41 : 33 : class InvalidRdataLength : public Exception {
42 : : public:
43 : 5 : InvalidRdataLength(const char* file, size_t line, const char* what) :
44 [ + - ][ + - ]: 33 : isc::Exception(file, line, what) {}
[ + - ][ + - ]
[ + - ][ + - ]
45 : : };
46 : :
47 : : ///
48 : : /// \brief A standard DNS module exception that is thrown if RDATA parser
49 : : /// fails to recognize a given textual representation.
50 : : ///
51 : 125 : class InvalidRdataText : public Exception {
52 : : public:
53 : 96 : InvalidRdataText(const char* file, size_t line, const char* what) :
54 [ + - ][ + - ]: 130 : isc::Exception(file, line, what) {}
[ + - ][ + - ]
[ + - ][ + + ]
55 : : };
56 : :
57 : : ///
58 : : /// \brief A standard DNS module exception that is thrown if RDATA parser
59 : : /// parser encounters a character-string (as defined in RFC1035) exceeding
60 : : /// the maximum allowable length (\c MAX_CHARSTRING_LEN).
61 : : ///
62 : 6 : class CharStringTooLong : public Exception {
63 : : public:
64 : : CharStringTooLong(const char* file, size_t line, const char* what) :
65 [ + - ][ + - ]: 6 : isc::Exception(file, line, what) {}
66 : : };
67 : :
68 : : // Forward declaration to define RdataPtr.
69 : : class Rdata;
70 : :
71 : : ///
72 : : /// The \c RdataPtr type is a pointer-like type, pointing to an
73 : : /// object of some concrete derived class of \c Rdata.
74 : : ///
75 : : typedef boost::shared_ptr<Rdata> RdataPtr;
76 : : typedef boost::shared_ptr<const Rdata> ConstRdataPtr;
77 : :
78 : : /// \brief Possible maximum length of RDATA, which is the maximum unsigned
79 : : /// 16 bit value.
80 : : const size_t MAX_RDLENGTH = 65535;
81 : :
82 : : /// \brief The maximum allowable length of character-string containing in
83 : : /// RDATA as defined in RFC1035, not including the 1-byte length field.
84 : : const unsigned int MAX_CHARSTRING_LEN = 255;
85 : :
86 : : /// \brief The \c Rdata class is an abstract base class that provides
87 : : /// a set of common interfaces to manipulate concrete RDATA objects.
88 : : ///
89 : : /// Generally, a separate derived class directly inherited from the base
90 : : /// \c Rdata class is defined for each well known RDATA.
91 : : /// Each of such classes will define the common logic based on the
92 : : /// corresponding protocol standard.
93 : : ///
94 : : /// Since some types of RRs are class specific and the corresponding RDATA
95 : : /// may have different semantics (e.g. type A for class IN and type A for
96 : : /// class CH have different representations and semantics), we separate
97 : : /// \c Rdata derived classes for such RR types in different namespaces.
98 : : /// The namespace of types specific to a class is named the lower-cased class
99 : : /// name; for example, RDATA of class IN-specific types are defined in the
100 : : /// \c in namespace, and RDATA of class CH-specific types are defined in
101 : : /// the \c ch namespace, and so on.
102 : : /// The derived classes are named using the RR type name (upper cased) such as
103 : : /// \c A or \c AAAA.
104 : : /// Thus RDATA of type A RR for class IN and CH are defined as \c in::A and
105 : : /// \c ch::A, respectively.
106 : : /// Many other RR types are class independent; the derived \c Rdata classes
107 : : /// for such RR types are defined in the \c generic namespace. Examples are
108 : : /// \c generic::NS and \c generic::SOA.
109 : : ///
110 : : /// If applications need to refer to these derived classes, it is generally
111 : : /// recommended to prepend at least some part of the namespace because the
112 : : /// same class name can be used in different namespaces.
113 : : /// So, instead of doing
114 : : /// \code using namespace isc::dns::rdata::in;
115 : : /// A& rdata_type_a; \endcode
116 : : /// it is advisable to prepend at least \c in from the namespace:
117 : : /// \code using namespace isc::dns::rdata;
118 : : /// in::A& rdata_type_a; \endcode
119 : : ///
120 : : /// In many cases, however, an application doesn't have to care about such
121 : : /// derived classes.
122 : : /// For instance, to parse an incoming DNS message an application wouldn't
123 : : /// have to perform type specific operation unless the application is
124 : : /// specifically concerned about a particular type.
125 : : /// So, this API generally handles \c Rdata in a polymorphic way through
126 : : /// a pointer or reference to this base abstract class.
127 : : class Rdata {
128 : : ///
129 : : /// \name Constructors and Destructor
130 : : ///
131 : : /// Note: The copy constructor and the assignment operator are intentionally
132 : : /// defined as private. Concrete classes should generally specialize their
133 : : /// own versions of these methods.
134 : : //@{
135 : : protected:
136 : : /// The default constructor.
137 : : ///
138 : : /// This is intentionally defined as \c protected as this base class should
139 : : /// never be instantiated (except as part of a derived class). In many
140 : : /// cases, the derived class wouldn't define a public default constructor
141 : : /// either, because an \c Rdata object without concrete data isn't
142 : : /// meaningful.
143 : 42316 : Rdata() {}
144 : : private:
145 : : Rdata(const Rdata& source);
146 : : void operator=(const Rdata& source);
147 : : public:
148 : : /// The destructor.
149 [ + - ][ + - ]: 42301 : virtual ~Rdata() {};
[ + - ]
150 : : //@}
151 : :
152 : : ///
153 : : /// \name Converter methods
154 : : ///
155 : : //@{
156 : : /// \brief Convert an \c Rdata to a string.
157 : : ///
158 : : /// This method returns a \c std::string object representing the \c Rdata.
159 : : ///
160 : : /// This is a pure virtual method without the definition; the actual
161 : : /// representation is specific to each derived concrete class and
162 : : /// should be explicitly defined in the derived class.
163 : : ///
164 : : /// \return A string representation of \c Rdata.
165 : : virtual std::string toText() const = 0;
166 : :
167 : : /// \brief Render the \c Rdata in the wire format into a buffer.
168 : : ///
169 : : /// This is a pure virtual method without the definition; the actual
170 : : /// conversion is specific to each derived concrete class and
171 : : /// should be explicitly defined in the derived class.
172 : : ///
173 : : /// \param buffer An output buffer to store the wire data.
174 : : virtual void toWire(isc::util::OutputBuffer& buffer) const = 0;
175 : :
176 : : /// \brief Render the \c Rdata in the wire format into a
177 : : /// \c MessageRenderer object.
178 : : ///
179 : : /// This is a pure virtual method without the definition; the actual
180 : : /// conversion is specific to each derived concrete class and
181 : : /// should be explicitly defined in the derived class.
182 : : ///
183 : : /// \param renderer DNS message rendering context that encapsulates the
184 : : /// output buffer in which the \c Rdata is to be stored.
185 : : virtual void toWire(AbstractMessageRenderer& renderer) const = 0;
186 : : //@}
187 : :
188 : : ///
189 : : /// \name Comparison method
190 : : ///
191 : : //@{
192 : : /// \brief Compare two instances of \c Rdata.
193 : : ///
194 : : /// This method compares \c this and the \c other Rdata objects
195 : : /// in terms of the DNSSEC sorting order as defined in RFC4034, and returns
196 : : /// the result as an integer.
197 : : ///
198 : : /// This is a pure virtual method without the definition; the actual
199 : : /// comparison logic is specific to each derived concrete class and
200 : : /// should be explicitly defined in the derived class.
201 : : ///
202 : : /// Specific implementations of this method must confirm that \c this
203 : : /// and the \c other are objects of the same concrete derived class of
204 : : /// \c Rdata. This is normally done by \c dynamic_cast in the
205 : : /// implementation. It also means if the assumption isn't met
206 : : /// an exception of class \c std::bad_cast will be thrown.
207 : : ///
208 : : /// Here is an implementation choice: instead of relying on
209 : : /// \c dynamic_cast, we could first convert the data into wire-format
210 : : /// and compare the pair as opaque data. This would be more polymorphic,
211 : : /// but might involve significant overhead, especially for a large size
212 : : /// of RDATA.
213 : : ///
214 : : /// \param other the right-hand operand to compare against.
215 : : /// \return < 0 if \c this would be sorted before \c other.
216 : : /// \return 0 if \c this is identical to \c other in terms of sorting order.
217 : : /// \return > 0 if \c this would be sorted after \c other.
218 : : virtual int compare(const Rdata& other) const = 0;
219 : : //@}
220 : : };
221 : :
222 : : namespace generic {
223 : :
224 : : /// \brief The \c GenericImpl class is the actual implementation of the
225 : : /// \c generic::Generic class.
226 : : ///
227 : : /// The implementation is hidden from applications. This approach requires
228 : : /// dynamic memory allocation on construction, copy, or assignment, but
229 : : /// we believe it should be acceptable as "unknown" RDATA should be pretty
230 : : /// rare.
231 : : struct GenericImpl;
232 : :
233 : : /// \brief The \c generic::Generic class represents generic "unknown" RDATA.
234 : : ///
235 : : /// This class is used as a placeholder for all non well-known type of RDATA.
236 : : /// By definition, the stored data is regarded as opaque binary without
237 : : /// assuming any structure.
238 : : class Generic : public Rdata {
239 : : public:
240 : : ///
241 : : /// \name Constructors, Assignment Operator and Destructor.
242 : : ///
243 : : //@{
244 : : /// \brief Constructor from a string.
245 : : ///
246 : : /// This method constructs a \c generic::Generic object from a textual
247 : : /// representation as defined in RFC3597.
248 : : ///
249 : : /// If \c rdata_string isn't a valid textual representation of this type
250 : : /// of RDATA, an exception of class \c InvalidRdataText or
251 : : /// \c InvalidRdataLength will be thrown.
252 : : /// If resource allocation to store the data fails, a corresponding standard
253 : : /// exception will be thrown.
254 : : ///
255 : : /// \param rdata_string A string of textual representation of generic
256 : : /// RDATA.
257 : : explicit Generic(const std::string& rdata_string);
258 : :
259 : : ///
260 : : /// \brief Constructor from wire-format data.
261 : : ///
262 : : /// The \c buffer parameter normally stores a complete DNS message
263 : : /// containing the generic RDATA to be constructed.
264 : : /// The current read position of the buffer points to the head of the
265 : : /// data.
266 : : ///
267 : : /// This method reads \c rdata_len bytes from the \c buffer, and internally
268 : : /// stores the data as an opaque byte sequence.
269 : : ///
270 : : /// \c rdata_len must not exceed \c MAX_RDLENGTH; otherwise, an exception
271 : : /// of class \c InvalidRdataLength will be thrown.
272 : : /// If resource allocation to hold the data fails, a corresponding standard
273 : : /// exception will be thrown; if the \c buffer doesn't contain \c rdata_len
274 : : /// bytes of unread data, an exception of class \c InvalidBufferPosition
275 : : /// will be thrown.
276 : : ///
277 : : /// \param buffer A reference to an \c InputBuffer object storing the
278 : : /// \c Rdata to parse.
279 : : /// \param rdata_len The length in buffer of the \c Rdata. In bytes.
280 : : Generic(isc::util::InputBuffer& buffer, size_t rdata_len);
281 : :
282 : : ///
283 : : /// \brief The destructor.
284 : : virtual ~Generic();
285 : : ///
286 : : /// \brief The copy constructor.
287 : : ///
288 : : /// If resource allocation to copy the data fails, a corresponding standard
289 : : /// exception will be thrown.
290 : : ///
291 : : /// \param source A reference to a \c generic::Generic object to copy from.
292 : : Generic(const Generic& source);
293 : :
294 : : ///
295 : : /// \brief The assignment operator.
296 : : ///
297 : : /// If resource allocation to copy the data fails, a corresponding standard
298 : : /// exception will be thrown.
299 : : ///
300 : : /// \param source A reference to a \c generic::Generic object to copy from.
301 : : Generic& operator=(const Generic& source);
302 : : //@}
303 : :
304 : : ///
305 : : /// \name Converter methods
306 : : ///
307 : : //@{
308 : : /// \brief Convert an \c generic::Generic object to a string.
309 : : ///
310 : : /// This method converts a generic "unknown" RDATA object into a textual
311 : : /// representation of such unknown data as defined in RFC3597.
312 : : ///
313 : : /// If resource allocation to copy the data fails, a corresponding standard
314 : : /// exception will be thrown.
315 : : ///
316 : : /// \return A string representation of \c generic::Generic.
317 : : virtual std::string toText() const;
318 : :
319 : : ///
320 : : /// \brief Render the \c generic::Generic in the wire format into a buffer.
321 : : ///
322 : : /// This will require \c rdata_len bytes of remaining capacity in the
323 : : /// \c buffer. If this is not the case and resource allocation for the
324 : : /// necessary memory space fails, a corresponding standard exception will
325 : : /// be thrown.
326 : : ///
327 : : /// \param buffer An output buffer to store the wire data.
328 : : virtual void toWire(isc::util::OutputBuffer& buffer) const;
329 : :
330 : : /// \brief Render the \c generic::Generic in the wire format into a
331 : : /// \c MessageRenderer object.
332 : : ///
333 : : /// This will require \c rdata_len bytes of remaining capacity in the
334 : : /// \c buffer. If this is not the case and resource allocation for the
335 : : /// necessary memory space fails, a corresponding standard exception will
336 : : /// be thrown.
337 : : ///
338 : : /// \param renderer DNS message rendering context that encapsulates the
339 : : /// output buffer in which the \c Generic object is to be stored.
340 : : virtual void toWire(AbstractMessageRenderer& renderer) const;
341 : : //@}
342 : :
343 : : ///
344 : : /// \name Comparison method
345 : : ///
346 : : //@{
347 : : /// \brief Compare two instances of \c generic::Generic objects.
348 : : ///
349 : : /// As defined in RFC4034, this method simply compares the wire-format
350 : : /// representations of the two objects as left-justified unsigned octet
351 : : /// sequences.
352 : : ///
353 : : /// The object referenced by \c other must have been instantiated as
354 : : /// a c generic::Generic class object; otherwise, an exception of class
355 : : /// \c std::bad_cast will be thrown.
356 : : /// Note that the comparison is RR type/class agnostic: this method doesn't
357 : : /// check whether the two \c Rdata objects to compare are of the comparable
358 : : /// RR type/class. For example, \c this object may come from an \c RRset
359 : : /// of \c RRType x, and the \c other may come from a different \c RRset
360 : : /// of \c RRType y (where x != y). This situation would be considered a
361 : : /// bug, but this method cannot detect this type of error.
362 : : /// The caller must ensure this condition.
363 : : ///
364 : : /// \param other the right-hand operand to compare against.
365 : : /// \return < 0 if \c this would be sorted before \c other.
366 : : /// \return 0 if \c this is identical to \c other in terms of sorting order.
367 : : /// \return > 0 if \c this would be sorted after \c other.
368 : : virtual int compare(const Rdata& other) const;
369 : : //@}
370 : : private:
371 : : GenericImpl* impl_;
372 : : };
373 : :
374 : : ///
375 : : /// \brief Insert the name as a string into stream.
376 : : ///
377 : : /// This method convert the \c rdata into a string and inserts it into the
378 : : /// output stream \c os.
379 : : ///
380 : : /// This function overloads the global \c operator<< to behave as described in
381 : : /// \c ostream::operator<< but applied to \c generic::Generic Rdata objects.
382 : : ///
383 : : /// \param os A \c std::ostream object on which the insertion operation is
384 : : /// performed.
385 : : /// \param rdata The \c Generic object output by the operation.
386 : : /// \return A reference to the same \c std::ostream object referenced by
387 : : /// parameter \c os after the insertion operation.
388 : : std::ostream& operator<<(std::ostream& os, const Generic& rdata);
389 : : } // end of namespace "generic"
390 : :
391 : : //
392 : : // Non class-member functions related to Rdata
393 : : //
394 : :
395 : : ///
396 : : /// \name Parameterized Polymorphic RDATA Factories
397 : : ///
398 : : /// This set of global functions provide a unified interface to create an
399 : : /// \c Rdata object in a parameterized polymorphic way,
400 : : /// that is, these functions take a pair of \c RRType and \c RRClass
401 : : /// objects and data specific to that pair, and create an object of
402 : : /// the corresponding concrete derived class of \c Rdata.
403 : : ///
404 : : /// These will be useful when parsing/constructing a DNS message or
405 : : /// parsing a master file, where information for a specific type of RDATA
406 : : /// is given but the resulting object, once created, should better be used
407 : : /// in a polymorphic way.
408 : : ///
409 : : /// For example, if a master file parser encounters an NS RR
410 : : /// \verbatim example.com. 3600 IN NS ns.example.com.\endverbatim
411 : : /// it stores the text fragments "IN", "NS", and "ns.example.com." in
412 : : /// \c std::string objects \c class_txt, \c type_txt, and \c nsname_txt,
413 : : /// respectively, then it would create a new \c RdataPtr object as follows:
414 : : /// \code RdataPtr rdata = createRdata(RRType(type_txt), RRClass(class_txt),
415 : : /// nsname_txt); \endcode
416 : : /// On success, \c rdata will point to an object of the \c generic::NS class
417 : : /// that internally holds a domain name of "ns.example.com."
418 : : ///
419 : : /// Internally, these functions uses the corresponding
420 : : /// \c RRParamRegistry::createRdata methods of the \c RRParamRegistry.
421 : : /// See also the description on these methods for related notes.
422 : : //@{
423 : : /// \brief Create RDATA of a given pair of RR type and class from a string.
424 : : ///
425 : : /// This method creates from a string an \c Rdata object of the given pair
426 : : /// of RR type and class.
427 : : ///
428 : : /// \param rrtype An \c RRType object specifying the type/class pair.
429 : : /// \param rrclass An \c RRClass object specifying the type/class pair.
430 : : /// \param rdata_string A string of textual representation of the \c Rdata.
431 : : /// \return An \c RdataPtr object pointing to the created \c Rdata
432 : : /// object.
433 : : RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
434 : : const std::string& rdata_string);
435 : :
436 : : /// \brief Create RDATA of a given pair of RR type and class from
437 : : /// wire-format data.
438 : : ///
439 : : /// This method creates from wire-format binary data an \c Rdata object
440 : : /// of the given pair of RR type and class.
441 : : ///
442 : : /// \c len must not exceed the protocol defined maximum value, \c MAX_RDLENGTH;
443 : : /// otherwise, an exception of class \c InvalidRdataLength will be thrown.
444 : : ///
445 : : /// In some cases, the length of the RDATA is determined without the
446 : : /// information of \c len. For example, the RDATA length of an IN/A RR
447 : : /// must always be 4. If \c len is not equal to the actual length in such
448 : : /// cases, an exception of class InvalidRdataLength will be thrown.
449 : : ///
450 : : /// \param rrtype An \c RRType object specifying the type/class pair.
451 : : /// \param rrclass An \c RRClass object specifying the type/class pair.
452 : : /// \param buffer A reference to an \c InputBuffer object storing the
453 : : /// \c Rdata to parse.
454 : : /// \param len The length in buffer of the \c Rdata. In bytes.
455 : : /// \return An \c RdataPtr object pointing to the created \c Rdata
456 : : /// object.
457 : : RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
458 : : isc::util::InputBuffer& buffer, size_t len);
459 : :
460 : : /// \brief Create RDATA of a given pair of RR type and class, copying
461 : : /// of another RDATA of same kind.
462 : : ///
463 : : /// This method creates an \c Rdata object of the given pair of
464 : : /// RR type and class, copying the content of the given \c Rdata,
465 : : /// \c source.
466 : : ///
467 : : /// \param rrtype An \c RRType object specifying the type/class pair.
468 : : /// \param rrclass An \c RRClass object specifying the type/class pair.
469 : : /// \param source A reference to an \c Rdata object whose content
470 : : /// is to be copied to the created \c Rdata object.
471 : : /// \return An \c RdataPtr object pointing to the created
472 : : /// \c Rdata object.
473 : : RdataPtr createRdata(const RRType& rrtype, const RRClass& rrclass,
474 : : const Rdata& source);
475 : : //@}
476 : :
477 : : ///
478 : : /// \brief Gives relative ordering of two names in terms of DNSSEC RDATA
479 : : /// ordering.
480 : : ///
481 : : /// This method compares two names as defined in Sections 6.2 and 6.3 of
482 : : /// RFC4034: Comparing two names in their canonical form
483 : : /// (i.e., converting upper case ASCII characters to lower ones) and
484 : : /// as a left-justified unsigned octet sequence. Note that the ordering is
485 : : /// different from that for owner names. For example, "a.example" should be
486 : : /// sorted before "example" as RDATA, but the ordering is the opposite when
487 : : /// compared as owner names.
488 : : ///
489 : : /// Normally, applications would not need this function directly.
490 : : /// This is mostly an internal helper function for \c Rdata related classes
491 : : /// to implement their \c compare() method.
492 : : /// This function is publicly open, however, for the convenience of
493 : : /// external developers who want to implement new or experimental RR types.
494 : : ///
495 : : /// This function never throws an exception as long as the given names are
496 : : /// valid \c Name objects.
497 : : ///
498 : : /// Additional note about applicability: In fact, BIND9's similar function,
499 : : /// \c dns_name_rdatacompare(), is only used in rdata implementations and
500 : : /// for testing purposes.
501 : : ///
502 : : /// \param n1,n2 \c Name class objects to compare.
503 : : /// \return -1 if \c n1 would be sorted before \c n2.
504 : : /// \return 0 if \c n1 is identical to \c n2 in terms of sorting order.
505 : : /// \return 1 if \c n1 would be sorted after \c n2.
506 : : ///
507 : : int compareNames(const Name& n1, const Name& n2);
508 : :
509 : : } // end of namespace "rdata"
510 : : }
511 : : }
512 : : #endif // __RDATA_H
513 : :
514 : : // Local Variables:
515 : : // mode: c++
516 : : // End:
|