nameserver_entry.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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 __NAMESERVER_ENTRY_H
  15. #define __NAMESERVER_ENTRY_H
  16. // Workaround for a problem with boost and sunstudio 5.10
  17. // There is a version check in there that appears wrong,
  18. // which makes including boost/thread.hpp fail
  19. // This will probably be fixed in a future version of boost,
  20. // in which case this part can be removed then
  21. #ifdef NEED_SUNPRO_WORKAROUND
  22. #if defined(__SUNPRO_CC) && __SUNPRO_CC == 0x5100
  23. #undef __SUNPRO_CC
  24. #define __SUNPRO_CC 0x5090
  25. #endif
  26. #endif // NEED_SUNPRO_WORKAROUND
  27. #include <string>
  28. #include <vector>
  29. #include <boost/thread.hpp>
  30. #include <boost/enable_shared_from_this.hpp>
  31. #include <exceptions/exceptions.h>
  32. #include <dns/rrset.h>
  33. #include <dns/rrtype.h>
  34. #include <resolve/resolver_interface.h>
  35. #include "address_entry.h"
  36. #include "asiolink.h"
  37. #include "nsas_types.h"
  38. #include "hash_key.h"
  39. #include "lru_list.h"
  40. #include "fetchable.h"
  41. #include "nsas_entry.h"
  42. #include "nameserver_address.h"
  43. namespace isc {
  44. namespace nsas {
  45. class NameserverAddress;
  46. /// \brief Inconsistent Owner Names
  47. ///
  48. /// Thrown if a NameserverEntry is constructed from both an A and AAAA RRset
  49. /// where the owner names do not match.
  50. class InconsistentOwnerNames : public Exception {
  51. public:
  52. InconsistentOwnerNames(const char* file, size_t line, const char* what) :
  53. isc::Exception(file, line, what)
  54. {}
  55. };
  56. /// \brief RTT is zero
  57. ///
  58. /// Thrown if a RTT related with an address is 0.
  59. class RTTIsZero : public Exception {
  60. public:
  61. RTTIsZero(const char* file, size_t line, const char* what) :
  62. isc::Exception(file, line, what)
  63. {}
  64. };
  65. /// \brief Inconsistent Class
  66. ///
  67. /// Thrown if a NameserverEntry is constructed from both an A and AAAA RRset
  68. /// where the classes do not match.
  69. class InconsistentClass : public Exception {
  70. public:
  71. InconsistentClass(const char* file, size_t line, const char* what) :
  72. isc::Exception(file, line, what)
  73. {}
  74. };
  75. class ZoneEntry;
  76. /// \brief Nameserver Entry
  77. ///
  78. /// Describes a nameserver and its addresses. A nameserver be authoritative
  79. /// for several zones (hence is pointed to by more than one zone entry), and
  80. /// may have several addresses associated with it.
  81. ///
  82. /// The addresses expire after their TTL has been reached. For simplicity,
  83. /// (and because it is unlikely that A and AAAA records from the same zone have
  84. /// different TTLs) there is one expiration time for all address records.
  85. /// When that is reached, all records are declared expired and new fetches
  86. /// started for the information.
  87. ///
  88. /// As this object will be stored in the nameserver address store LRU list,
  89. /// it is derived from the LRU list entry class.
  90. ///
  91. /// It uses shared_from_this in its methods. It must live inside a shared_ptr.
  92. class NameserverEntry : public NsasEntry<NameserverEntry>, public Fetchable {
  93. public:
  94. /// List of addresses associated with this nameserver
  95. typedef std::vector<NameserverAddress> AddressVector;
  96. typedef AddressVector::iterator AddressVectorIterator;
  97. /// \brief Constructor where no A records are supplied.
  98. ///
  99. /// \param name Name of the nameserver,
  100. /// \param class_code class of the nameserver
  101. NameserverEntry(const std::string& name,
  102. const isc::dns::RRClass& class_code) :
  103. name_(name),
  104. classCode_(class_code),
  105. expiration_(0)
  106. {}
  107. /*
  108. * \brief Return Address
  109. *
  110. * Returns a vector of addresses corresponding to this nameserver.
  111. *
  112. * \param addresses Vector of address entries into which will be appended
  113. * addresses that match the specified criteria. (The reason for
  114. * choosing this signature is that addresses from more than one
  115. * nameserver may be retrieved, in which case appending to an existing
  116. * list of addresses is convenient.)
  117. * \param family The family of address that is requested.
  118. * \param expired_ok Return addresses even when expired. This is here
  119. * because an address with TTL 0 is expired at the exact time it
  120. * arrives. But when we call the callback, the owner of callback
  121. * is allowed to use them anyway so it should set expired_ok
  122. * to true.
  123. * \return The state this is currently in. If the TTL expires, it enters
  124. * the EXPIRED state by itself and passes no addresses. It may be
  125. * IN_PROGRESS and still return some addresses (when one address family
  126. * arrived and is is returned, but the other is still on the way).
  127. * \todo Should we sort out unreachable addresses as well?
  128. */
  129. Fetchable::State getAddresses(AddressVector& addresses,
  130. AddressFamily family = ANY_OK, bool expired_ok = false);
  131. /// \brief Return Address that corresponding to the index
  132. ///
  133. /// \param index The address index in the address vector
  134. /// \param family The address family, V4_ONLY or V6_ONLY
  135. asiolink::IOAddress getAddressAtIndex(size_t index,
  136. AddressFamily family) const;
  137. /// \brief Update RTT
  138. ///
  139. /// Updates the RTT for a particular address
  140. ///
  141. /// \param address Address to update
  142. /// \param rtt New RTT for the address
  143. void setAddressRTT(const asiolink::IOAddress& address, uint32_t rtt);
  144. /// \brief Update RTT of the address that corresponding to the index
  145. ///
  146. /// Shouldn't probably be used directly. Use corresponding
  147. /// NameserverAddress.
  148. /// \param rtt Round-Trip Time
  149. /// \param index The address's index in address vector
  150. /// \param family The address family, V4_ONLY or V6_ONLY
  151. void updateAddressRTTAtIndex(uint32_t rtt, size_t index,
  152. AddressFamily family);
  153. /**
  154. * \short Update RTT of an address.
  155. *
  156. * This is similar to updateAddressRTTAtIndex, but you pass the address,
  157. * not it's index. Passing the index might be unsafe, because the position
  158. * of the address or the cound of addresses may change in time.
  159. *
  160. * \param rtt Round-Trip Time
  161. * \param address The address whose RTT should be updated.
  162. * \param family The address family, V4_ONLY or V6_ONLY
  163. */
  164. void updateAddressRTT(uint32_t rtt, const asiolink::IOAddress& address,
  165. AddressFamily family);
  166. /// \brief Set Address Unreachable
  167. ///
  168. /// Sets the specified address to be unreachable
  169. ///
  170. /// \param address Address to update
  171. void setAddressUnreachable(const asiolink::IOAddress& address);
  172. /// \return Owner Name of RRset
  173. std::string getName() const {
  174. return name_;
  175. }
  176. /// \return Class of RRset
  177. const isc::dns::RRClass& getClass() const {
  178. return classCode_;
  179. }
  180. /// \return Hash Key of the Nameserver
  181. virtual HashKey hashKey() const {
  182. return HashKey(name_, classCode_);
  183. }
  184. /// \return Hash Key of the Nameserver
  185. /// \return Expiration Time of Data
  186. ///
  187. /// Returns the expiration time of addresses for this nameserver. For
  188. /// simplicity, this quantity is calculated as the minimum expiration time
  189. /// of the A and AAAA address records.
  190. time_t getExpiration() const {
  191. return expiration_;
  192. }
  193. /// \name Obtaining the IP addresses from resolver
  194. //@{
  195. /// \short A callback that some information here arrived (or are unavailable).
  196. struct Callback {
  197. virtual void operator()(boost::shared_ptr<NameserverEntry> self) = 0;
  198. /// \short Virtual destructor, so descendants are properly cleaned up
  199. virtual ~ Callback() {}
  200. };
  201. /**
  202. * \short Asks the resolver for IP address (or addresses).
  203. *
  204. * Adds a callback for given zone when they are ready or the information
  205. * is found unreachable.
  206. *
  207. * If it is not in NOT_ASKED or EXPIRED state, it does not ask the for the
  208. * IP address again, it just inserts the callback. It is up to the caller
  209. * not to insert one callback multiple times.
  210. *
  211. * The callback might be called directly from this function.
  212. *
  213. * \param resolver Who to ask.
  214. * \param callback The callback.
  215. * \param family Which addresses are interesting to the caller. This does
  216. * not change which adresses are requested, but the callback might
  217. * be executed when at last one requested type is available (eg. not
  218. * waiting for the other one).
  219. * \return The state the entry is currently in. It can return UNREACHABLE
  220. * even when there are addresses, if there are no addresses for this
  221. * family.
  222. */
  223. void askIP(boost::shared_ptr<isc::resolve::ResolverInterface> resolver,
  224. boost::shared_ptr<Callback> callback, AddressFamily family);
  225. //@}
  226. private:
  227. mutable boost::recursive_mutex mutex_; ///< Mutex protecting this object
  228. std::string name_; ///< Canonical name of the nameserver
  229. isc::dns::RRClass classCode_; ///< Class of the nameserver
  230. /**
  231. * \short Address lists.
  232. *
  233. * Only V4_ONLY and V6_ONLY is used, therefore we use the nearest larger
  234. * value as the size of the array.
  235. *
  236. * previous_addresses is kept until the data arrive again on re-fetch and
  237. * is used to pick up the RTTs from there.
  238. */
  239. std::vector<AddressEntry> addresses_[ANY_OK], previous_addresses_[ANY_OK];
  240. time_t expiration_; ///< Summary expiration time. 0 = unset
  241. // Do we have some addresses already? Do we expect some to come?
  242. // These are set after asking for IP, if NOT_ASKED, they are uninitialized
  243. bool has_address_[ADDR_REQ_MAX], expect_address_[ADDR_REQ_MAX];
  244. // Callbacks from resolver
  245. class ResolverCallback;
  246. friend class ResolverCallback;
  247. // Callbacks inserted into this object
  248. typedef std::pair<AddressFamily, boost::shared_ptr<Callback> >
  249. CallbackPair;
  250. std::vector<CallbackPair> callbacks_;
  251. /// \short Private version that does the actual asking of one address type
  252. ///
  253. /// Call unlocked.
  254. void askIP(boost::shared_ptr<isc::resolve::ResolverInterface> resolver,
  255. const isc::dns::RRType&, AddressFamily);
  256. };
  257. } // namespace dns
  258. } // namespace isc
  259. #endif // __NAMESERVER_ENTRY_H