treenode_rrset.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  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 <util/buffer.h>
  16. #include <dns/messagerenderer.h>
  17. #include <dns/name.h>
  18. #include <dns/rrclass.h>
  19. #include <dns/rrtype.h>
  20. #include <dns/rrttl.h>
  21. #include <dns/rdata.h>
  22. #include <dns/rrset.h>
  23. #include "treenode_rrset.h"
  24. #include "rdata_serialization.h"
  25. #include <boost/bind.hpp>
  26. #include <cassert>
  27. #include <string>
  28. #include <vector>
  29. using namespace isc::dns;
  30. using namespace isc::dns::rdata;
  31. namespace isc {
  32. namespace datasrc {
  33. namespace memory {
  34. TreeNodeRRset::TreeNodeRRset(const dns::Name& realname,
  35. const dns::RRClass& rrclass,
  36. const ZoneNode* node, const RdataSet* rdataset,
  37. bool dnssec_ok) :
  38. node_(node), rdataset_(rdataset),
  39. rrsig_count_(rdataset_->getSigRdataCount()), rrclass_(rrclass),
  40. dnssec_ok_(dnssec_ok), name_(NULL)
  41. {
  42. const LabelSequence labels(realname);
  43. const size_t labels_storangelen = labels.getSerializedLength();
  44. realname_buf_ = new uint8_t[labels_storangelen];
  45. labels.serialize(realname_buf_, labels_storangelen);
  46. }
  47. const Name&
  48. TreeNodeRRset::getName() const {
  49. if (name_ == NULL) {
  50. uint8_t labels_buf[LabelSequence::MAX_SERIALIZED_LENGTH];
  51. const LabelSequence name_labels = getOwnerLabels(labels_buf);
  52. size_t data_len;
  53. const uint8_t* data = name_labels.getData(&data_len);
  54. util::InputBuffer buffer(data, data_len);
  55. name_ = new Name(buffer);
  56. }
  57. return (*name_);
  58. }
  59. const RRTTL&
  60. TreeNodeRRset::getTTL() const {
  61. isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
  62. }
  63. void
  64. TreeNodeRRset::setName(const Name&) {
  65. isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
  66. }
  67. void
  68. TreeNodeRRset::setTTL(const RRTTL&) {
  69. isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
  70. }
  71. std::string
  72. TreeNodeRRset::toText() const {
  73. // Create TTL from internal data
  74. util::InputBuffer ttl_buffer(rdataset_->getTTLData(), sizeof(uint32_t));
  75. const RRTTL ttl(ttl_buffer);
  76. // Dump the main RRset, if not empty
  77. std::string ret;
  78. RRsetPtr tmp_rrset;
  79. for (RdataIteratorPtr rit = getRdataIterator();
  80. !rit->isLast();
  81. rit->next())
  82. {
  83. if (!tmp_rrset) {
  84. tmp_rrset = RRsetPtr(new RRset(getName(), rrclass_, getType(),
  85. ttl));
  86. }
  87. tmp_rrset->addRdata(rit->getCurrent());
  88. }
  89. if (tmp_rrset) {
  90. ret = tmp_rrset->toText();
  91. }
  92. // Dump any RRSIGs
  93. tmp_rrset.reset();
  94. for (RdataIteratorPtr rit = getSigRdataIterator();
  95. !rit->isLast();
  96. rit->next())
  97. {
  98. if (!tmp_rrset) {
  99. tmp_rrset = RRsetPtr(new RRset(getName(), rrclass_,
  100. RRType::RRSIG(), ttl));
  101. }
  102. tmp_rrset->addRdata(rit->getCurrent());
  103. }
  104. if (tmp_rrset) {
  105. ret += tmp_rrset->toText();
  106. }
  107. return (ret);
  108. }
  109. namespace {
  110. void
  111. renderName(const LabelSequence& name_labels, RdataNameAttributes attr,
  112. AbstractMessageRenderer* renderer)
  113. {
  114. renderer->writeName(name_labels, (attr & NAMEATTR_COMPRESSIBLE) != 0);
  115. }
  116. void
  117. renderData(const void* data, size_t data_len,
  118. AbstractMessageRenderer* renderer)
  119. {
  120. renderer->writeData(data, data_len);
  121. }
  122. // Common code logic for rendering a single (either main or RRSIG) RRset.
  123. size_t
  124. writeRRs(AbstractMessageRenderer& renderer, size_t rr_count,
  125. const LabelSequence& name_labels, const RRType& rrtype,
  126. const RRClass& rrclass, const void* ttl_data,
  127. RdataReader& reader, bool (RdataReader::* rdata_iterate_fn)())
  128. {
  129. for (size_t i = 0; i < rr_count; ++i) {
  130. const size_t pos0 = renderer.getLength();
  131. // Name, type, class, TTL
  132. renderer.writeName(name_labels, true);
  133. rrtype.toWire(renderer);
  134. rrclass.toWire(renderer);
  135. renderer.writeData(ttl_data, sizeof(uint32_t));
  136. // RDLEN and RDATA
  137. const size_t pos = renderer.getLength();
  138. renderer.skip(sizeof(uint16_t)); // leave the space for RDLENGTH
  139. const bool rendered = (reader.*rdata_iterate_fn)();
  140. assert(rendered == true);
  141. renderer.writeUint16At(renderer.getLength() - pos - sizeof(uint16_t),
  142. pos);
  143. // Check if truncation would happen
  144. if (renderer.getLength() > renderer.getLengthLimit()) {
  145. renderer.trim(renderer.getLength() - pos0);
  146. renderer.setTruncated();
  147. return (i);
  148. }
  149. }
  150. return (rr_count);
  151. }
  152. }
  153. unsigned int
  154. TreeNodeRRset::toWire(AbstractMessageRenderer& renderer) const {
  155. RdataReader reader(rrclass_, rdataset_->type, rdataset_->getDataBuf(),
  156. rdataset_->getRdataCount(), rrsig_count_,
  157. boost::bind(renderName, _1, _2, &renderer),
  158. boost::bind(renderData, _1, _2, &renderer));
  159. // Get the owner name of the RRset in the form of LabelSequence.
  160. uint8_t labels_buf[LabelSequence::MAX_SERIALIZED_LENGTH];
  161. const LabelSequence name_labels = getOwnerLabels(labels_buf);
  162. // Render the main (non RRSIG) RRs
  163. const size_t rendered_rdata_count =
  164. writeRRs(renderer, rdataset_->getRdataCount(), name_labels,
  165. rdataset_->type, rrclass_, rdataset_->getTTLData(), reader,
  166. &RdataReader::iterateRdata);
  167. if (renderer.isTruncated()) {
  168. return (rendered_rdata_count);
  169. }
  170. const bool rendered = reader.iterateRdata();
  171. assert(rendered == false); // we should've reached the end
  172. // Render any RRSIGs, if we supposed to do so
  173. const size_t rendered_rrsig_count = dnssec_ok_ ?
  174. writeRRs(renderer, rrsig_count_, name_labels, RRType::RRSIG(),
  175. rrclass_, rdataset_->getTTLData(), reader,
  176. &RdataReader::iterateSingleSig) : 0;
  177. return (rendered_rdata_count + rendered_rrsig_count);
  178. }
  179. unsigned int
  180. TreeNodeRRset::toWire(isc::util::OutputBuffer& /*buffer*/) const {
  181. isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
  182. }
  183. void
  184. TreeNodeRRset::addRdata(rdata::ConstRdataPtr) {
  185. isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
  186. }
  187. void
  188. TreeNodeRRset::addRdata(const rdata::Rdata&) {
  189. isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
  190. }
  191. namespace {
  192. // In this namespace we define a set of helper stuff to implement the
  193. // RdataIterator for the TreeNodeRRset. We should eventually optimize
  194. // the code so that performance sensitive path won't require the iterator,
  195. // so, at the moment, the implementation is straightforward, but less
  196. // efficient one: It builds a vector of Rdata objects on construction,
  197. // and its getCurrent() returns the stored data.
  198. class TreeNodeRdataIterator : public RdataIterator {
  199. public:
  200. TreeNodeRdataIterator(const std::vector<ConstRdataPtr>& rdata_list) :
  201. rdata_list_(rdata_list), rdata_it_(rdata_list_.begin())
  202. {}
  203. virtual void first() { rdata_it_ = rdata_list_.begin(); }
  204. virtual void next() {
  205. ++rdata_it_;
  206. }
  207. virtual const rdata::Rdata& getCurrent() const {
  208. return (**rdata_it_);
  209. }
  210. virtual bool isLast() const { return (rdata_it_ == rdata_list_.end()); }
  211. private:
  212. const std::vector<ConstRdataPtr> rdata_list_;
  213. std::vector<ConstRdataPtr>::const_iterator rdata_it_;
  214. };
  215. void
  216. renderNameToBuffer(const LabelSequence& name_labels, RdataNameAttributes,
  217. util::OutputBuffer* buffer)
  218. {
  219. size_t data_len;
  220. const uint8_t *data = name_labels.getData(&data_len);
  221. buffer->writeData(data, data_len);
  222. }
  223. void
  224. renderDataToBuffer(const void* data, size_t data_len,
  225. util::OutputBuffer* buffer)
  226. {
  227. buffer->writeData(data, data_len);
  228. }
  229. }
  230. RdataIteratorPtr
  231. TreeNodeRRset::getRdataIteratorInternal(bool is_rrsig, size_t count) const {
  232. util::OutputBuffer buffer(0);
  233. RdataReader reader(rrclass_, rdataset_->type, rdataset_->getDataBuf(),
  234. rdataset_->getRdataCount(), rrsig_count_,
  235. boost::bind(renderNameToBuffer, _1, _2, &buffer),
  236. boost::bind(renderDataToBuffer, _1, _2, &buffer));
  237. std::vector<ConstRdataPtr> rdata_list;
  238. for (size_t i = 0; i < count; ++i) {
  239. buffer.clear();
  240. const bool rendered = is_rrsig ? reader.iterateSingleSig() :
  241. reader.iterateRdata();
  242. assert(rendered == true);
  243. util::InputBuffer ib(buffer.getData(), buffer.getLength());
  244. rdata_list.push_back(
  245. createRdata(is_rrsig ? RRType::RRSIG() : rdataset_->type, rrclass_,
  246. ib, ib.getLength()));
  247. }
  248. return (RdataIteratorPtr(new TreeNodeRdataIterator(rdata_list)));
  249. }
  250. RdataIteratorPtr
  251. TreeNodeRRset::getRdataIterator() const {
  252. return (getRdataIteratorInternal(false, rdataset_->getRdataCount()));
  253. }
  254. RdataIteratorPtr
  255. TreeNodeRRset::getSigRdataIterator() const {
  256. return (getRdataIteratorInternal(true, dnssec_ok_ ? rrsig_count_ : 0));
  257. }
  258. RRsetPtr
  259. TreeNodeRRset::getRRsig() const {
  260. isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
  261. }
  262. void
  263. TreeNodeRRset::addRRsig(const rdata::ConstRdataPtr&) {
  264. isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
  265. }
  266. void
  267. TreeNodeRRset::addRRsig(const rdata::RdataPtr&) {
  268. isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
  269. }
  270. void
  271. TreeNodeRRset::addRRsig(const AbstractRRset&) {
  272. isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
  273. }
  274. void
  275. TreeNodeRRset::addRRsig(const ConstRRsetPtr&) {
  276. isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
  277. }
  278. void
  279. TreeNodeRRset::addRRsig(const RRsetPtr&) {
  280. isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
  281. }
  282. void
  283. TreeNodeRRset::removeRRsig() {
  284. isc_throw(Unexpected, "unexpected method called on TreeNodeRRset");
  285. }
  286. bool
  287. TreeNodeRRset::isSameKind(const AbstractRRset& abs_other) const {
  288. const TreeNodeRRset* other =
  289. dynamic_cast<const TreeNodeRRset*>(&abs_other);
  290. if (other != NULL) {
  291. // If type is different, they are not the same kind
  292. if (rdataset_ != other->rdataset_) {
  293. return (false);
  294. }
  295. // Same for the owner name (note: in practice this method would be
  296. // called for rrsets at different nodes, so we check that condition
  297. // first). Note also that based on the basic assumption of the
  298. // ZoneTree, if the nodes are different their RR classes must be
  299. // different.
  300. if (node_ != other->node_ || !hasSameRealName(*other)) {
  301. return (false);
  302. }
  303. return (true);
  304. }
  305. return (AbstractRRset::isSameKind(abs_other));
  306. }
  307. bool
  308. TreeNodeRRset::hasSameRealName(const TreeNodeRRset& other) const {
  309. // If one is constructed with a "real name" and the other isn't
  310. // *we consider* them different.
  311. if ((realname_buf_ == NULL && other.realname_buf_ != NULL) ||
  312. (realname_buf_ != NULL && other.realname_buf_ == NULL)) {
  313. return (false);
  314. }
  315. // If both are constructed with a "real name", we compare their names
  316. // (as label sequences) explicitly.
  317. if (realname_buf_ != NULL && other.realname_buf_ != NULL) {
  318. uint8_t labels_buf[LabelSequence::MAX_SERIALIZED_LENGTH];
  319. uint8_t other_labels_buf[LabelSequence::MAX_SERIALIZED_LENGTH];
  320. if (!getOwnerLabels(labels_buf).equals(
  321. other.getOwnerLabels(other_labels_buf))) {
  322. return (false);
  323. }
  324. }
  325. return (true);
  326. }
  327. } // namespace memory
  328. } // namespace datasrc
  329. } // datasrc isc