rdata_encoder.cc 23 KB

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