rdata_serialization.cc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  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 "rdata_serialization.h"
  15. #include <exceptions/exceptions.h>
  16. #include <util/buffer.h>
  17. #include <dns/name.h>
  18. #include <dns/labelsequence.h>
  19. #include <dns/messagerenderer.h>
  20. #include <dns/rdata.h>
  21. #include <dns/rrclass.h>
  22. #include <dns/rrtype.h>
  23. #include <cassert>
  24. #include <cstring>
  25. #include <vector>
  26. #include <boost/static_assert.hpp>
  27. using namespace isc::dns;
  28. using std::vector;
  29. namespace isc {
  30. namespace datasrc {
  31. namespace memory {
  32. #include "rdata_serialization_priv.cc"
  33. namespace {
  34. // Many types of RDATA can be treated as a single-field, variable length
  35. // field (in terms of our encoding). The following define such most general
  36. // form of field spec.
  37. const RdataFieldSpec generic_data_fields[] = {
  38. {RdataFieldSpec::VARLEN_DATA, 0, NAMEATTR_NONE}
  39. };
  40. const uint16_t n_generic_data_fields =
  41. sizeof(generic_data_fields) / sizeof(RdataFieldSpec);
  42. const RdataEncodeSpec generic_data_spec = {
  43. n_generic_data_fields, 0, 1, generic_data_fields
  44. };
  45. // RDATA consist of a single IPv4 address field.
  46. const RdataFieldSpec single_ipv4_fields[] = {
  47. {RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint32_t), NAMEATTR_NONE}
  48. };
  49. const uint16_t n_ipv4_fields =
  50. sizeof(single_ipv4_fields) / sizeof(RdataFieldSpec);
  51. // RDATA consist of a single IPv6 address field.
  52. const RdataFieldSpec single_ipv6_fields[] = {
  53. {RdataFieldSpec::FIXEDLEN_DATA, 16, NAMEATTR_NONE} // 128bits = 16 bytes
  54. };
  55. const uint16_t n_ipv6_fields =
  56. sizeof(single_ipv6_fields) / sizeof(RdataFieldSpec);
  57. // There are several RR types that consist of a single domain name.
  58. const RdataFieldSpec single_noattr_name_fields[] = {
  59. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE}
  60. };
  61. const RdataFieldSpec single_compressible_name_fields[] = {
  62. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE}
  63. };
  64. const RdataFieldSpec single_compadditional_name_fields[] = {
  65. {RdataFieldSpec::DOMAIN_NAME, 0,
  66. static_cast<RdataNameAttributes>(
  67. static_cast<unsigned int>(NAMEATTR_COMPRESSIBLE) |
  68. static_cast<unsigned int>(NAMEATTR_ADDITIONAL))}
  69. };
  70. const uint16_t n_single_name_fields =
  71. sizeof(single_noattr_name_fields) / sizeof(RdataFieldSpec);
  72. // RDATA consisting of two names. There are some of this type.
  73. const RdataFieldSpec double_compressible_name_fields[] = {
  74. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE},
  75. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE}
  76. };
  77. const RdataFieldSpec double_noattr_name_fields[] = {
  78. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE},
  79. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE}
  80. };
  81. const uint16_t n_double_name_fields =
  82. sizeof(double_compressible_name_fields) / sizeof(RdataFieldSpec);
  83. // SOA specific: two compressible names + 5*32-bit data
  84. const RdataFieldSpec soa_fields[] = {
  85. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE},
  86. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE},
  87. {RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint32_t) * 5, NAMEATTR_NONE}
  88. };
  89. const uint16_t n_soa_fields = sizeof(soa_fields) / sizeof(RdataFieldSpec);
  90. // MX specific: 16-bit data + compressible/additional name
  91. const RdataFieldSpec mx_fields[] = {
  92. {RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint16_t), NAMEATTR_NONE},
  93. {RdataFieldSpec::DOMAIN_NAME, 0,
  94. static_cast<RdataNameAttributes>(
  95. static_cast<unsigned int>(NAMEATTR_COMPRESSIBLE) |
  96. static_cast<unsigned int>(NAMEATTR_ADDITIONAL))}
  97. };
  98. const uint16_t n_mx_fields = sizeof(mx_fields) / sizeof(RdataFieldSpec);
  99. // AFSDB specific: 16-bit data + no-attribute name
  100. const RdataFieldSpec afsdb_fields[] = {
  101. {RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint16_t), NAMEATTR_NONE},
  102. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE}
  103. };
  104. const uint16_t n_afsdb_fields = sizeof(afsdb_fields) / sizeof(RdataFieldSpec);
  105. // SRV specific: 3*16-bit data + additional name
  106. const RdataFieldSpec srv_fields[] = {
  107. {RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint16_t) * 3, NAMEATTR_NONE},
  108. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_ADDITIONAL}
  109. };
  110. const uint16_t n_srv_fields = sizeof(srv_fields) / sizeof(RdataFieldSpec);
  111. // NAPTR specific: (multi-field) variable data + (additional) name
  112. // NAPTR requires complicated additional section handling; for now, we skip
  113. // the additional handling completely.
  114. const RdataFieldSpec naptr_fields[] = {
  115. {RdataFieldSpec::VARLEN_DATA, 0, NAMEATTR_NONE},
  116. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE}
  117. };
  118. const uint16_t n_naptr_fields = sizeof(naptr_fields) / sizeof(RdataFieldSpec);
  119. // NSEC specific: no-attribute name + varlen data
  120. const RdataFieldSpec nsec_fields[] = {
  121. {RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE},
  122. {RdataFieldSpec::VARLEN_DATA, 0, NAMEATTR_NONE}
  123. };
  124. const uint16_t n_nsec_fields = sizeof(nsec_fields) / sizeof(RdataFieldSpec);
  125. // Class IN encode specs. This gives a shortcut to the encode spec for
  126. // some well-known types of RDATA specific to class IN (most of which are
  127. // generic and can be used for other classes). The array index is the
  128. // RR type code.
  129. const RdataEncodeSpec encode_spec_list_in[] = {
  130. generic_data_spec, // #0: (NONE)
  131. {n_ipv4_fields, 0, 0, single_ipv4_fields}, // #1: A
  132. {n_single_name_fields, 1, 0, single_compadditional_name_fields}, // #2: NS
  133. generic_data_spec, // #3
  134. generic_data_spec, // #4
  135. {n_single_name_fields, 1, 0, single_compressible_name_fields}, // #5: CNAME
  136. {n_soa_fields, 2, 0, soa_fields}, // #6: SOA
  137. generic_data_spec, // #7
  138. generic_data_spec, // #8
  139. generic_data_spec, // #9
  140. generic_data_spec, // #10
  141. generic_data_spec, // #11
  142. {n_single_name_fields, 1, 0, single_compressible_name_fields}, // #12: PTR
  143. generic_data_spec, // #13: HINFO
  144. {n_double_name_fields, 2, 0, double_compressible_name_fields}, // #14:HINFO
  145. {n_mx_fields, 1, 0, mx_fields}, // #15: MX
  146. generic_data_spec, // #16: TXT
  147. {n_double_name_fields, 2, 0, double_noattr_name_fields}, // 17: RP
  148. {n_afsdb_fields, 1, 0, afsdb_fields}, // #18: AFSDB
  149. // #19-#26
  150. generic_data_spec, generic_data_spec, generic_data_spec, generic_data_spec,
  151. generic_data_spec, generic_data_spec, generic_data_spec, generic_data_spec,
  152. generic_data_spec, // #27
  153. {n_ipv6_fields, 0, 0, single_ipv6_fields}, // #28: AAAA
  154. // #29-#32
  155. generic_data_spec, generic_data_spec, generic_data_spec, generic_data_spec,
  156. {n_srv_fields, 1, 0, srv_fields}, // #33: SRV
  157. generic_data_spec, // #34
  158. {n_naptr_fields, 1, 1, naptr_fields}, // #35: NAPTR
  159. generic_data_spec, // #36
  160. generic_data_spec, // #37
  161. generic_data_spec, // #38
  162. {n_single_name_fields, 1, 0, single_noattr_name_fields}, // #39 DNAME
  163. generic_data_spec, // #40
  164. generic_data_spec, // #41 (OPT)
  165. generic_data_spec, // #42
  166. generic_data_spec, // #43: DS (this is opaque for encoding purposes)
  167. generic_data_spec, // #44: SSHFP (this is opaque for encoding purposes)
  168. generic_data_spec, // #45
  169. generic_data_spec, // #46: RRSIG (this is opaque for encoding purposes)
  170. {n_nsec_fields, 1, 1, nsec_fields} // #47: NSEC
  171. // All others can be treated as single-field variable length data, at
  172. // least for currently supported RR types.
  173. };
  174. // # of entries in encode_spec_list_in
  175. const size_t encode_spec_list_in_size =
  176. sizeof(encode_spec_list_in) / sizeof(encode_spec_list_in[0]);
  177. BOOST_STATIC_ASSERT(encode_spec_list_in_size == 48);
  178. }
  179. /// \brief Get the spec for given class and type
  180. const RdataEncodeSpec&
  181. getRdataEncodeSpec(const RRClass& rrclass, const RRType& rrtype) {
  182. // Special case: for classes other than IN, we treat RDATA of RR types
  183. // that are class-IN specific as generic opaque data.
  184. if (rrclass != RRClass::IN() &&
  185. (rrtype == RRType::A() || rrtype == RRType::AAAA() ||
  186. rrtype == RRType::SRV())) {
  187. return (generic_data_spec);
  188. }
  189. // Otherwise, if the type is in the pre-defined range, we use the defined
  190. // spec; otherwise we treat it as opaque data.
  191. const uint16_t typecode = rrtype.getCode();
  192. if (typecode < encode_spec_list_in_size) {
  193. return (encode_spec_list_in[rrtype.getCode()]);
  194. }
  195. return (generic_data_spec);
  196. }
  197. namespace {
  198. // This class is a helper for RdataEncoder to divide the content of RDATA
  199. // fields for encoding by "abusing" the message rendering logic.
  200. // The idea is to identify domain name fields in the writeName() method,
  201. // while keeping track of the size and position of other types of data
  202. // around the names.
  203. //
  204. // Technically, this use of inheritance may be considered a violation of
  205. // Liskov Substitution Principle in that it doesn't actually compress domain
  206. // names, and some of the methods are not expected to be used.
  207. // In fact, skip() or trim() may not be make much sense in this context.
  208. // Nevertheless we keep this idea at the moment. Since the usage is limited
  209. // (it's only used within this file, and only used with \c Rdata variants),
  210. // it's hopefully an acceptable practice.
  211. class RdataFieldComposer : public AbstractMessageRenderer {
  212. public:
  213. RdataFieldComposer() : last_data_pos_(0), encode_spec_(NULL),
  214. current_field_(0)
  215. {}
  216. virtual ~RdataFieldComposer() {}
  217. virtual bool isTruncated() const { return (false); }
  218. virtual size_t getLengthLimit() const { return (65535); }
  219. virtual CompressMode getCompressMode() const { return (CASE_INSENSITIVE); }
  220. virtual void setTruncated() {}
  221. virtual void setLengthLimit(size_t) {}
  222. virtual void setCompressMode(CompressMode) {}
  223. virtual void writeName(const LabelSequence&, bool) {
  224. // We don't need this version of writeName
  225. isc_throw(Unexpected, "unexpected version of writeName is called");
  226. }
  227. // Called for each domain name in the RDATA, from the RDATA's toWire()
  228. // implementation.
  229. virtual void writeName(const Name& name, bool compress) {
  230. // First, see if we have other data already stored in the renderer's
  231. // buffer, and handle it appropriately.
  232. updateOtherData();
  233. // Then, we should still have a field in the spec, and it must be a
  234. // domain name field.
  235. if (current_field_ >= encode_spec_->field_count) {
  236. isc_throw(BadValue,
  237. "RDATA encoder encounters an unexpected name data: " <<
  238. name);
  239. }
  240. const RdataFieldSpec& field =
  241. encode_spec_->fields[current_field_++];
  242. // Since we know we've passed any prior data field, the next field
  243. // must be a domain name as long as it exists; otherwise it's a bug
  244. // in the spec (not a bogus input). So we assert() that condition.
  245. assert(field.type == RdataFieldSpec::DOMAIN_NAME);
  246. // It would be compressed iff the field has that attribute.
  247. if (compress !=
  248. ((field.name_attributes & NAMEATTR_COMPRESSIBLE) != 0)) {
  249. isc_throw(BadValue, "RDATA encoder error, inconsistent name "
  250. "compression policy: " << name);
  251. }
  252. const LabelSequence labels(name);
  253. labels.serialize(labels_placeholder_, sizeof(labels_placeholder_));
  254. writeData(labels_placeholder_, labels.getSerializedLength());
  255. last_data_pos_ += labels.getSerializedLength();
  256. }
  257. // Clear all internal states and resources for a new set of RDATA.
  258. void clearLocal(const RdataEncodeSpec* encode_spec) {
  259. AbstractMessageRenderer::clear();
  260. encode_spec_ = encode_spec;
  261. data_lengths_.clear();
  262. last_data_pos_ = 0;
  263. }
  264. // Called at the beginning of an RDATA.
  265. void startRdata() {
  266. current_field_ = 0;
  267. }
  268. // Called at the end of an RDATA.
  269. void endRdata() {
  270. // Handle any remaining data (there should be no more name). Then
  271. // we should reach the end of the fields.
  272. updateOtherData();
  273. if (current_field_ != encode_spec_->field_count) {
  274. isc_throw(BadValue,
  275. "RDATA encoder didn't find all expected fields");
  276. }
  277. }
  278. // Hold the lengths of variable length fields, in the order of their
  279. // appearance. For convenience, allow the encoder to refer to it
  280. // directly.
  281. vector<uint16_t> data_lengths_;
  282. private:
  283. // We use generict write* methods, with the exception of writeName.
  284. // So new data can arrive without us knowing it, this considers all new
  285. // data to be just data, checking consistency with the field spec, and
  286. // if it contains variable-length field, record its length.
  287. size_t last_data_pos_;
  288. void updateOtherData() {
  289. // If we've reached the end of the fields or we are expecting a
  290. // domain name, there's nothing to do here.
  291. if (current_field_ >= encode_spec_->field_count ||
  292. encode_spec_->fields[current_field_].type ==
  293. RdataFieldSpec::DOMAIN_NAME) {
  294. return;
  295. }
  296. const size_t cur_pos = getLength();
  297. const size_t data_len = cur_pos - last_data_pos_;
  298. const RdataFieldSpec& field = encode_spec_->fields[current_field_];
  299. if (field.type == RdataFieldSpec::FIXEDLEN_DATA) {
  300. // The data length of a fixed length field must be the one
  301. // specified in the field spec.
  302. if (data_len != field.fixeddata_len) {
  303. isc_throw(BadValue,
  304. "RDATA encoding: available data too short for the "
  305. "type");
  306. }
  307. } else {
  308. // For encoding purposes, a variable-length data field is
  309. // a single field covering all data, even if it may
  310. // consist of multiple fields as DNS RDATA (e.g. TXT).
  311. if (data_len > 0xffff) {
  312. isc_throw(RdataEncodingError, "RDATA field is too large: "
  313. << data_len << " bytes");
  314. }
  315. data_lengths_.push_back(data_len);
  316. }
  317. ++current_field_;
  318. last_data_pos_ = cur_pos;
  319. }
  320. // The RDATA field spec of the current session. Set at the beginning of
  321. // each session.
  322. const RdataEncodeSpec* encode_spec_;
  323. // the RDATA field (for encoding) currently handled. Reset to 0 for
  324. // each RDATA of the session.
  325. size_t current_field_;
  326. // Placeholder to convert a name object to a label sequence.
  327. uint8_t labels_placeholder_[LabelSequence::MAX_SERIALIZED_LENGTH];
  328. };
  329. } // end of unnamed namespace
  330. struct RdataEncoder::RdataEncoderImpl {
  331. RdataEncoderImpl() : encode_spec_(NULL), rrsig_buffer_(0),
  332. rdata_count_(0)
  333. {}
  334. const RdataEncodeSpec* encode_spec_; // encode spec of current RDATA set
  335. RdataFieldComposer field_composer_;
  336. util::OutputBuffer rrsig_buffer_;
  337. size_t rdata_count_;
  338. vector<uint16_t> rrsig_lengths_;
  339. };
  340. RdataEncoder::RdataEncoder() :
  341. impl_(new RdataEncoderImpl)
  342. {}
  343. RdataEncoder::~RdataEncoder() {
  344. delete impl_;
  345. }
  346. void
  347. RdataEncoder::start(RRClass rrclass, RRType rrtype) {
  348. if (rrtype == RRType::RRSIG()) {
  349. isc_throw(BadValue, "RRSIG cannot be encoded as main RDATA type");
  350. }
  351. impl_->encode_spec_ = &getRdataEncodeSpec(rrclass, rrtype);
  352. impl_->field_composer_.clearLocal(impl_->encode_spec_);
  353. impl_->rrsig_buffer_.clear();
  354. impl_->rdata_count_ = 0;
  355. impl_->rrsig_lengths_.clear();
  356. }
  357. void
  358. RdataEncoder::addRdata(const rdata::Rdata& rdata) {
  359. if (impl_->encode_spec_ == NULL) {
  360. isc_throw(InvalidOperation,
  361. "RdataEncoder::addRdata performed before start");
  362. }
  363. impl_->field_composer_.startRdata();
  364. rdata.toWire(impl_->field_composer_);
  365. impl_->field_composer_.endRdata();
  366. ++impl_->rdata_count_;
  367. }
  368. void
  369. RdataEncoder::addSIGRdata(const rdata::Rdata& sig_rdata) {
  370. if (impl_->encode_spec_ == NULL) {
  371. isc_throw(InvalidOperation,
  372. "RdataEncoder::addSIGRdata performed before start");
  373. }
  374. const size_t cur_pos = impl_->rrsig_buffer_.getLength();
  375. sig_rdata.toWire(impl_->rrsig_buffer_);
  376. const size_t rrsig_datalen = impl_->rrsig_buffer_.getLength() - cur_pos;
  377. if (rrsig_datalen > 0xffff) {
  378. isc_throw(RdataEncodingError, "RRSIG is too large: "
  379. << rrsig_datalen << " bytes");
  380. }
  381. impl_->rrsig_lengths_.push_back(rrsig_datalen);
  382. }
  383. size_t
  384. RdataEncoder::getStorageLength() const {
  385. if (impl_->encode_spec_ == NULL) {
  386. isc_throw(InvalidOperation,
  387. "RdataEncoder::getStorageLength performed before start");
  388. }
  389. return (sizeof(uint16_t) * impl_->field_composer_.data_lengths_.size() +
  390. sizeof(uint16_t) * impl_->rrsig_lengths_.size() +
  391. impl_->rrsig_buffer_.getLength() +
  392. impl_->field_composer_.getLength());
  393. }
  394. void
  395. RdataEncoder::encode(void* buf, size_t buf_len) const {
  396. if (impl_->encode_spec_ == NULL) {
  397. isc_throw(InvalidOperation,
  398. "RdataEncoder::encode performed before start");
  399. }
  400. if (buf == NULL) {
  401. isc_throw(BadValue,
  402. "RdataEncoder::encode NULL buffer is given");
  403. }
  404. if (getStorageLength() > buf_len) {
  405. isc_throw(BadValue, "RdataEncoder::encode short buffer given");
  406. }
  407. uint8_t* const dp_beg = reinterpret_cast<uint8_t*>(buf);
  408. uint8_t* dp = dp_beg;
  409. uint16_t* lenp = reinterpret_cast<uint16_t*>(buf);
  410. // Encode list of lengths for variable length fields (if any)
  411. if (!impl_->field_composer_.data_lengths_.empty()) {
  412. const size_t varlen_fields_len =
  413. impl_->field_composer_.data_lengths_.size() * sizeof(uint16_t);
  414. std::memcpy(lenp, &impl_->field_composer_.data_lengths_[0],
  415. varlen_fields_len);
  416. lenp += impl_->field_composer_.data_lengths_.size();
  417. dp += varlen_fields_len;
  418. }
  419. // Encode list of lengths for RRSIGs (if any)
  420. if (!impl_->rrsig_lengths_.empty()) {
  421. const size_t rrsigs_len =
  422. impl_->rrsig_lengths_.size() * sizeof(uint16_t);
  423. std::memcpy(lenp, &impl_->rrsig_lengths_[0], rrsigs_len);
  424. dp += rrsigs_len;
  425. }
  426. // Encode main RDATA
  427. std::memcpy(dp, impl_->field_composer_.getData(),
  428. impl_->field_composer_.getLength());
  429. dp += impl_->field_composer_.getLength();
  430. // Encode RRSIGs, if any
  431. std::memcpy(dp, impl_->rrsig_buffer_.getData(),
  432. impl_->rrsig_buffer_.getLength());
  433. dp += impl_->rrsig_buffer_.getLength();
  434. // The validation at the entrance must ensure this
  435. assert(buf_len >= dp - dp_beg);
  436. }
  437. RdataReader::RdataReader(const RRClass& rrclass, const RRType& rrtype,
  438. const void* data,
  439. size_t rdata_count, size_t sig_count,
  440. const NameAction& name_action,
  441. const DataAction& data_action) :
  442. name_action_(name_action),
  443. data_action_(data_action),
  444. spec_(getRdataEncodeSpec(rrclass, rrtype)),
  445. var_count_total_(spec_.varlen_count * rdata_count),
  446. sig_count_(sig_count),
  447. spec_count_(spec_.field_count * rdata_count),
  448. // The lenghts are stored first
  449. lengths_(reinterpret_cast<const uint16_t*>(data)),
  450. // And the data just after all the lengths
  451. data_(reinterpret_cast<const uint8_t*>(data) +
  452. (var_count_total_ + sig_count_) * sizeof(uint16_t)),
  453. sigs_(NULL)
  454. {
  455. rewind();
  456. }
  457. void
  458. RdataReader::rewind() {
  459. data_pos_ = 0;
  460. spec_pos_ = 0;
  461. length_pos_ = 0;
  462. sig_data_pos_ = 0;
  463. sig_pos_ = 0;
  464. }
  465. RdataReader::Boundary
  466. RdataReader::nextInternal(const NameAction& name_action,
  467. const DataAction& data_action)
  468. {
  469. if (spec_pos_ < spec_count_) {
  470. const RdataFieldSpec& spec(spec_.fields[(spec_pos_++) %
  471. spec_.field_count]);
  472. if (spec.type == RdataFieldSpec::DOMAIN_NAME) {
  473. const LabelSequence sequence(data_ + data_pos_);
  474. data_pos_ += sequence.getSerializedLength();
  475. name_action(sequence, spec.name_attributes);
  476. } else {
  477. const size_t length(spec.type == RdataFieldSpec::FIXEDLEN_DATA ?
  478. spec.fixeddata_len : lengths_[length_pos_++]);
  479. const uint8_t* const pos = data_ + data_pos_;
  480. data_pos_ += length;
  481. data_action(pos, length);
  482. }
  483. return (spec_pos_ % spec_.field_count == 0 ?
  484. RDATA_BOUNDARY : NO_BOUNDARY);
  485. } else {
  486. sigs_ = data_ + data_pos_;
  487. return (RRSET_BOUNDARY);
  488. }
  489. }
  490. RdataReader::Boundary
  491. RdataReader::next() {
  492. return (nextInternal(name_action_, data_action_));
  493. }
  494. void
  495. RdataReader::emptyNameAction(const LabelSequence&, RdataNameAttributes) {
  496. // Do nothing here.
  497. }
  498. void
  499. RdataReader::emptyDataAction(const void*, size_t) {
  500. // Do nothing here.
  501. }
  502. RdataReader::Boundary
  503. RdataReader::nextSig() {
  504. if (sig_pos_ < sig_count_) {
  505. if (sigs_ == NULL) {
  506. // We didn't find where the signatures start yet. We do it
  507. // by iterating the whole data and then returning the state
  508. // back.
  509. const size_t data_pos = data_pos_;
  510. const size_t spec_pos = spec_pos_;
  511. const size_t length_pos = length_pos_;
  512. // When the next() gets to the last item, it sets the sigs_
  513. while (nextInternal(emptyNameAction, emptyDataAction) !=
  514. RRSET_BOUNDARY) {}
  515. assert(sigs_ != NULL);
  516. // Return the state
  517. data_pos_ = data_pos;
  518. spec_pos_ = spec_pos;
  519. length_pos_ = length_pos;
  520. }
  521. // Extract the result
  522. const size_t length = lengths_[var_count_total_ + sig_pos_];
  523. const uint8_t* const pos = sigs_ + sig_data_pos_;
  524. // Move the position of iterator.
  525. sig_data_pos_ += lengths_[var_count_total_ + sig_pos_];
  526. ++sig_pos_;
  527. // Call the callback
  528. data_action_(pos, length);
  529. return (RDATA_BOUNDARY);
  530. } else {
  531. return (RRSET_BOUNDARY);
  532. }
  533. }
  534. size_t
  535. RdataReader::getSize() const {
  536. size_t storage_size = 0; // this will be the end result
  537. size_t data_pos = 0;
  538. size_t length_pos = 0;
  539. // Go over all data fields, adding their lengths to storage_size
  540. for (size_t spec_pos = 0; spec_pos < spec_count_; ++spec_pos) {
  541. const RdataFieldSpec& spec =
  542. spec_.fields[spec_pos % spec_.field_count];
  543. if (spec.type == RdataFieldSpec::DOMAIN_NAME) {
  544. const size_t seq_len =
  545. LabelSequence(data_ + data_pos).getSerializedLength();
  546. data_pos += seq_len;
  547. storage_size += seq_len;
  548. } else {
  549. const size_t data_len =
  550. (spec.type == RdataFieldSpec::FIXEDLEN_DATA ?
  551. spec.fixeddata_len : lengths_[length_pos++]);
  552. data_pos += data_len;
  553. storage_size += data_len;
  554. }
  555. }
  556. // Same for all RRSIG data
  557. for (size_t sig_pos = 0; sig_pos < sig_count_; ++sig_pos) {
  558. const size_t sig_data_len = lengths_[length_pos++];
  559. storage_size += sig_data_len;
  560. }
  561. // Finally, add the size for 16-bit length fields
  562. storage_size += (var_count_total_ * sizeof(uint16_t) +
  563. sig_count_ * sizeof(uint16_t));
  564. return (storage_size);
  565. }
  566. } // namespace memory
  567. } // namespace datasrc
  568. } // datasrc isc