tsigrecord.cc 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Copyright (C) 2011 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 <ostream>
  15. #include <string>
  16. #include <util/buffer.h>
  17. #include <dns/exceptions.h>
  18. #include <dns/messagerenderer.h>
  19. #include <dns/rrclass.h>
  20. #include <dns/rrttl.h>
  21. #include <dns/tsigrecord.h>
  22. using namespace isc::util;
  23. using namespace isc::dns::rdata;
  24. namespace {
  25. // Internally used constants:
  26. // Size in octets for the RR type, class TTL, RDLEN fields.
  27. const size_t RR_COMMON_LEN = 10;
  28. // Size in octets for the fixed part of TSIG RDATAs.
  29. // - Time Signed (6)
  30. // - Fudge (2)
  31. // - MAC Size (2)
  32. // - Original ID (2)
  33. // - Error (2)
  34. // - Other Len (2)
  35. const size_t RDATA_COMMON_LEN = 16;
  36. }
  37. namespace isc {
  38. namespace dns {
  39. TSIGRecord::TSIGRecord(const Name& key_name,
  40. const rdata::any::TSIG& tsig_rdata) :
  41. key_name_(key_name), rdata_(tsig_rdata),
  42. length_(RR_COMMON_LEN + RDATA_COMMON_LEN + key_name_.getLength() +
  43. rdata_.getAlgorithm().getLength() +
  44. rdata_.getMACSize() + rdata_.getOtherLen())
  45. {}
  46. namespace {
  47. // This is a straightforward wrapper of dynamic_cast<const any::TSIG&>.
  48. // We use this so that we can throw the DNSMessageFORMERR exception when
  49. // unexpected type of RDATA is detected in the member initialization list
  50. // of the constructor below.
  51. const any::TSIG&
  52. castToTSIGRdata(const rdata::Rdata& rdata) {
  53. try {
  54. return (dynamic_cast<const any::TSIG&>(rdata));
  55. } catch (std::bad_cast&) {
  56. isc_throw(DNSMessageFORMERR,
  57. "TSIG record is being constructed from "
  58. "incompatible RDATA:" << rdata.toText());
  59. }
  60. }
  61. }
  62. TSIGRecord::TSIGRecord(const Name& name, const RRClass& rrclass,
  63. const RRTTL& ttl, const rdata::Rdata& rdata,
  64. size_t length) :
  65. key_name_(name), rdata_(castToTSIGRdata(rdata)), length_(length)
  66. {
  67. if (rrclass != getClass()) {
  68. isc_throw(DNSMessageFORMERR, "Unexpected TSIG RR class: " << rrclass);
  69. }
  70. if (ttl != RRTTL(TSIG_TTL)) {
  71. isc_throw(DNSMessageFORMERR, "Unexpected TSIG TTL: " << ttl);
  72. }
  73. }
  74. const RRClass&
  75. TSIGRecord::getClass() {
  76. return (RRClass::ANY());
  77. }
  78. const RRTTL&
  79. TSIGRecord::getTTL() {
  80. static RRTTL ttl(TSIG_TTL);
  81. return (ttl);
  82. }
  83. namespace {
  84. template <typename OUTPUT>
  85. void
  86. toWireCommon(OUTPUT& output, const rdata::any::TSIG& rdata) {
  87. // RR type, class, TTL are fixed constants.
  88. RRType::TSIG().toWire(output);
  89. TSIGRecord::getClass().toWire(output);
  90. output.writeUint32(TSIGRecord::TSIG_TTL);
  91. // RDLEN
  92. output.writeUint16(RDATA_COMMON_LEN + rdata.getAlgorithm().getLength() +
  93. rdata.getMACSize() + rdata.getOtherLen());
  94. // TSIG RDATA
  95. rdata.toWire(output);
  96. }
  97. }
  98. int
  99. TSIGRecord::toWire(AbstractMessageRenderer& renderer) const {
  100. // If adding the TSIG would exceed the size limit, don't do it.
  101. if (renderer.getLength() + length_ > renderer.getLengthLimit()) {
  102. renderer.setTruncated();
  103. return (0);
  104. }
  105. // key name = owner. note that we disable compression.
  106. renderer.writeName(key_name_, false);
  107. toWireCommon(renderer, rdata_);
  108. return (1);
  109. }
  110. int
  111. TSIGRecord::toWire(OutputBuffer& buffer) const {
  112. key_name_.toWire(buffer);
  113. toWireCommon(buffer, rdata_);
  114. return (1);
  115. }
  116. std::string
  117. TSIGRecord::toText() const {
  118. return (key_name_.toText() + " " + RRTTL(TSIG_TTL).toText() + " " +
  119. getClass().toText() + " " + RRType::TSIG().toText() + " " +
  120. rdata_.toText() + "\n");
  121. }
  122. std::ostream&
  123. operator<<(std::ostream& os, const TSIGRecord& record) {
  124. return (os << record.toText());
  125. }
  126. } // namespace dns
  127. } // namespace isc