rrset.h 38 KB

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