treenode_rrset.cc 11 KB

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