rdataset.cc 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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 <exceptions/exceptions.h>
  15. #include <dns/rdata.h>
  16. #include <dns/rdataclass.h>
  17. #include <dns/rrclass.h>
  18. #include <dns/rrtype.h>
  19. #include <dns/rrset.h>
  20. #include "rdataset.h"
  21. #include "rdata_serialization.h"
  22. #include <boost/static_assert.hpp>
  23. #include <stdint.h>
  24. #include <algorithm>
  25. #include <cstring>
  26. #include <new> // for the placement new
  27. using namespace isc::dns;
  28. using namespace isc::dns::rdata;
  29. namespace isc {
  30. namespace datasrc {
  31. namespace memory {
  32. namespace {
  33. RRType
  34. getCoveredType(const Rdata& rdata) {
  35. const generic::RRSIG* rrsig_rdata =
  36. dynamic_cast<const generic::RRSIG*>(&rdata);
  37. if (!rrsig_rdata) {
  38. isc_throw(BadValue, "Non RRSIG is given where it's expected");
  39. }
  40. return (rrsig_rdata->typeCovered());
  41. }
  42. // A helper for lowestTTL: restore RRTTL object from wire-format 32-bit data.
  43. RRTTL
  44. restoreTTL(const void* ttl_data) {
  45. isc::util::InputBuffer b(ttl_data, sizeof(uint32_t));
  46. return (RRTTL(b));
  47. }
  48. // A helper function for create(): return the TTL that has lowest value
  49. // amount the given those of given rdataset (if non NULL), rrset, sig_rrset.
  50. RRTTL
  51. lowestTTL(const RdataSet* rdataset, ConstRRsetPtr& rrset,
  52. ConstRRsetPtr& sig_rrset)
  53. {
  54. if (rrset && sig_rrset) {
  55. const RRTTL tmp(std::min(rrset->getTTL(), sig_rrset->getTTL()));
  56. return (rdataset ?
  57. std::min(restoreTTL(rdataset->getTTLData()), tmp) : tmp);
  58. } else if (rrset) {
  59. return (rdataset ? std::min(restoreTTL(rdataset->getTTLData()),
  60. rrset->getTTL()) : rrset->getTTL());
  61. } else {
  62. return (rdataset ? std::min(restoreTTL(rdataset->getTTLData()),
  63. sig_rrset->getTTL()) :
  64. sig_rrset->getTTL());
  65. }
  66. }
  67. // Do some sanity checks on params of create and substract. Return the
  68. // target rrclass and rrtype (as they are produced as side effect of the
  69. // checks).
  70. //
  71. // The only reason for this function is to reuse common code of the
  72. // methods.
  73. std::pair<RRClass, RRType>
  74. sanityChecks(const ConstRRsetPtr& rrset, const ConstRRsetPtr &sig_rrset,
  75. const RdataSet *old_rdataset)
  76. {
  77. // Check basic validity
  78. if (!rrset && !sig_rrset) {
  79. isc_throw(BadValue, "Both RRset and RRSIG are NULL");
  80. }
  81. if (rrset && rrset->getRdataCount() == 0) {
  82. isc_throw(BadValue, "Empty RRset");
  83. }
  84. if (sig_rrset && sig_rrset->getRdataCount() == 0) {
  85. isc_throw(BadValue, "Empty SIG RRset");
  86. }
  87. if (rrset && sig_rrset && rrset->getClass() != sig_rrset->getClass()) {
  88. isc_throw(BadValue, "RR class doesn't match between RRset and RRSIG");
  89. }
  90. const RRClass rrclass = rrset ? rrset->getClass() : sig_rrset->getClass();
  91. const RRType rrtype = rrset ? rrset->getType() :
  92. getCoveredType(sig_rrset->getRdataIterator()->getCurrent());
  93. if (old_rdataset && old_rdataset->type != rrtype) {
  94. isc_throw(BadValue, "RR type doesn't match for merging RdataSet");
  95. }
  96. return (std::pair<RRClass, RRType>(rrclass, rrtype));
  97. }
  98. } // Anonymous namespace
  99. RdataSet*
  100. RdataSet::create(util::MemorySegment& mem_sgmt, RdataEncoder& encoder,
  101. ConstRRsetPtr rrset, ConstRRsetPtr sig_rrset,
  102. const RdataSet* old_rdataset)
  103. {
  104. const std::pair<RRClass, RRType>& rrparams =
  105. sanityChecks(rrset, sig_rrset, old_rdataset);
  106. const RRClass& rrclass = rrparams.first;
  107. const RRType& rrtype = rrparams.second;
  108. const RRTTL rrttl = lowestTTL(old_rdataset, rrset, sig_rrset);
  109. if (old_rdataset) {
  110. encoder.start(rrclass, rrtype, old_rdataset->getDataBuf(),
  111. old_rdataset->getRdataCount(),
  112. old_rdataset->getSigRdataCount());
  113. } else {
  114. encoder.start(rrclass, rrtype);
  115. }
  116. // Store RDATAs to be added and check assumptions on the number of them
  117. size_t rdata_count = old_rdataset ? old_rdataset->getRdataCount() : 0;
  118. if (rrset) {
  119. for (RdataIteratorPtr it = rrset->getRdataIterator();
  120. !it->isLast();
  121. it->next()) {
  122. if (encoder.addRdata(it->getCurrent())) {
  123. ++rdata_count;
  124. }
  125. }
  126. }
  127. if (rdata_count > MAX_RDATA_COUNT) {
  128. isc_throw(RdataSetError, "Too many RDATAs for RdataSet: "
  129. << rrset->getRdataCount() << ", must be <= "
  130. << MAX_RDATA_COUNT);
  131. }
  132. // Same for RRSIG
  133. size_t rrsig_count = old_rdataset ? old_rdataset->getSigRdataCount() : 0;
  134. if (sig_rrset) {
  135. for (RdataIteratorPtr it = sig_rrset->getRdataIterator();
  136. !it->isLast();
  137. it->next())
  138. {
  139. if (getCoveredType(it->getCurrent()) != rrtype) {
  140. isc_throw(BadValue, "Type covered doesn't match");
  141. }
  142. if (encoder.addSIGRdata(it->getCurrent())) {
  143. ++rrsig_count;
  144. }
  145. }
  146. }
  147. if (rrsig_count > MAX_RRSIG_COUNT) {
  148. isc_throw(RdataSetError, "Too many RRSIGs for RdataSet: "
  149. << sig_rrset->getRdataCount() << ", must be <= "
  150. << MAX_RRSIG_COUNT);
  151. }
  152. const size_t ext_rrsig_count_len =
  153. rrsig_count >= MANY_RRSIG_COUNT ? sizeof(uint16_t) : 0;
  154. const size_t data_len = encoder.getStorageLength();
  155. void* p = mem_sgmt.allocate(sizeof(RdataSet) + ext_rrsig_count_len +
  156. data_len);
  157. RdataSet* rdataset = new(p) RdataSet(rrtype, rdata_count, rrsig_count,
  158. rrttl);
  159. if (rrsig_count >= MANY_RRSIG_COUNT) {
  160. *rdataset->getExtSIGCountBuf() = rrsig_count;
  161. }
  162. encoder.encode(rdataset->getDataBuf(), data_len);
  163. return (rdataset);
  164. }
  165. void
  166. RdataSet::destroy(util::MemorySegment& mem_sgmt, RdataSet* rdataset,
  167. RRClass rrclass)
  168. {
  169. const size_t data_len =
  170. RdataReader(rrclass, rdataset->type,
  171. reinterpret_cast<const uint8_t*>(rdataset->getDataBuf()),
  172. rdataset->getRdataCount(), rdataset->getSigRdataCount(),
  173. &RdataReader::emptyNameAction,
  174. &RdataReader::emptyDataAction).getSize();
  175. const size_t ext_rrsig_count_len =
  176. rdataset->sig_rdata_count_ == MANY_RRSIG_COUNT ? sizeof(uint16_t) : 0;
  177. rdataset->~RdataSet();
  178. mem_sgmt.deallocate(rdataset,
  179. sizeof(RdataSet) + ext_rrsig_count_len + data_len);
  180. }
  181. namespace {
  182. // Convert the given RRTTL into the corresponding 32-bit unsigned integer,
  183. // in the network byte order. We do not use htonl() to be as portable as
  184. // possible.
  185. uint32_t
  186. convertTTL(RRTTL ttl) {
  187. const uint32_t ttl_val = ttl.getValue();
  188. uint8_t buf[4];
  189. buf[0] = (ttl_val & 0xff000000) >> 24;
  190. buf[1] = (ttl_val & 0x00ff0000) >> 16;
  191. buf[2] = (ttl_val & 0x0000ff00) >> 8;
  192. buf[3] = (ttl_val & 0x000000ff);
  193. uint32_t ret;
  194. std::memcpy(&ret, buf, sizeof(ret));
  195. return (ret);
  196. }
  197. }
  198. RdataSet::RdataSet(RRType type_param, size_t rdata_count,
  199. size_t sig_rdata_count, RRTTL ttl) :
  200. type(type_param),
  201. sig_rdata_count_(sig_rdata_count >= MANY_RRSIG_COUNT ?
  202. MANY_RRSIG_COUNT : sig_rdata_count),
  203. rdata_count_(rdata_count), ttl_(convertTTL(ttl))
  204. {
  205. // Make sure an RRType object is essentially a plain 16-bit value, so
  206. // our assumption of the size of RdataSet holds. If it's not the case
  207. // we should use the bare value instead of the class object.
  208. BOOST_STATIC_ASSERT(sizeof(type) == sizeof(uint16_t));
  209. // Confirm we meet the alignment requirement for RdataEncoder
  210. // ("this + 1" should be safely passed to the encoder).
  211. BOOST_STATIC_ASSERT(sizeof(RdataSet) % sizeof(uint16_t) == 0);
  212. }
  213. } // namespace memory
  214. } // namespace datasrc
  215. } // datasrc isc