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 __RRSET_H
16 : : #define __RRSET_H 1
17 : :
18 : : #include <iostream>
19 : : #include <string>
20 : :
21 : : #include <boost/shared_ptr.hpp>
22 : :
23 : : #include <exceptions/exceptions.h>
24 : :
25 : : #include <dns/rdata.h>
26 : : #include <dns/rrtype.h>
27 : :
28 : : namespace isc {
29 : : namespace util {
30 : : class OututBuffer;
31 : : }
32 : :
33 : : namespace dns {
34 : :
35 : : ///
36 : : /// \brief A standard DNS module exception that is thrown if an RRset object
37 : : /// does not contain any RDATA where required.
38 : : ///
39 : 10 : class EmptyRRset : public Exception {
40 : : public:
41 : : EmptyRRset(const char* file, size_t line, const char* what) :
42 [ + - ][ + - ]: 10 : isc::Exception(file, line, what) {}
[ + - ]
43 : : };
44 : :
45 : : // forward declarations
46 : : class Name;
47 : : class RRType;
48 : : class RRClass;
49 : : class RRTTL;
50 : : class AbstractMessageRenderer;
51 : : class AbstractRRset;
52 : : class BasicRRset;
53 : : class RdataIterator;
54 : : class BasicRRsetImpl;
55 : : class RRset;
56 : :
57 : : /// \brief A pointer-like type pointing to an \c RRset object.
58 : : ///
59 : : /// This type is commonly used as an argument of various functions defined
60 : : /// in this library in order to handle RRsets in a polymorphic manner.
61 : : typedef boost::shared_ptr<AbstractRRset> RRsetPtr;
62 : :
63 : : /// \brief A pointer-like type pointing to an (immutable) \c RRset
64 : : /// object.
65 : : ///
66 : : /// This type is commonly used as an argument of various functions defined
67 : : /// in this library in order to handle RRsets in a polymorphic manner.
68 : : typedef boost::shared_ptr<const AbstractRRset> ConstRRsetPtr;
69 : :
70 : : /// \brief A pointer-like type point to an \c RdataIterator object.
71 : : typedef boost::shared_ptr<RdataIterator> RdataIteratorPtr;
72 : :
73 : : /// \brief The \c AbstractRRset class is an abstract base class that
74 : : /// models a DNS RRset.
75 : : ///
76 : : /// An object of (a specific derived class of) \c AbstractRRset
77 : : /// models an RRset as described in the DNS standard:
78 : : /// A set of DNS resource records (RRs) of the same type and class.
79 : : /// The standard requires the TTL of all RRs in an RRset be the same;
80 : : /// this class follows that requirement.
81 : :
82 : : /// Note about duplicate RDATA: RFC2181 states that it's meaningless that an
83 : : /// RRset contains two identical RRs and that name servers should suppress
84 : : /// such duplicates.
85 : : /// This class is not responsible for ensuring this requirement: For example,
86 : : /// \c addRdata() method doesn't check if there's already RDATA identical
87 : : /// to the one being added.
88 : : /// This is because such checks can be expensive, and it's often easy to
89 : : /// ensure the uniqueness requirement at the %data preparation phase
90 : : /// (e.g. when loading a zone).
91 : : /// When parsing an incoming DNS message, the uniqueness may not be guaranteed,
92 : : /// so the application needs to detect and ignore any duplicate RDATA
93 : : /// (the \c Message class of this library should provide this responsibility).
94 : : ///
95 : : /// Another point to note is that \c AbstractRRset and its derived classes
96 : : /// allow an object to have an empty set of RDATA.
97 : : /// Even though there's no corresponding notion in the protocol specification,
98 : : /// it would be more intuitive for a container-like %data structure
99 : : /// to allow an empty set.
100 : : ///
101 : : /// Since \c AbstractRRset is an abstract class, it is generally used
102 : : /// via a pointer (or pointer like object) or a reference.
103 : : /// In particular, \c RRsetPtr, a pointer like type for \c AbstractRRset,
104 : : /// is used for polymorphic RRset operations throughout this library.
105 : : ///
106 : : /// The \c AbstractRRset class is also intended to be a major customization
107 : : /// point. For example, a high performance server implementation may want
108 : : /// to define an optimized "pre-compiled" RRset and provide an optimized
109 : : /// implementation of the \c toWire() method.
110 : : ///
111 : : /// Note about design choice: In BIND9, a set of RDATA with a common tuple
112 : : /// of RR class, RR type, and TTL was represented in a structure named
113 : : /// \c rdataset. Unlike the RRset classes, an \c rdataset did not contain
114 : : /// the information of the owner name.
115 : : /// This might be advantageous if we want to handle "RRsets", that is,
116 : : /// a set of different types of RRset for the same owner name, because
117 : : /// a single "name" structure can be used for multiple RRsets, minimizing
118 : : /// %data copy and memory footprint.
119 : : /// On the other hand, it's inconvenient for API users since in many cases
120 : : /// a pair of name and an \c rdataset must be maintained. It's also counter
121 : : /// intuitive in implementing protocol operations as an RRset is often used
122 : : /// as an atomic entity in DNS protocols while an \c rdataset is a component
123 : : /// of an RRset.
124 : : ///
125 : : /// We have therefore defined the notion of RRset explicitly in our initial
126 : : /// API design. We believe memory footprint is not a big concern because
127 : : /// RRsets are generally expected to be used as temporary objects, e.g.
128 : : /// while parsing or constructing a DNS message, or searching a DNS %data
129 : : /// source; for longer term purposes such as in-memory %data source entries,
130 : : /// the corresponding %data would be represented in a different, memory
131 : : /// optimized format. As for the concern about %data copy, we believe
132 : : /// it can be mitigated by using copy-efficient implementation for the
133 : : /// \c Name class implementation, such as reference counted objects.
134 : : /// Later, We plan to perform benchmark tests later to see if this assumption
135 : : /// is valid and to revisit the design if necessary.
136 : : ///
137 : : /// Note about terminology: there has been a discussion at the IETF
138 : : /// namedroppers ML about RRset vs RRSet (case of "s")
139 : : /// [http://ops.ietf.org/lists/namedroppers/namedroppers.2009/msg02737.html].
140 : : /// While RFC2181 uses the latter, many other RFCs use the former,
141 : : /// and most of the list members who showed their opinion seem to prefer
142 : : /// "RRset". We follow that preference in this implementation.
143 : : ///
144 : : /// The current design of \c AbstractRRset is still in flux.
145 : : /// There are many open questions in design details:
146 : : /// - support more set-like operations, e.g, merge two RRsets of the same
147 : : /// type?
148 : : /// - more convenient methods or non member utility functions, e.g.
149 : : /// "sort" and "search(find)" method?
150 : : /// - what about comparing two RRsets of the same type? If we need this,
151 : : /// should it compare rdata's as a set or as a list (i.e. compare
152 : : /// each rdata one by one or as a whole)? c.f. NLnet Labs' ldns
153 : : /// (http://www.nlnetlabs.nl/projects/ldns/doc/index.html)
154 : : /// has \c ldns_rr_list_compare(), which takes the latter approach
155 : : /// (seemingly assuming the caller sorts the lists beforehand).
156 : : /// - BIND9 libdns has some special DNSSEC-related methods
157 : : /// such as \c addnoqname() or \c addclosest(). Do we need these?
158 : : /// (Probably not. We wouldn't want to make the class design too
159 : : /// monolithic.)
160 : : /// - Do we need to allow the user to remove specific Rdata?
161 : : /// Probably not, according to the current usage of the BIND9 code.
162 : : class AbstractRRset {
163 : : ///
164 : : /// \name Constructors and Destructor
165 : : ///
166 : : /// Note: The copy constructor and the assignment operator are intentionally
167 : : /// defined as private to make it explicit that this is a pure base class.
168 : : //@{
169 : : private:
170 : : AbstractRRset(const AbstractRRset& source);
171 : : AbstractRRset& operator=(const AbstractRRset& source);
172 : : protected:
173 : : /// \brief The default constructor.
174 : : ///
175 : : /// This is intentionally defined as \c protected as this base class should
176 : : /// never be instantiated (except as part of a derived class).
177 : 26752 : AbstractRRset() {}
178 : : public:
179 : : /// The destructor.
180 : 26746 : virtual ~AbstractRRset() {}
181 : : //@}
182 : :
183 : : ///
184 : : /// \name Getter and Setter Methods
185 : : ///
186 : : /// These methods are generally expected to be exception free, but it's
187 : : /// not guaranteed at the interface level;
188 : : /// for example, some performance optimized derived class may manage
189 : : /// the information corresponding to the class "attributes" to get or set,
190 : : /// and may require dynamic memory allocation to execute the method.
191 : : /// Consult the derived class description to see if a specific derived
192 : : /// \c RRset class may throw an exception from these methods.
193 : : ///
194 : : /// Note that setter methods are not provided for \c RRClass and
195 : : /// \c RRType. This is intentional. Since the format and semantics of
196 : : /// \c Rdata are dependent on the RR type (and RR class for some RR types),
197 : : /// allowing dynamically modify these attributes can easily lead to a
198 : : /// bug where the RDATA and type and/or class become inconsistent.
199 : : /// We want to avoid that situation by restricting the access.
200 : : //@{
201 : : /// \brief Returns the number of \c Rdata objects contained in the \c RRset.
202 : : ///
203 : : /// Note that an \c RRset with an empty set of \c Rdata can exist, so
204 : : /// this method may return 0.
205 : : ///
206 : : /// \return The number of \c Rdata objects contained.
207 : : virtual unsigned int getRdataCount() const = 0;
208 : :
209 : : /// \brief Returns the owner name of the \c RRset.
210 : : ///
211 : : /// \return A reference to a \c Name class object corresponding to the
212 : : /// \c RRset owner name.
213 : : virtual const Name& getName() const = 0;
214 : :
215 : : /// \brief Returns the RR Class of the \c RRset.
216 : : ///
217 : : /// \return A reference to a \c RRClass class object corresponding to the
218 : : /// RR class of the \c RRset.
219 : : virtual const RRClass& getClass() const = 0;
220 : :
221 : : /// \brief Returns the RR Type of the \c RRset.
222 : : ///
223 : : /// \return A reference to a \c RRType class object corresponding to the
224 : : /// RR type of the \c RRset.
225 : : virtual const RRType& getType() const = 0;
226 : :
227 : : /// \brief Returns the TTL of the RRset.
228 : : ///
229 : : /// \return A reference to a \c RRTTL class object corresponding to the
230 : : /// TTL of the \c RRset.
231 : : virtual const RRTTL& getTTL() const = 0;
232 : :
233 : : /// \brief Updates the owner name of the \c RRset.
234 : : ///
235 : : /// \param name A reference to a \c Name class object to be copied as the
236 : : /// new name.
237 : : virtual void setName(const Name& name) = 0;
238 : :
239 : : /// \brief Updates the TTL of the \c RRset.
240 : : ///
241 : : /// \param ttl A reference to a \c RRTTL class object to be copied as the
242 : : /// new TTL.
243 : : virtual void setTTL(const RRTTL& ttl) = 0;
244 : : //@}
245 : :
246 : : ///
247 : : /// \name Converter Methods
248 : : ///
249 : : /// These methods have the default implementation that can be reused by
250 : : /// derived classes.
251 : : /// Since they are defined as pure virtual, derived classes
252 : : /// that want to reuse the default implementation must explicitly
253 : : /// invoke their base class version (see the description for
254 : : /// <code>addRdata(const rdata::Rdata&)</code>).
255 : : ///
256 : : /// Design Note: the default implementations are defined only using
257 : : /// other public methods of the \c AbstractRRset class, and could be
258 : : /// implemented as non member functions (as some C++ textbooks suggest).
259 : : /// However, since derived classes may want to provide customized versions
260 : : /// (especially of the \c toWire() method for performance reasons)
261 : : /// we chose to define them as virtual functions, and, as a result,
262 : : /// member functions.
263 : : //@{
264 : : /// \brief Convert the RRset to a string.
265 : : ///
266 : : /// Unlike other similar methods of this library, this method terminates
267 : : /// the resulting string with a trailing newline character.
268 : : /// (following the BIND9 convention)
269 : : ///
270 : : /// The RRset must contain some RDATA; otherwise, an exception of class
271 : : /// \c EmptyRRset will be thrown.
272 : : /// If resource allocation fails, a corresponding standard exception
273 : : /// will be thrown.
274 : : /// The default implementation may throw other exceptions if the
275 : : /// \c toText() method of the RDATA objects throws.
276 : : /// If a derived class of \c AbstractRRset overrides the default
277 : : /// implementation, the derived version may throw its own exceptions.
278 : : ///
279 : : /// Open issue: We may want to support multiple output formats as
280 : : /// BIND9 does. For example, we might want to allow omitting the owner
281 : : /// name when possible in the context of zone dump. This is a future
282 : : /// TODO item.
283 : : ///
284 : : /// \return A string representation of the RRset.
285 : : virtual std::string toText() const = 0;
286 : :
287 : : /// \brief Render the RRset in the wire format with name compression and
288 : : /// truncation handling.
289 : : ///
290 : : /// This method compresses the owner name of the RRset and domain names
291 : : /// used in RDATA that should be compressed.
292 : : /// In addition, this method detects the case where rendering the entire
293 : : /// RRset would cause truncation, and handles the case appropriately
294 : : /// (this is a TODO item, and not implemented in this version).
295 : : ///
296 : : /// Note: perhaps we may want to add more arguments to convey optional
297 : : /// information such as an "rrset-order" policy or how to handle truncation
298 : : /// case. This is a TODO item.
299 : : ///
300 : : /// If resource allocation fails, a corresponding standard exception
301 : : /// will be thrown.
302 : : /// The RRset must contain some RDATA; otherwise, an exception of class
303 : : /// \c EmptyRRset will be thrown.
304 : : /// The default implementation may throw other exceptions if the
305 : : /// \c toWire() method of the RDATA objects throws.
306 : : /// If a derived class of \c AbstractRRset overrides the default
307 : : /// implementation, the derived version may throw its own exceptions.
308 : : ///
309 : : /// \param renderer DNS message rendering context that encapsulates the
310 : : /// output buffer and name compression information.
311 : : /// \return The number of RRs rendered. If the truncation is necessary
312 : : /// this value may be different from the number of RDATA objects contained
313 : : /// in the RRset.
314 : : virtual unsigned int toWire(AbstractMessageRenderer& renderer) const = 0;
315 : :
316 : : /// \brief Render the RRset in the wire format without any compression.
317 : : ///
318 : : /// See the other toWire() description about possible exceptions.
319 : : ///
320 : : /// \param buffer An output buffer to store the wire data.
321 : : /// \return The number of RRs rendered.
322 : : virtual unsigned int toWire(isc::util::OutputBuffer& buffer) const = 0;
323 : : //@}
324 : :
325 : : ///
326 : : /// \name RDATA Manipulation Methods
327 : : ///
328 : : //@{
329 : : /// \brief Add an RDATA to the RRset (pointer version).
330 : : ///
331 : : /// This method adds the given RDATA (as a pointer-like type to a
332 : : /// derived class object of \c rdata::Rdata) to the \c RRset.
333 : : ///
334 : : /// \param rdata A pointer (like) type of \c rdata::RdataPtr to be added
335 : : /// to the \c RRset.
336 : : virtual void addRdata(rdata::ConstRdataPtr rdata) = 0;
337 : :
338 : : /// \brief Add an RDATA to the RRset (reference version).
339 : : ///
340 : : /// This method adds the given RDATA (as a reference to a
341 : : /// derived class object of \c rdata::Rdata) to the \c RRset.
342 : : ///
343 : : /// This method has the default implementation that can be reused by
344 : : /// derived classes.
345 : : /// Since this method is defined as pure virtual, derived classes
346 : : /// that want to reuse the default implementation must explicitly
347 : : /// invoke this base class version.
348 : : /// For example, if the class \c CustomizedRRset, a derived class of
349 : : /// \c AbstractRRset, wants to reuse the default implementation of
350 : : /// \c %addRdata() (reference version), it would be defined as follows:
351 : : /// \code void
352 : : /// CustomizedRRset::addRdata(const rdata::Rdata& rdata)
353 : : /// {
354 : : /// AbstractRRset::addRdata(rdata);
355 : : /// }
356 : : /// \endcode
357 : : ///
358 : : /// This method is more strictly typed than the pointer version:
359 : : /// If \c rdata does not refer to the appropriate derived
360 : : /// \c Rdata class
361 : : /// for the \c RRType for this \c RRset, it throws an exception of class
362 : : /// \c std::bad_cast.
363 : : /// If resource allocation fails, a corresponding standard exception
364 : : /// will be thrown.
365 : : /// The RRset must contain some RDATA; otherwise, an exception of class
366 : : /// \c EmptyRRset will be thrown.
367 : : /// The default implementation may throw other exceptions if the
368 : : /// \c toWire() method of the RDATA objects throws.
369 : : /// If a derived class of \c AbstractRRset overrides the default
370 : : /// implementation, the derived version may throw its own exceptions.
371 : : ///
372 : : /// The default implementation simply constructs an \c rdata::RdataPtr
373 : : /// object from a newly allocated RDATA object copying from parameter
374 : : /// \c rdata, and calls the other version of
375 : : /// \c addRdata(const rdata::RdataPtr).
376 : : /// So it is inherently less efficient than the other version.
377 : : /// Still, this version would offer a more intuitive interface and is
378 : : /// provided as such.
379 : : ///
380 : : /// \param rdata A reference to a \c rdata::RdataPtr (derived) class
381 : : /// object, a copy of which is to be added to the \c RRset.
382 : : virtual void addRdata(const rdata::Rdata& rdata) = 0;
383 : :
384 : : /// \brief Return an iterator to go through all RDATA stored in the
385 : : /// \c RRset.
386 : : ///
387 : : /// The rdata cursor of the returned iterator will point to the first
388 : : /// RDATA, that is, it effectively calls \c RdataIterator::first()
389 : : /// internally.
390 : : ///
391 : : /// Using the design pattern terminology, \c getRdataIterator()
392 : : /// is an example of a <em>factory method</em>.
393 : : ///
394 : : /// Whether this method throws an exception depends on the actual
395 : : /// implementation of the derived \c AbstractRRset class, but in general
396 : : /// it will involve resource allocation and can throw a standard exception
397 : : /// if it fails.
398 : : ///
399 : : /// \return A pointer-like object pointing to the derived \c RdataIterator
400 : : /// object.
401 : : virtual RdataIteratorPtr getRdataIterator() const = 0;
402 : : //@}
403 : :
404 : : ///
405 : : /// \name Associated RRSIG methods
406 : : ///
407 : : /// These methods access an "associated" RRset, that containing the DNSSEC
408 : : /// signatures for this RRset. It can be argued that this is not a
409 : : /// fundamental part of the RRset abstraction, since RFC 2181 defined an
410 : : /// RRset as a group of records with the same label, class and type but
411 : : /// different data. However, BIND 10 has to deal with DNSSEC and in
412 : : /// practice, including the information at the AbstractRRset level makes
413 : : /// implementation easier. (If a class is ever needed that must be
414 : : /// ignorant of the idea of an associated RRSIG RRset - e.g. a specialised
415 : : /// RRSIG RRset class - these methods can just throw a "NotImplemented"
416 : : /// exception.)
417 : : //@{
418 : : /// \brief Return pointer to this RRset's RRSIG RRset
419 : : ///
420 : : /// \return Pointer to the associated RRSIG RRset or null if there is none.
421 : : virtual RRsetPtr getRRsig() const = 0;
422 : :
423 : : /// \brief Adds RRSIG RRset RRs to the associated RRSIG RRset
424 : : ///
425 : : /// Adds the (assumed) RRSIG rdata the RRSIG RRset associated with this
426 : : /// RRset. If one does not exist, it is created using the data given.
427 : : ///
428 : : /// \param rdata Pointer to RRSIG rdata to be added.
429 : : virtual void addRRsig(const rdata::ConstRdataPtr& rdata) = 0;
430 : :
431 : : /// \brief Adds RRSIG RRset RRs to the associated RRSIG RRset
432 : : ///
433 : : /// Adds the (assumed) RRSIG rdata the RRSIG RRset associated with this
434 : : /// RRset. If one does not exist, it is created using the data given.
435 : : ///
436 : : /// (This overload is for an older version of boost that doesn't support
437 : : /// conversion from shared_ptr<X> to shared_ptr<const X>.)
438 : : ///
439 : : /// \param rdata Pointer to RRSIG rdata to be added.
440 : : virtual void addRRsig(const rdata::RdataPtr& rdata) = 0;
441 : :
442 : : /// \brief Adds RRSIG RRset RRs to the associated RRSIG RRset
443 : : ///
444 : : /// Adds the signatures in the given (assumed) RRSIG RRset to the RRSIG
445 : : /// RRset associated with this RRset. If one does not exist, it is created
446 : : /// using the data given.
447 : : ///
448 : : /// \param sigs RRSIG RRset containing signatures to be added to the
449 : : /// RRSIG RRset associated with this class.
450 : : virtual void addRRsig(const AbstractRRset& sigs) = 0;
451 : :
452 : : /// \brief Adds RRSIG RRset RRs to the associated RRSIG RRset
453 : : ///
454 : : /// Adds the signatures in the given (assumed) RRSIG RRset to the RRSIG
455 : : /// RRset associated with this RRset. If one does not exist, it is created
456 : : /// using the data given.
457 : : ///
458 : : /// \param sigs Pointer to a RRSIG RRset containing signatures to be added
459 : : /// to the RRSIG RRset associated with this class.
460 : : virtual void addRRsig(const ConstRRsetPtr& sigs) = 0;
461 : :
462 : : /// \brief Adds RRSIG RRset RRs to the associated RRSIG RRset
463 : : ///
464 : : /// Adds the signatures in the given (assumed) RRSIG RRset to the RRSIG
465 : : /// RRset associated with this RRset. If one does not exist, it is created
466 : : /// using the data given.
467 : : ///
468 : : /// (This overload is for an older version of boost that doesn't support
469 : : /// conversion from shared_ptr<X> to shared_ptr<const X>.)
470 : : ///
471 : : /// \param sigs Pointer to a RRSIG RRset containing signatures to be added
472 : : /// to the RRSIG RRset associated with this class.
473 : : virtual void addRRsig(const RRsetPtr& sigs) = 0;
474 : :
475 : : /// \brief Clear the RRSIGs for this RRset
476 : : virtual void removeRRsig() = 0;
477 : :
478 : : /// \brief Check whether two RRsets are of the same kind
479 : : ///
480 : : /// Checks if two RRsets have the same name, RR type, and RR class.
481 : : ///
482 : : /// \param other Pointer to another AbstractRRset to compare
483 : : /// against.
484 : : virtual bool isSameKind(const AbstractRRset& other) const;
485 : : //@}
486 : :
487 : : };
488 : :
489 : : /// \brief The \c RdataIterator class is an abstract base class that
490 : : /// provides an interface for accessing RDATA objects stored in an RRset.
491 : : ///
492 : : /// While different derived classes of \c AbstractRRset may maintain the RDATA
493 : : /// objects in different ways, the \c RdataIterator class provides a
494 : : /// unified interface to iterate over the RDATA objects in a polymorphic
495 : : /// manner.
496 : : ///
497 : : /// Each derived class of \c AbstractRRset is expected to provide a concrete
498 : : /// derived class of \c RdataIterator, and each derived \c RdataIterator
499 : : /// class implements the unified interface in a way specific to the
500 : : /// implementation of the corresponding derived \c AbstractRRset class.
501 : : /// Using the design pattern terminology, this is a typical example of
502 : : /// the \e Iterator pattern.
503 : : ///
504 : : /// The RDATA objects stored in the \c RRset are considered to form
505 : : /// a unidirectional list from the \c RdataIterator point of view (while
506 : : /// the actual implementation in the derived \c RRset may not use a list).
507 : : /// We call this unidirectional list the <em>rdata list</em>.
508 : : ///
509 : : /// An \c RdataIterator object internally (and conceptually) holds a
510 : : /// <em>rdata cursor</em>, which points to a specific item of the rdata list.
511 : : ///
512 : : /// Note about design choice: as is clear from the interface, \c RdataIterator
513 : : /// is not compatible with the standard iterator classes.
514 : : /// Although it would be useful (for example, we could then use STL algorithms)
515 : : /// and is not necessarily impossible, it would make the iterator implementation
516 : : /// much more complicated.
517 : : /// For instance, any standard iterator must be assignable and
518 : : /// copy-constructible.
519 : : /// So we'd need to implement \c RdataIterator::operator=() in a polymorphic
520 : : /// way. This will require non-trivial implementation tricks.
521 : : /// We believe the simplified iterator interface as provided by the
522 : : /// \c RdataIterator class is sufficient in practice:
523 : : /// Most applications will simply go through the RDATA objects contained in
524 : : /// an RRset, examining (and possibly using) each object, as one path
525 : : /// operation.
526 : : class RdataIterator {
527 : : ///
528 : : /// \name Constructors and Destructor
529 : : ///
530 : : /// Note: The copy constructor and the assignment operator are intentionally
531 : : /// defined as private to make it explicit that this is a pure base class.
532 : : //@{
533 : : protected:
534 : : /// \brief The default constructor.
535 : : ///
536 : : /// This is intentionally defined as \c protected as this base class should
537 : : /// never be instantiated (except as part of a derived class).
538 : 14929 : RdataIterator() {}
539 : : public:
540 : : /// \brief Destructor
541 : 14929 : virtual ~RdataIterator() {}
542 : : private:
543 : : RdataIterator(const RdataIterator& source);
544 : : RdataIterator& operator=(const RdataIterator& source);
545 : : //@}
546 : :
547 : : public:
548 : : /// \brief Move the rdata cursor to the first RDATA in the rdata list
549 : : /// (if any).
550 : : ///
551 : : /// This method can safely be called multiple times, even after moving
552 : : /// the rdata cursor forward by the \c next() method.
553 : : ///
554 : : /// This method should never throw an exception.
555 : : virtual void first() = 0;
556 : :
557 : : /// \brief Move the rdata cursor to the next RDATA in the rdata list
558 : : /// (if any).
559 : : ///
560 : : /// This method should never throw an exception.
561 : : virtual void next() = 0;
562 : :
563 : : /// \brief Return the current \c Rdata corresponding to the rdata cursor.
564 : : ///
565 : : /// \return A reference to an \c rdata::Rdata object corresponding
566 : : /// to the rdata cursor.
567 : : virtual const rdata::Rdata& getCurrent() const = 0;
568 : :
569 : : /// \brief Return true iff the rdata cursor has reached the end of the
570 : : /// rdata list.
571 : : ///
572 : : /// Once this method returns \c true, the behavior of any subsequent
573 : : /// call to \c next() or \c getCurrent() is undefined.
574 : : /// Likewise, the result of \c isLast() call followed by such undefined
575 : : /// operations is also undefined.
576 : : ///
577 : : /// This method should never throw an exception.
578 : : ///
579 : : /// \return \c true if the rdata cursor has reached the end of the
580 : : /// rdata list; otherwise \c false.
581 : : virtual bool isLast() const = 0;
582 : : };
583 : :
584 : : /// \brief The \c BasicRRset class is a concrete derived class of
585 : : /// \c AbstractRRset that defines a straightforward RRset implementation.
586 : : ///
587 : : /// This class is designed to be as portable as possible, and so it adopts
588 : : /// the Pimpl idiom to hide as many details as possible.
589 : : /// Performance is a secondary concern for this class.
590 : : ///
591 : : /// This class is intended to be used by applications that only need
592 : : /// moderate level of performance with full functionality provided by
593 : : /// the \c AbstractRRset interfaces.
594 : : /// Highly performance-sensitive applications, such as a large scale
595 : : /// authoritative or caching name servers will implement and use a customized
596 : : /// version of derived \c AbstractRRset class.
597 : : class BasicRRset : public AbstractRRset {
598 : : ///
599 : : /// \name Constructors and Destructor
600 : : ///
601 : : /// Note: The copy constructor and the assignment operator are intentionally
602 : : /// defined as private. The intended use case wouldn't require copies of
603 : : /// a \c BasicRRset object; once created, it would normally be used
604 : : /// as a \c const object (via references).
605 : : //@{
606 : : private:
607 : : BasicRRset(const BasicRRset& source);
608 : : BasicRRset& operator=(const BasicRRset& source);
609 : : public:
610 : : /// \brief Constructor from (mostly) fixed parameters of the RRset.
611 : : ///
612 : : /// This constructor is normally expected to be exception free, but
613 : : /// copying the name may involve resource allocation, and if it fails
614 : : /// the corresponding standard exception will be thrown.
615 : : ///
616 : : /// \param name The owner name of the RRset.
617 : : /// \param rrclass The RR class of the RRset.
618 : : /// \param rrtype The RR type of the RRset.
619 : : /// \param ttl The TTL of the RRset.
620 : : BasicRRset(const Name& name, const RRClass& rrclass,
621 : : const RRType& rrtype, const RRTTL& ttl);
622 : : /// \brief The destructor.
623 : : virtual ~BasicRRset();
624 : : //@}
625 : :
626 : : ///
627 : : /// \name Getter and Setter Methods
628 : : ///
629 : : //@{
630 : : /// \brief Returns the number of \c Rdata objects contained in the \c RRset.
631 : : ///
632 : : /// This method never throws an exception.
633 : : ///
634 : : /// \return The number of \c Rdata objects contained.
635 : : virtual unsigned int getRdataCount() const;
636 : :
637 : : /// \brief Returns the owner name of the \c RRset.
638 : : ///
639 : : /// This method never throws an exception.
640 : : ///
641 : : /// \return A reference to a \c Name class object corresponding to the
642 : : /// \c RRset owner name.
643 : : virtual const Name& getName() const;
644 : :
645 : : /// \brief Returns the RR Class of the \c RRset.
646 : : ///
647 : : /// This method never throws an exception.
648 : : ///
649 : : /// \return A reference to a \c RRClass class object corresponding to the
650 : : /// RR class of the \c RRset.
651 : : virtual const RRClass& getClass() const;
652 : :
653 : : /// \brief Returns the RR Type of the \c RRset.
654 : : ///
655 : : /// This method never throws an exception.
656 : : ///
657 : : /// \return A reference to a \c RRType class object corresponding to the
658 : : /// RR type of the \c RRset.
659 : : virtual const RRType& getType() const;
660 : :
661 : : /// \brief Returns the TTL of the \c RRset.
662 : : ///
663 : : /// This method never throws an exception.
664 : : ///
665 : : /// \return A reference to a \c RRTTL class object corresponding to the
666 : : /// TTL of the \c RRset.
667 : : virtual const RRTTL& getTTL() const;
668 : :
669 : : /// \brief Updates the owner name of the \c RRset.
670 : : ///
671 : : /// This method normally does not throw an exception, but could throw
672 : : /// some standard exception on resource allocation failure if the
673 : : /// internal copy of the \c name involves resource allocation and it
674 : : /// fails.
675 : : ///
676 : : /// \param name A reference to a \c Name class object to be copied as the
677 : : /// new name.
678 : : virtual void setName(const Name& name);
679 : :
680 : : /// \brief Updates the TTL of the \c RRset.
681 : : ///
682 : : /// This method never throws an exception.
683 : : ///
684 : : /// \param ttl A reference to a \c RRTTL class object to be copied as the
685 : : /// new TTL.
686 : : virtual void setTTL(const RRTTL& ttl);
687 : : //@}
688 : :
689 : : ///
690 : : /// \name Converter Methods
691 : : ///
692 : : //@{
693 : : /// \brief Convert the RRset to a string.
694 : : ///
695 : : /// This method simply uses the default implementation.
696 : : /// See \c AbstractRRset::toText().
697 : : virtual std::string toText() const;
698 : :
699 : : /// \brief Render the RRset in the wire format with name compression and
700 : : /// truncation handling.
701 : : ///
702 : : /// This method simply uses the default implementation.
703 : : /// See \c AbstractRRset::toWire(MessageRenderer&)const.
704 : : virtual unsigned int toWire(AbstractMessageRenderer& renderer) const;
705 : :
706 : : /// \brief Render the RRset in the wire format without any compression.
707 : : ///
708 : : /// This method simply uses the default implementation.
709 : : /// See \c AbstractRRset::toWire(OutputBuffer&)const.
710 : : virtual unsigned int toWire(isc::util::OutputBuffer& buffer) const;
711 : : //@}
712 : :
713 : : ///
714 : : /// \name RDATA manipulation methods
715 : : ///
716 : : //@{
717 : : /// \brief Add an RDATA to the RRset (pointer version).
718 : : ///
719 : : /// This method is normally expected to be exception free, but it may
720 : : /// involve resource allocation, and if it fails the corresponding
721 : : /// standard exception will be thrown.
722 : : ///
723 : : /// \param rdata A pointer (like) type of \c rdata::RdataPtr to be added
724 : : /// to the \c BasicRRset.
725 : : virtual void addRdata(rdata::ConstRdataPtr rdata);
726 : :
727 : : /// \brief Add an RDATA to the RRset (reference version).
728 : : ///
729 : : /// This method simply uses the default implementation.
730 : : /// See \c AbstractRRset::addRdata(const rdata::Rdata&).
731 : : virtual void addRdata(const rdata::Rdata& rdata);
732 : :
733 : : /// \brief Return an iterator to go through all RDATA stored in the
734 : : /// \c BasicRRset.
735 : : ///
736 : : /// This is a concrete derived implementation of
737 : : /// \c AbstractRRset::getRdataIterator().
738 : : ///
739 : : /// This method dynamically allocates resources. If it fails it will
740 : : /// throw the corresponding standard exception.
741 : : /// The iterator methods for the \c BasicRRset class are exception free.
742 : : ///
743 : : /// \return A pointer-like object pointing to the derived \c RdataIterator
744 : : /// object for the \c BasicRRset class.
745 : : virtual RdataIteratorPtr getRdataIterator() const;
746 : : //@}
747 : :
748 : : ///
749 : : /// \name Associated RRSIG methods
750 : : ///
751 : : /// The associated RRSIG RRset is not supported in BasicRRset. For
752 : : /// ease of use, getRRsig() returns a null pointer (indicating no RRset).
753 : : /// The addRRsig()/removeRRsig() methods throw a "NotImplemented"
754 : : /// exception - if you are using a BasicRRset, you should not be trying
755 : : /// to modify signatures on it.
756 : : //@{
757 : : /// \brief Return pointer to this RRset's RRSIG RRset
758 : : ///
759 : : /// \exception NotImplemented Always thrown. Associated RRSIG RRsets are
760 : : /// not supported in this class.
761 : : ///
762 : : /// \return Null pointer, as this class does not support RRSIG records.
763 : 0 : virtual RRsetPtr getRRsig() const {
764 : 0 : return (RRsetPtr());
765 : : }
766 : :
767 : 0 : virtual void addRRsig(const rdata::ConstRdataPtr&) {
768 [ # # ][ # # ]: 0 : isc_throw(NotImplemented,
769 : : "BasicRRset does not implement the addRRsig() method");
770 : : }
771 : :
772 : 0 : virtual void addRRsig(const rdata::RdataPtr&) {
773 [ # # ][ # # ]: 0 : isc_throw(NotImplemented,
774 : : "BasicRRset does not implement the addRRsig() method");
775 : : }
776 : :
777 : 0 : virtual void addRRsig(const AbstractRRset&) {
778 [ # # ][ # # ]: 0 : isc_throw(NotImplemented,
779 : : "BasicRRset does not implement the addRRsig() method");
780 : : }
781 : :
782 : 0 : virtual void addRRsig(const ConstRRsetPtr&) {
783 [ # # ][ # # ]: 0 : isc_throw(NotImplemented,
784 : : "BasicRRset does not implement the addRRsig() method");
785 : : }
786 : :
787 : 0 : virtual void addRRsig(const RRsetPtr&) {
788 [ # # ][ # # ]: 0 : isc_throw(NotImplemented,
789 : : "BasicRRset does not implement the addRRsig() method");
790 : : }
791 : :
792 : 0 : virtual void removeRRsig() {
793 [ # # ][ # # ]: 0 : isc_throw(NotImplemented,
794 : : "BasicRRset does not implement the removeRRsig() method");
795 : : }
796 : : //@}
797 : : private:
798 : : BasicRRsetImpl* impl_;
799 : : };
800 : :
801 : : /// \brief The \c RRset class is a concrete derived class of
802 : : /// \c BasicRRset which contains a pointer to an additional RRset
803 : : /// containing associated RRSIG records. This allows DNSSEC aware
804 : : /// applications to treat data associated with a particular
805 : : /// QNAME/QTYPE/QCLASS as a single object.
806 : : class RRset : public BasicRRset {
807 : : public:
808 : : RRset(const Name& name, const RRClass& rrclass,
809 : : const RRType& rrtype, const RRTTL& ttl);
810 : :
811 : : virtual ~RRset();
812 : :
813 : : /// \brief Updates the owner name of the \c RRset, including RRSIGs if any
814 : 17 : virtual void setName(const Name& n) {
815 : 18 : BasicRRset::setName(n);
816 [ + + ][ # # ]: 18 : if (rrsig_) {
817 : 5 : rrsig_->setName(n);
818 : : }
819 : 17 : }
820 : :
821 : : /// \brief Updates the owner name of the \c RRset, including RRSIGs if any
822 : 374 : virtual void setTTL(const RRTTL& ttl) {
823 : 374 : BasicRRset::setTTL(ttl);
824 [ - + ]: 374 : if (rrsig_) {
825 : 0 : rrsig_->setTTL(ttl);
826 : : }
827 : 374 : }
828 : :
829 : : /// \brief Adds an RRSIG RR to this RRset's signatures
830 : 4572 : virtual void addRRsig(const rdata::ConstRdataPtr& rdata) {
831 [ + + ]: 4572 : if (!rrsig_) {
832 : 9136 : rrsig_ = RRsetPtr(new RRset(getName(), getClass(),
833 [ + - # # ]: 4568 : RRType::RRSIG(), getTTL()));
[ + - ]
834 : : }
835 [ + - ]: 9144 : rrsig_->addRdata(rdata);
836 : 4572 : }
837 : :
838 : : // Workaround for older versions of boost: some don't support implicit
839 : : // conversion from shared_ptr<X> to shared_ptr<const X>. Note: we should
840 : : // revisit the interface of managing RRset signatures, at which point this
841 : : // problem may go away.
842 : 4571 : virtual void addRRsig(const rdata::RdataPtr& rdata) {
843 : : // Don't try to convert as a reference here. SunStudio will reject it.
844 [ + - ]: 4571 : addRRsig(static_cast<const rdata::ConstRdataPtr>(rdata));
845 : 4571 : }
846 : :
847 : : /// \brief Adds an RRSIG RRset to this RRset
848 : 776 : virtual void addRRsig(const AbstractRRset& sigs) {
849 : 776 : RdataIteratorPtr it = sigs.getRdataIterator();
850 : :
851 [ + + ]: 776 : if (!rrsig_) {
852 : 1550 : rrsig_ = RRsetPtr(new RRset(getName(), getClass(),
853 [ + - ][ + - ]: 775 : RRType::RRSIG(), getTTL()));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
854 : : }
855 : :
856 [ + - ][ + - ]: 1555 : for (it->first(); !it->isLast(); it->next()) {
[ + - ][ + + ]
857 [ + - ][ + - ]: 779 : rrsig_->addRdata(it->getCurrent());
858 : : }
859 : 776 : }
860 : :
861 : 469 : virtual void addRRsig(const ConstRRsetPtr& sigs) { addRRsig(*sigs); }
862 : :
863 : : // Another workaround for older boost (see above)
864 : 301 : virtual void addRRsig(const RRsetPtr& sigs) { addRRsig(*sigs); }
865 : :
866 : : /// \brief Clear the RRSIGs for this RRset
867 [ + - ]: 6 : virtual void removeRRsig() { rrsig_ = RRsetPtr(); }
868 : :
869 : : /// \brief Return a pointer to this RRset's RRSIG RRset
870 : 5800 : RRsetPtr getRRsig() const { return (rrsig_); }
871 : : private:
872 : : RRsetPtr rrsig_;
873 : : };
874 : :
875 : :
876 : : /// \brief Insert the \c RRset as a string into stream.
877 : : ///
878 : : /// This method convert the \c rrset into a string and inserts it into the
879 : : /// output stream \c os.
880 : : ///
881 : : /// This function overloads the global \c operator<< to behave as described in
882 : : /// \c %ostream::%operator<< but applied to RRset objects.
883 : : ///
884 : : /// \param os A \c std::ostream object on which the insertion operation is
885 : : /// performed.
886 : : /// \param rrset A reference to a (derived class of) \c AbstractRRset object
887 : : /// output by the operation.
888 : : /// \return A reference to the same \c std::ostream object referenced by
889 : : /// parameter \c os after the insertion operation.
890 : : std::ostream& operator<<(std::ostream& os, const AbstractRRset& rrset);
891 : : } // end of namespace dns
892 : : } // end of namespace isc
893 : : #endif // __RRSET_H
894 : :
895 : : // Local Variables:
896 : : // mode: c++
897 : : // End:
|