zone_checker.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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 ZONE_CHECKER_H
  15. #define ZONE_CHECKER_H 1
  16. #include <dns/dns_fwd.h>
  17. #include <boost/function.hpp>
  18. #include <string>
  19. namespace isc {
  20. namespace dns {
  21. /// \brief Set of callbacks used in zone checks.
  22. ///
  23. /// Objects of this class are expected to be passed to \c checkZone().
  24. class ZoneCheckerCallbacks {
  25. public:
  26. /// \brief Functor type of the callback on some issue (error or warning).
  27. ///
  28. /// Its parameter indicates the reason for the corresponding issue.
  29. typedef boost::function<void(const std::string& reason)> IssueCallback;
  30. /// \brief Constructor.
  31. ///
  32. /// Either or both of the callbacks can be empty, in which case the
  33. /// corresponding callback will be effectively no-operation. This can be
  34. /// used, for example, when the caller of \c checkZone() is only
  35. /// interested in the final result. Note that a \c NULL pointer will be
  36. /// implicitly converted to an empty functor object, so passing \c NULL
  37. /// suffices.
  38. ///
  39. /// \throw none
  40. ///
  41. /// \param error_callback Callback functor to be called on critical errors.
  42. /// \param warn_callback Callback functor to be called on non critical
  43. /// issues.
  44. ZoneCheckerCallbacks(const IssueCallback& error_callback,
  45. const IssueCallback& warn_callback) :
  46. error_callback_(error_callback), warn_callback_(warn_callback)
  47. {}
  48. /// \brief Call the callback for a critical error.
  49. ///
  50. /// This method itself is exception free, but propagates any exception
  51. /// thrown from the callback.
  52. ///
  53. /// \param reason Textual representation of the reason for the error.
  54. void error(const std::string& reason) const {
  55. if (!error_callback_.empty()) {
  56. error_callback_(reason);
  57. }
  58. }
  59. /// \brief Call the callback for a non critical issue.
  60. ///
  61. /// This method itself is exception free, but propagates any exception
  62. /// thrown from the callback.
  63. ///
  64. /// \param reason Textual representation of the reason for the issue.
  65. void warn(const std::string& reason) const {
  66. if (!warn_callback_.empty())
  67. warn_callback_(reason);
  68. }
  69. private:
  70. IssueCallback error_callback_;
  71. IssueCallback warn_callback_;
  72. };
  73. /// \brief Perform basic integrity checks on zone RRsets.
  74. ///
  75. /// This function performs some lightweight checks on zone's SOA and (apex)
  76. /// NS records. Here, lightweight means it doesn't require traversing
  77. /// the entire zone, and should be expected to complete reasonably quickly
  78. /// regardless of the size of the zone.
  79. ///
  80. /// It distinguishes "critical" errors and other undesirable issues:
  81. /// the former should be interpreted as the resulting zone shouldn't be used
  82. /// further, e.g, by an authoritative server implementation; the latter means
  83. /// the issues are better to be addressed but are not necessarily considered
  84. /// to make the zone invalid. Critical errors are reported via the
  85. /// \c error() method of \c callbacks, and non critical issues are reported
  86. /// via its \c warn() method.
  87. ///
  88. /// Specific checks performed by this function is as follows. Failure of
  89. /// a check is considered a critical error unless noted otherwise:
  90. /// - There is exactly one SOA RR at the zone apex.
  91. /// - There is at least one NS RR at the zone apex.
  92. /// - For each apex NS record, if the NS name (the RDATA of the record) is
  93. /// in the zone (i.e., it's a subdomain of the zone origin and above any
  94. /// zone cut due to delegation), check the following:
  95. /// - the NS name should have an address record (AAAA or A). Failure of
  96. /// this check is considered a non critical issue.
  97. /// - the NS name does not have a CNAME. This is prohibited by Section
  98. /// 10.3 of RFC 2181.
  99. /// - the NS name is not subject to DNAME substitution. This is prohibited
  100. /// by Section 4 of RFC 6672.
  101. /// .
  102. ///
  103. /// In addition, when the check is completed without any critical error, this
  104. /// function guarantees that RRsets for the SOA and (apex) NS stored in the
  105. /// passed RRset collection have the expected type of Rdata objects,
  106. /// i.e., generic::SOA and generic::NS, respectively. (This is normally
  107. /// expected to be the case, but not guaranteed by the API).
  108. ///
  109. /// As for the check on the existence of AAAA or A records for NS names,
  110. /// it should be noted that BIND 9 treats this as a critical error.
  111. /// It's not clear whether it's an implementation dependent behavior or
  112. /// based on the protocol standard (it looks like the former), but to make
  113. /// it sure we need to confirm there is even no wildcard match for the names.
  114. /// This should be a very rare configuration, and more expensive to detect,
  115. /// so we do not check this condition, and treat this case as a non critical
  116. /// issue.
  117. ///
  118. /// This function indicates the result of the checks (whether there is a
  119. /// critical error) via the return value: It returns \c true if there is no
  120. /// critical error and returns \c false otherwise. It doesn't throw an
  121. /// exception on encountering an error so that it can report as many errors
  122. /// as possible in a single call. If an exception is a better way to signal
  123. /// the error, the caller can pass a callback object that throws from its
  124. /// \c error() method.
  125. ///
  126. /// This function can still throw an exception if it finds a really bogus
  127. /// condition that is most likely to be an implementation bug of the caller.
  128. /// Such cases include when an RRset contained in the RRset collection is
  129. /// empty.
  130. ///
  131. /// \throw Unexpected Conditions that suggest a caller's bug (see the
  132. /// description)
  133. ///
  134. /// \param zone_name The name of the zone to be checked
  135. /// \param zone_class The RR class of the zone to be checked
  136. /// \param zone_rrsets The collection of RRsets of the zone
  137. /// \param callbacks Callback object used to report errors and issues
  138. ///
  139. /// \return \c true if no critical errors are found; \c false otherwise.
  140. bool
  141. checkZone(const Name& zone_name, const RRClass& zone_class,
  142. const RRsetCollectionBase& zone_rrsets,
  143. const ZoneCheckerCallbacks& callbacks);
  144. } // namespace dns
  145. } // namespace isc
  146. #endif // ZONE_CHECKER_H
  147. // Local Variables:
  148. // mode: c++
  149. // End: