zone_data_updater.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. // Copyright (C) 2012 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 DATASRC_ZONE_DATA_UPDATER_H
  15. #define DATASRC_ZONE_DATA_UPDATER_H 1
  16. #include <datasrc/exceptions.h>
  17. #include <datasrc/memory/zone_data.h>
  18. #include <datasrc/memory/rdata_serialization.h>
  19. #include <dns/name.h>
  20. #include <dns/rrclass.h>
  21. #include <dns/rrset.h>
  22. #include <dns/nsec3hash.h>
  23. #include <util/memory_segment.h>
  24. #include <boost/noncopyable.hpp>
  25. namespace isc {
  26. namespace datasrc {
  27. namespace memory {
  28. /// \brief A helper class to add records to a zone.
  29. ///
  30. /// This class provides an \c add() method that can be used to add
  31. /// RRsets to a ZoneData instance. The RRsets are first validated for
  32. /// correctness and consistency, and their data is made into RdataSets
  33. /// which are added to the ZoneData for the zone.
  34. ///
  35. /// The way to use this is to make a ZoneDataUpdater instance, and call
  36. /// add() on it as follows:
  37. ///
  38. /// \code
  39. /// ZoneDataUpdater updater(mem_sgmt, rrclass, zone_origin_name, zone_data);
  40. /// ConstRRsetPtr rrset;
  41. /// updater.add(rrset, ConstRRsetPtr());
  42. /// \endcode
  43. ///
  44. /// We enforce that instances are non-copyable as it's pointless to make
  45. /// copies.
  46. class ZoneDataUpdater : boost::noncopyable {
  47. public:
  48. ///
  49. /// \name Constructors and Destructor.
  50. ///
  51. //@{
  52. /// The constructor.
  53. ///
  54. /// \param mem_sgmt The memory segment used for the zone data.
  55. /// \param rrclass The RRclass of the zone data.
  56. /// \param zone_name The Name of the zone under which records will be
  57. /// added.
  58. /// \param zone_data The ZoneData object which is populated with
  59. /// record data.
  60. /// \throw InvalidOperation if there's already a zone data updater
  61. /// on the given memory segment. Currently, at most one zone data
  62. /// updater may exist on the same memory segment.
  63. ZoneDataUpdater(util::MemorySegment& mem_sgmt,
  64. isc::dns::RRClass rrclass,
  65. const isc::dns::Name& zone_name,
  66. ZoneData& zone_data) :
  67. mem_sgmt_(mem_sgmt),
  68. rrclass_(rrclass),
  69. zone_name_(zone_name),
  70. hash_(NULL),
  71. zone_data_(&zone_data)
  72. {
  73. if (mem_sgmt_.getNamedAddress("updater_zone_data").first) {
  74. isc_throw(isc::InvalidOperation, "A ZoneDataUpdater already exists"
  75. " on this memory segment. Destroy it first.");
  76. }
  77. if (mem_sgmt_.setNamedAddress("updater_zone_data", zone_data_)) {
  78. // It might have relocated during the set
  79. zone_data_ =
  80. static_cast<ZoneData*>(mem_sgmt_.getNamedAddress(
  81. "updater_zone_data").second);
  82. }
  83. assert(zone_data_);
  84. }
  85. /// The destructor.
  86. ~ZoneDataUpdater() {
  87. mem_sgmt_.clearNamedAddress("updater_zone_data");
  88. delete hash_;
  89. }
  90. //@}
  91. /// This is thrown if the provided RRset parameter passed to \c
  92. /// add() is NULL.
  93. struct NullRRset : public InvalidParameter {
  94. NullRRset(const char* file, size_t line, const char* what) :
  95. InvalidParameter(file, line, what)
  96. {}
  97. };
  98. /// \brief General failure exception for \c add().
  99. ///
  100. /// This is thrown against general error cases in adding an RRset
  101. /// to the zone.
  102. struct AddError : public ZoneLoaderException {
  103. AddError(const char* file, size_t line, const char* what) :
  104. ZoneLoaderException(file, line, what)
  105. {}
  106. };
  107. /// \brief Add an RRset to the zone.
  108. ///
  109. /// This is the core method of this class. It is used to add an
  110. /// RRset to the ZoneData associated with this object. The RRset is
  111. /// first validated for correctness and consistency with the rest of
  112. /// the records in the zone, and then an RdataSet is created and
  113. /// populated with the record data and added to the ZoneData for the
  114. /// name in the RRset.
  115. ///
  116. /// At least one of \c rrset or \c sig_rrset must be non NULL.
  117. /// \c sig_rrset can be reasonably NULL when \c rrset is not signed in
  118. /// the zone; it's unusual that \c rrset is NULL, but is still possible
  119. /// if these RRsets are given separately to the loader, or if even the
  120. /// zone is half broken and really contains an RRSIG that doesn't have
  121. /// any covered RRset. This implementation supports these cases (but
  122. /// see the note below).
  123. ///
  124. /// There is one tricky case: Due to a limitation of the current
  125. /// implementation, it cannot accept an RRSIG for NSEC3 without the covered
  126. /// NSEC3, unless at least one NSEC3 or NSEC3PARAM has been added.
  127. /// In this case an isc::NotImplemented exception will be thrown. It
  128. /// should be very rare in practice, and hopefully wouldn't be a real
  129. /// issue.
  130. ///
  131. /// \note Due to limitations of the current implementation, if a
  132. /// (non RRSIG) RRset and its RRSIG are added separately in different
  133. /// calls to this method, the second attempt will be rejected due to
  134. /// an \c AddError exception. This will be loosened in Trac
  135. /// ticket #2441.
  136. ///
  137. /// \throw NullRRset Both \c rrset and sig_rrset is NULL
  138. /// \throw AddError any of a variety of validation checks fail for the
  139. /// \c rrset and its associated \c sig_rrset.
  140. /// \throw NotImplemented RRSIG for NSEC3 cannot be added due to internal
  141. /// restriction.
  142. ///
  143. /// \param rrset The RRset to be added.
  144. /// \param sig_rrset An associated RRSIG RRset for the \c rrset. It
  145. /// can be empty if there is no RRSIG for the \c rrset.
  146. void add(const isc::dns::ConstRRsetPtr& rrset,
  147. const isc::dns::ConstRRsetPtr& sig_rrset);
  148. private:
  149. // Add the necessary magic for any wildcard contained in 'name'
  150. // (including itself) to be found in the zone.
  151. //
  152. // In order for wildcard matching to work correctly in the zone finder,
  153. // we must ensure that a node for the wildcarding level exists in the
  154. // backend ZoneTree.
  155. // E.g. if the wildcard name is "*.sub.example." then we must ensure
  156. // that "sub.example." exists and is marked as a wildcard level.
  157. // Note: the "wildcarding level" is for the parent name of the wildcard
  158. // name (such as "sub.example.").
  159. //
  160. // We also perform the same trick for empty wild card names possibly
  161. // contained in 'name' (e.g., '*.foo.example' in 'bar.*.foo.example').
  162. void addWildcards(const isc::dns::Name& name);
  163. void addInternal(const isc::dns::Name& name,
  164. const isc::dns::RRType& rrtype,
  165. const isc::dns::ConstRRsetPtr& rrset,
  166. const isc::dns::ConstRRsetPtr& rrsig);
  167. // Does some checks in context of the data that are already in the
  168. // zone. Currently checks for forbidden combinations of RRsets in
  169. // the same domain (CNAME+anything, DNAME+NS). If such condition is
  170. // found, it throws AddError.
  171. void contextCheck(const isc::dns::AbstractRRset& rrset,
  172. const RdataSet* set) const;
  173. // Validate rrset before adding it to the zone. If something is wrong
  174. // it throws an exception. It doesn't modify the zone, and provides
  175. // the strong exception guarantee.
  176. void validate(const isc::dns::ConstRRsetPtr rrset) const;
  177. const isc::dns::NSEC3Hash* getNSEC3Hash();
  178. template <typename T>
  179. void setupNSEC3(const isc::dns::ConstRRsetPtr rrset);
  180. void addNSEC3(const isc::dns::Name& name,
  181. const isc::dns::ConstRRsetPtr& rrset,
  182. const isc::dns::ConstRRsetPtr& rrsig);
  183. void addRdataSet(const isc::dns::Name& name,
  184. const isc::dns::RRType& rrtype,
  185. const isc::dns::ConstRRsetPtr& rrset,
  186. const isc::dns::ConstRRsetPtr& rrsig);
  187. util::MemorySegment& mem_sgmt_;
  188. const isc::dns::RRClass rrclass_;
  189. const isc::dns::Name& zone_name_;
  190. RdataEncoder encoder_;
  191. const isc::dns::NSEC3Hash* hash_;
  192. ZoneData* zone_data_;
  193. };
  194. } // namespace memory
  195. } // namespace datasrc
  196. } // namespace isc
  197. #endif // DATASRC_ZONE_DATA_UPDATER_H
  198. // Local Variables:
  199. // mode: c++
  200. // End: