opt_41.cc 6.0 KB

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