zone_data.cc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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. #include <util/memory_segment.h>
  15. #include <dns/name.h>
  16. #include <dns/rrclass.h>
  17. #include <dns/rdataclass.h>
  18. #include "rdataset.h"
  19. #include "rdata_serialization.h"
  20. #include "zone_data.h"
  21. #include "segment_object_holder.h"
  22. #include <boost/bind.hpp>
  23. #include <boost/function.hpp>
  24. #include <cassert>
  25. #include <cstring>
  26. #include <new> // for the placement new
  27. #include <vector>
  28. using namespace isc::dns;
  29. using namespace isc::dns::rdata;
  30. namespace isc {
  31. namespace datasrc {
  32. namespace memory {
  33. namespace {
  34. void
  35. rdataSetDeleter(RRClass rrclass, util::MemorySegment* mem_sgmt,
  36. RdataSet* rdataset_head)
  37. {
  38. RdataSet* rdataset_next;
  39. for (RdataSet* rdataset = rdataset_head;
  40. rdataset != NULL;
  41. rdataset = rdataset_next)
  42. {
  43. rdataset_next = rdataset->getNext();
  44. RdataSet::destroy(*mem_sgmt, rdataset, rrclass);
  45. }
  46. }
  47. void
  48. nullDeleter(RdataSet* rdataset_head) {
  49. assert(rdataset_head == NULL);
  50. }
  51. }
  52. NSEC3Data*
  53. NSEC3Data::create(util::MemorySegment& mem_sgmt,
  54. const Name& zone_origin,
  55. const generic::NSEC3PARAM& rdata)
  56. {
  57. return (NSEC3Data::create(mem_sgmt, zone_origin,
  58. rdata.getHashalg(), rdata.getFlags(),
  59. rdata.getIterations(), rdata.getSalt()));
  60. }
  61. NSEC3Data*
  62. NSEC3Data::create(util::MemorySegment& mem_sgmt,
  63. const Name& zone_origin,
  64. const generic::NSEC3& rdata)
  65. {
  66. return (NSEC3Data::create(mem_sgmt, zone_origin,
  67. rdata.getHashalg(), rdata.getFlags(),
  68. rdata.getIterations(), rdata.getSalt()));
  69. }
  70. NSEC3Data*
  71. NSEC3Data::create(util::MemorySegment& mem_sgmt,
  72. const Name& zone_origin,
  73. uint8_t hashalg, uint8_t flags, uint16_t iterations,
  74. const std::vector<uint8_t>& salt)
  75. {
  76. // NSEC3Data allocation can throw. To avoid leaking the tree, we manage
  77. // it in the holder.
  78. // Note: we won't add any RdataSet, so we use the NO-OP deleter
  79. // (with an assertion check for that).
  80. typedef boost::function<void(RdataSet*)> RdataSetDeleterType;
  81. detail::SegmentObjectHolder<ZoneTree, RdataSetDeleterType> holder(
  82. mem_sgmt, ZoneTree::create(mem_sgmt, true),
  83. boost::bind(nullDeleter, _1));
  84. ZoneTree* tree = holder.get();
  85. const ZoneTree::Result result =
  86. tree->insert(mem_sgmt, zone_origin, NULL);
  87. assert(result == ZoneTree::SUCCESS);
  88. const size_t salt_len = salt.size();
  89. void* p = mem_sgmt.allocate(sizeof(NSEC3Data) + 1 + salt_len);
  90. NSEC3Data* const param_data =
  91. new(p) NSEC3Data(holder.release(), hashalg, flags, iterations);
  92. uint8_t* dp = param_data->getSaltBuf();
  93. *dp++ = salt_len;
  94. if (salt_len > 0) {
  95. std::memcpy(dp, &salt.at(0), salt_len); // use at for safety
  96. }
  97. return (param_data);
  98. }
  99. void
  100. NSEC3Data::destroy(util::MemorySegment& mem_sgmt, NSEC3Data* data,
  101. RRClass nsec3_class)
  102. {
  103. ZoneTree::destroy(mem_sgmt, data->nsec3_tree_.get(),
  104. boost::bind(rdataSetDeleter, nsec3_class, &mem_sgmt,
  105. _1));
  106. mem_sgmt.deallocate(data, sizeof(NSEC3Data) + 1 + data->getSaltLen());
  107. }
  108. void
  109. NSEC3Data::insertName(util::MemorySegment& mem_sgmt, const Name& name,
  110. ZoneNode** node)
  111. {
  112. const ZoneTree::Result result = nsec3_tree_->insert(mem_sgmt, name, node);
  113. // This should be ensured by the API:
  114. assert((result == ZoneTree::SUCCESS ||
  115. result == ZoneTree::ALREADYEXISTS) && node != NULL);
  116. }
  117. namespace {
  118. // A helper to convert a TTL value in network byte order and set it in
  119. // ZoneData::min_ttl_. We can use util::OutputBuffer, but copy the logic
  120. // here to guarantee it is exception free.
  121. // Note: essentially this function is a local (re)implementation of the
  122. // standard htonl() library function, but we avoid relying on it in case it's
  123. // not available (it's not in the C++ standard library).
  124. void
  125. setTTLInNetOrder(uint32_t val, uint32_t* result) {
  126. uint8_t buf[4];
  127. buf[0] = static_cast<uint8_t>((val & 0xff000000) >> 24);
  128. buf[1] = static_cast<uint8_t>((val & 0x00ff0000) >> 16);
  129. buf[2] = static_cast<uint8_t>((val & 0x0000ff00) >> 8);
  130. buf[3] = static_cast<uint8_t>(val & 0x000000ff);
  131. std::memcpy(result, buf, sizeof(*result));
  132. }
  133. }
  134. ZoneData::ZoneData(ZoneTree* zone_tree, ZoneNode* origin_node) :
  135. zone_tree_(zone_tree), origin_node_(origin_node),
  136. min_ttl_(0) // tentatively set to silence static checkers
  137. {
  138. setTTLInNetOrder(RRTTL::MAX_TTL().getValue(), &min_ttl_);
  139. }
  140. ZoneData*
  141. ZoneData::create(util::MemorySegment& mem_sgmt, const Name& zone_origin) {
  142. // ZoneTree::insert() and ZoneData allocation can throw. See also
  143. // NSEC3Data::create().
  144. typedef boost::function<void(RdataSet*)> RdataSetDeleterType;
  145. detail::SegmentObjectHolder<ZoneTree, RdataSetDeleterType> holder(
  146. mem_sgmt, ZoneTree::create(mem_sgmt, true),
  147. boost::bind(nullDeleter, _1));
  148. ZoneTree* tree = holder.get();
  149. ZoneNode* origin_node = NULL;
  150. const ZoneTree::Result result =
  151. tree->insert(mem_sgmt, zone_origin, &origin_node);
  152. assert(result == ZoneTree::SUCCESS);
  153. void* p = mem_sgmt.allocate(sizeof(ZoneData));
  154. ZoneData* zone_data = new(p) ZoneData(holder.release(), origin_node);
  155. return (zone_data);
  156. }
  157. void
  158. ZoneData::destroy(util::MemorySegment& mem_sgmt, ZoneData* zone_data,
  159. RRClass zone_class)
  160. {
  161. ZoneTree::destroy(mem_sgmt, zone_data->zone_tree_.get(),
  162. boost::bind(rdataSetDeleter, zone_class, &mem_sgmt,
  163. _1));
  164. if (zone_data->nsec3_data_) {
  165. NSEC3Data::destroy(mem_sgmt, zone_data->nsec3_data_.get(), zone_class);
  166. }
  167. mem_sgmt.deallocate(zone_data, sizeof(ZoneData));
  168. }
  169. void
  170. ZoneData::insertName(util::MemorySegment& mem_sgmt, const Name& name,
  171. ZoneNode** node)
  172. {
  173. const ZoneTree::Result result = zone_tree_->insert(mem_sgmt, name, node);
  174. // This should be ensured by the API:
  175. assert((result == ZoneTree::SUCCESS ||
  176. result == ZoneTree::ALREADYEXISTS) && node != NULL);
  177. }
  178. void
  179. ZoneData::setMinTTL(uint32_t min_ttl_val) {
  180. setTTLInNetOrder(min_ttl_val, &min_ttl_);
  181. }
  182. } // namespace memory
  183. } // namespace datasrc
  184. } // datasrc isc