treenode_rrset.cc 11 KB

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