opt_41.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. // Copyright (C) 2010-2016 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #include <config.h>
  7. #include <util/buffer.h>
  8. #include <dns/messagerenderer.h>
  9. #include <dns/rdata.h>
  10. #include <dns/rdataclass.h>
  11. #include <boost/foreach.hpp>
  12. #include <string>
  13. #include <string.h>
  14. using namespace std;
  15. using namespace isc::util;
  16. // BEGIN_ISC_NAMESPACE
  17. // BEGIN_RDATA_NAMESPACE
  18. /// \brief Constructor.
  19. OPT::PseudoRR::PseudoRR(uint16_t code,
  20. boost::shared_ptr<std::vector<uint8_t> >& data) :
  21. code_(code),
  22. data_(data)
  23. {
  24. }
  25. uint16_t
  26. OPT::PseudoRR::getCode() const {
  27. return (code_);
  28. }
  29. const uint8_t*
  30. OPT::PseudoRR::getData() const {
  31. return (&(*data_)[0]);
  32. }
  33. uint16_t
  34. OPT::PseudoRR::getLength() const {
  35. return (data_->size());
  36. }
  37. struct OPTImpl {
  38. OPTImpl() :
  39. rdlength_(0)
  40. {}
  41. uint16_t rdlength_;
  42. std::vector<OPT::PseudoRR> pseudo_rrs_;
  43. };
  44. /// \brief Default constructor.
  45. OPT::OPT() :
  46. impl_(new OPTImpl)
  47. {
  48. }
  49. /// \brief Constructor from string.
  50. ///
  51. /// This constructor cannot be used, and always throws an exception.
  52. ///
  53. /// \throw InvalidRdataText OPT RR cannot be constructed from text.
  54. OPT::OPT(const std::string&) :
  55. impl_(NULL)
  56. {
  57. isc_throw(InvalidRdataText, "OPT RR cannot be constructed from text");
  58. }
  59. /// \brief Constructor with a context of MasterLexer.
  60. ///
  61. /// This constructor cannot be used, and always throws an exception.
  62. ///
  63. /// \throw InvalidRdataText OPT RR cannot be constructed from text.
  64. OPT::OPT(MasterLexer&, const Name*,
  65. MasterLoader::Options, MasterLoaderCallbacks&) :
  66. impl_(NULL)
  67. {
  68. isc_throw(InvalidRdataText, "OPT RR cannot be constructed from text");
  69. }
  70. OPT::OPT(InputBuffer& buffer, size_t rdata_len) :
  71. impl_(NULL)
  72. {
  73. std::unique_ptr<OPTImpl> impl_ptr(new OPTImpl);
  74. while (true) {
  75. if (rdata_len == 0) {
  76. break;
  77. }
  78. if (rdata_len < 4) {
  79. isc_throw(InvalidRdataLength,
  80. "Pseudo OPT RR record too short: "
  81. << rdata_len << " bytes");
  82. }
  83. const uint16_t option_code = buffer.readUint16();
  84. const uint16_t option_length = buffer.readUint16();
  85. rdata_len -= 4;
  86. if (static_cast<uint16_t>(impl_ptr->rdlength_ + option_length) <
  87. impl_ptr->rdlength_)
  88. {
  89. isc_throw(InvalidRdataText,
  90. "Option length " << option_length
  91. << " would overflow OPT RR RDLEN (currently "
  92. << impl_ptr->rdlength_ << ").");
  93. }
  94. if (rdata_len < option_length) {
  95. isc_throw(InvalidRdataLength, "Corrupt pseudo OPT RR record");
  96. }
  97. boost::shared_ptr<std::vector<uint8_t> >
  98. option_data(new std::vector<uint8_t>(option_length));
  99. buffer.readData(&(*option_data)[0], option_length);
  100. impl_ptr->pseudo_rrs_.push_back(PseudoRR(option_code, option_data));
  101. impl_ptr->rdlength_ += option_length;
  102. rdata_len -= option_length;
  103. }
  104. impl_ = impl_ptr.release();
  105. }
  106. OPT::OPT(const OPT& other) :
  107. Rdata(), impl_(new OPTImpl(*other.impl_))
  108. {
  109. }
  110. OPT&
  111. OPT::operator=(const OPT& source) {
  112. if (this == &source) {
  113. return (*this);
  114. }
  115. OPTImpl* newimpl = new OPTImpl(*source.impl_);
  116. delete impl_;
  117. impl_ = newimpl;
  118. return (*this);
  119. }
  120. OPT::~OPT() {
  121. delete impl_;
  122. }
  123. std::string
  124. OPT::toText() const {
  125. isc_throw(isc::InvalidOperation,
  126. "OPT RRs do not have a presentation format");
  127. }
  128. void
  129. OPT::toWire(OutputBuffer& buffer) const {
  130. BOOST_FOREACH(const PseudoRR& pseudo_rr, impl_->pseudo_rrs_) {
  131. buffer.writeUint16(pseudo_rr.getCode());
  132. const uint16_t length = pseudo_rr.getLength();
  133. buffer.writeUint16(length);
  134. if (length > 0) {
  135. buffer.writeData(pseudo_rr.getData(), length);
  136. }
  137. }
  138. }
  139. void
  140. OPT::toWire(AbstractMessageRenderer& renderer) const {
  141. BOOST_FOREACH(const PseudoRR& pseudo_rr, impl_->pseudo_rrs_) {
  142. renderer.writeUint16(pseudo_rr.getCode());
  143. const uint16_t length = pseudo_rr.getLength();
  144. renderer.writeUint16(length);
  145. if (length > 0) {
  146. renderer.writeData(pseudo_rr.getData(), length);
  147. }
  148. }
  149. }
  150. int
  151. OPT::compare(const Rdata&) const {
  152. isc_throw(isc::InvalidOperation,
  153. "It is meaningless to compare a set of OPT pseudo RRs; "
  154. "they have unspecified order");
  155. return (0);
  156. }
  157. void
  158. OPT::appendPseudoRR(uint16_t code, const uint8_t* data, uint16_t length) {
  159. // See if it overflows 16-bit length field. We only worry about the
  160. // pseudo-RR length here, not the whole message length (which should
  161. // be checked and enforced elsewhere).
  162. if (static_cast<uint16_t>(impl_->rdlength_ + length) <
  163. impl_->rdlength_)
  164. {
  165. isc_throw(isc::InvalidParameter,
  166. "Option length " << length
  167. << " would overflow OPT RR RDLEN (currently "
  168. << impl_->rdlength_ << ").");
  169. }
  170. boost::shared_ptr<std::vector<uint8_t> >
  171. option_data(new std::vector<uint8_t>(length));
  172. if (length != 0) {
  173. std::memcpy(&(*option_data)[0], data, length);
  174. }
  175. impl_->pseudo_rrs_.push_back(PseudoRR(code, option_data));
  176. impl_->rdlength_ += length;
  177. }
  178. const std::vector<OPT::PseudoRR>&
  179. OPT::getPseudoRRs() const {
  180. return (impl_->pseudo_rrs_);
  181. }
  182. // END_RDATA_NAMESPACE
  183. // END_ISC_NAMESPACE