edns.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // Copyright (C) 2010 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. // $Id$
  15. #include <config.h>
  16. #include <stdint.h>
  17. #include <cassert>
  18. #include <boost/lexical_cast.hpp>
  19. #include <exceptions/exceptions.h>
  20. #include <dns/edns.h>
  21. #include <dns/exceptions.h>
  22. #include <dns/message.h>
  23. #include <dns/messagerenderer.h>
  24. #include <dns/name.h>
  25. #include <dns/rdata.h>
  26. #include <dns/rdataclass.h>
  27. #include <dns/rrclass.h>
  28. #include <dns/rrttl.h>
  29. #include <dns/rrtype.h>
  30. using namespace std;
  31. using namespace boost;
  32. using namespace isc::dns::rdata;
  33. namespace isc {
  34. namespace dns {
  35. namespace {
  36. // This diagram shows the wire-format representation of the TTL field of
  37. // OPT RR and its relationship with implementation specific parameters.
  38. //
  39. // 0 7 15 31
  40. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  41. // | EXTENDED-RCODE| VERSION |D| Z |
  42. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  43. // <= VERSION_SHIFT (16 bits)
  44. // <= EXTRCODE_SHIFT (24 bits)
  45. //EXTFLAG_DO:0 0 0 ....................... 0 1 0 0 0 0.....................0
  46. //VER_MASK: 0 0 0 ........0 1 1 1 1 1 1 1 1 0 0 ..........................0
  47. const unsigned int VERSION_SHIFT = 16;
  48. const unsigned int EXTRCODE_SHIFT = 24;
  49. const uint32_t VERSION_MASK = 0x00ff0000;
  50. const uint32_t EXTFLAG_DO = 0x00008000;
  51. }
  52. EDNS::EDNS(const uint8_t version) :
  53. version_(version),
  54. udp_size_(Message::DEFAULT_MAX_UDPSIZE),
  55. dnssec_aware_(false)
  56. {
  57. if (version_ > SUPPORTED_VERSION) {
  58. isc_throw(isc::InvalidParameter,
  59. "failed to construct EDNS: unsupported version: " <<
  60. static_cast<unsigned int>(version_));
  61. }
  62. }
  63. EDNS::EDNS(const Name& name, const RRClass& rrclass, const RRType& rrtype,
  64. const RRTTL& ttl, const Rdata& rdata UNUSED_PARAM) :
  65. version_((ttl.getValue() & VERSION_MASK) >> VERSION_SHIFT)
  66. {
  67. if (rrtype != RRType::OPT()) {
  68. isc_throw(isc::InvalidParameter,
  69. "EDNS is being created with incompatible RR type: "
  70. << rrtype);
  71. }
  72. if (version_ > EDNS::SUPPORTED_VERSION) {
  73. isc_throw(DNSMessageBADVERS, "unsupported EDNS version: " <<
  74. static_cast<unsigned int>(version_));
  75. }
  76. if (name != Name::ROOT_NAME()) {
  77. isc_throw(DNSMessageFORMERR, "invalid owner name for EDNS OPT RR: " <<
  78. name);
  79. }
  80. dnssec_aware_ = ((ttl.getValue() & EXTFLAG_DO) != 0);
  81. udp_size_ = rrclass.getCode();
  82. }
  83. string
  84. EDNS::toText() const {
  85. string ret = "; EDNS: version: ";
  86. ret += lexical_cast<string>(static_cast<int>(getVersion()));
  87. ret += ", flags:";
  88. if (getDNSSECAwareness()) {
  89. ret += " do";
  90. }
  91. ret += "; udp: " + lexical_cast<string>(getUDPSize()) + "\n";
  92. return (ret);
  93. }
  94. template <typename Output>
  95. int
  96. EDNS::toWire(Output& output, const uint8_t extended_rcode) const {
  97. // Render EDNS OPT RR
  98. uint32_t extrcode_flags = extended_rcode << EXTRCODE_SHIFT;
  99. extrcode_flags |= (version_ << VERSION_SHIFT) & VERSION_MASK;
  100. if (dnssec_aware_) {
  101. extrcode_flags |= EXTFLAG_DO;
  102. }
  103. // Construct an RRset corresponding to the EDNS.
  104. // We don't support any options for now, so the OPT RR can be empty.
  105. RRsetPtr edns_rrset(new RRset(Name::ROOT_NAME(), RRClass(udp_size_),
  106. RRType::OPT(), RRTTL(extrcode_flags)));
  107. edns_rrset->addRdata(ConstRdataPtr(new generic::OPT()));
  108. edns_rrset->toWire(output);
  109. return (1);
  110. }
  111. unsigned int
  112. EDNS::toWire(MessageRenderer& renderer, const uint8_t extended_rcode) const {
  113. // If adding the OPT RR would exceed the size limit, don't do it.
  114. // 11 = len(".") + type(2byte) + class(2byte) + TTL(4byte) + RDLEN(2byte)
  115. // (RDATA is empty in this simple implementation)
  116. if (renderer.getLength() + 11 > renderer.getLengthLimit()) {
  117. return (0);
  118. }
  119. return (toWire<MessageRenderer>(renderer, extended_rcode));
  120. }
  121. unsigned int
  122. EDNS::toWire(OutputBuffer& buffer, const uint8_t extended_rcode) const {
  123. return (toWire<OutputBuffer>(buffer, extended_rcode));
  124. }
  125. EDNS*
  126. createEDNSFromRR(const Name& name, const RRClass& rrclass,
  127. const RRType& rrtype, const RRTTL& ttl,
  128. const Rdata& rdata UNUSED_PARAM,
  129. uint8_t& extended_rcode)
  130. {
  131. // Create a new EDNS object first for exception guarantee.
  132. EDNS* edns = new EDNS(name, rrclass, rrtype, ttl, rdata);
  133. // At this point we can update extended_rcode safely.
  134. extended_rcode = ttl.getValue() >> EXTRCODE_SHIFT;
  135. return (edns);
  136. }
  137. ostream&
  138. operator<<(std::ostream& os, const EDNS& edns) {
  139. os << edns.toText();
  140. return (os);
  141. }
  142. } // end of namespace dns
  143. } // end of namespace isc