rdata_nsecbitmap_unittest.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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 <dns/tests/unittest_util.h>
  15. #include <dns/exceptions.h>
  16. #include <dns/rdata.h>
  17. #include <dns/rdataclass.h>
  18. #include <dns/rrclass.h>
  19. #include <dns/rrtype.h>
  20. #include <gtest/gtest.h>
  21. #include <dns/tests/rdata_unittest.h>
  22. #include <boost/lexical_cast.hpp>
  23. #include <string>
  24. #include <vector>
  25. using namespace std;
  26. using boost::lexical_cast;
  27. using isc::UnitTestUtil;
  28. using namespace isc::dns;
  29. using namespace isc::dns::rdata;
  30. namespace {
  31. // Template for shared tests for NSEC and NSEC3 bitmaps
  32. template <typename RDATA_TYPE>
  33. class NSECLikeBitmapTest : public RdataTest {
  34. protected:
  35. RDATA_TYPE fromText(const string& rdata_text) {
  36. return (RDATA_TYPE(rdata_text));
  37. }
  38. vector<RDATA_TYPE> compare_set; // used in compare() tests
  39. void compareCheck() const {
  40. typename vector<RDATA_TYPE>::const_iterator it;
  41. typename vector<RDATA_TYPE>::const_iterator const it_end =
  42. compare_set.end();
  43. for (it = compare_set.begin(); it != it_end - 1; ++it) {
  44. SCOPED_TRACE("compare " + it->toText() + " to " +
  45. (it + 1)->toText());
  46. EXPECT_GT(0, (*it).compare(*(it + 1)));
  47. EXPECT_LT(0, (*(it + 1)).compare(*it));
  48. }
  49. }
  50. // These depend on the specific RR type. We use specialized methods
  51. // for them.
  52. static RRType getType(); // return either RRType::NSEC() or NSEC3()
  53. static string getWireFilePrefix();
  54. static string getCommonText(); // commonly used part of textual form
  55. };
  56. // Instantiate specific typed tests
  57. typedef ::testing::Types<generic::NSEC, generic::NSEC3> TestRdataTypes;
  58. TYPED_TEST_CASE(NSECLikeBitmapTest, TestRdataTypes);
  59. // NSEC and NSEC3 bitmaps have some subtle differences, in which case we
  60. // need to test them separately. Using these typedef type names with TEST_F
  61. // will do the trick.
  62. typedef NSECLikeBitmapTest<generic::NSEC3> NSEC3BitmapTest;
  63. typedef NSECLikeBitmapTest<generic::NSEC> NSECBitmapTest;
  64. template <>
  65. string
  66. NSECLikeBitmapTest<generic::NSEC>::getWireFilePrefix() {
  67. return ("rdata_nsec_");
  68. }
  69. template <>
  70. RRType
  71. NSECLikeBitmapTest<generic::NSEC>::getType() {
  72. return (RRType::NSEC());
  73. }
  74. template <>
  75. string
  76. NSECLikeBitmapTest<generic::NSEC3>::getWireFilePrefix() {
  77. return ("rdata_nsec3_");
  78. }
  79. template <>
  80. RRType
  81. NSECLikeBitmapTest<generic::NSEC3>::getType() {
  82. return (RRType::NSEC3());
  83. }
  84. template <>
  85. string
  86. NSECLikeBitmapTest<generic::NSEC>::getCommonText() {
  87. return ("next. ");
  88. }
  89. template <>
  90. string
  91. NSECLikeBitmapTest<generic::NSEC3>::getCommonText() {
  92. return ("1 1 12 AABBCCDD 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR ");
  93. }
  94. // Tests against various types of bogus NSEC/NSEC3 type bitmaps.
  95. // The syntax and semantics are common for both RR types, and our
  96. // implementation of that part is shared, so in theory it should be sufficient
  97. // to test for only one RR type. But we check for both just in case.
  98. TYPED_TEST(NSECLikeBitmapTest, createFromWire) {
  99. // A malformed NSEC bitmap length field that could cause overflow.
  100. EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
  101. (this->getWireFilePrefix() +
  102. "fromWire4.wire").c_str()),
  103. DNSMessageFORMERR);
  104. // The bitmap field is incomplete (only the first byte is included)
  105. EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
  106. (this->getWireFilePrefix() +
  107. "fromWire5.wire").c_str()),
  108. DNSMessageFORMERR);
  109. // Bitmap length is 0, which is invalid.
  110. EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
  111. (this->getWireFilePrefix() +
  112. "fromWire6.wire").c_str()),
  113. DNSMessageFORMERR);
  114. // Too large bitmap length with a short buffer.
  115. EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
  116. (this->getWireFilePrefix() +
  117. "fromWire3").c_str()),
  118. DNSMessageFORMERR);
  119. // A boundary case: longest possible bitmaps (32 maps). This should be
  120. // accepted.
  121. EXPECT_NO_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
  122. (this->getWireFilePrefix() +
  123. "fromWire7.wire").c_str()));
  124. // Another boundary condition: 33 bitmaps, which should be rejected.
  125. EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
  126. (this->getWireFilePrefix() +
  127. "fromWire8.wire").c_str()),
  128. DNSMessageFORMERR);
  129. // Disordered bitmap window blocks.
  130. EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
  131. (this->getWireFilePrefix() +
  132. "fromWire9.wire").c_str()),
  133. DNSMessageFORMERR);
  134. // Bitmap ending with all-zero bytes. Not necessarily harmful except
  135. // the additional overhead of parsing, but invalid according to the
  136. // spec anyway.
  137. EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
  138. (this->getWireFilePrefix() +
  139. "fromWire10.wire").c_str()),
  140. DNSMessageFORMERR);
  141. }
  142. TYPED_TEST(NSECLikeBitmapTest, badText) {
  143. // redundant space after the sequence
  144. EXPECT_THROW(this->fromText(this->getCommonText() + "A "),
  145. InvalidRdataText);
  146. }
  147. // This tests the result of toText() with various kinds of NSEC/NSEC3 bitmaps.
  148. // It also tests the "from text" constructor as a result.
  149. TYPED_TEST(NSECLikeBitmapTest, toText) {
  150. // A simple case (some commonly seen RR types in NSEC(3) bitmaps)
  151. string rdata_text = this->getCommonText() + "NS SOA RRSIG DNSKEY";
  152. EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText());
  153. // Similar to above, but involves more than one bitmap window blocks.
  154. rdata_text = this->getCommonText() + "NS DLV";
  155. EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText());
  156. // Make sure all possible bits in a one-octet bitmap field are handled
  157. // correctly.
  158. // We use the range around 1024 (reasonably higher number) so it's
  159. // unlikely that they have predefined mnemonic and can be safely converted
  160. // to TYPEnnnn by toText().
  161. for (unsigned int i = 1024; i < 1032; ++i) {
  162. rdata_text = this->getCommonText() + "TYPE" + lexical_cast<string>(i);
  163. EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText());
  164. }
  165. // Make sure all possible 32 octets in a longest possible block are
  166. // handled correctly.
  167. for (unsigned int i = 1024; i < 1024 + 256; i += 8) {
  168. rdata_text = this->getCommonText() + "TYPE" + lexical_cast<string>(i);
  169. EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText());
  170. }
  171. // Check for the highest window block.
  172. rdata_text = this->getCommonText() + "TYPE65535";
  173. EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText());
  174. }
  175. TYPED_TEST(NSECLikeBitmapTest, compare) {
  176. // Bit map: [win=0][len=1] 00000010
  177. this->compare_set.push_back(this->fromText(this->getCommonText() + "SOA"));
  178. // Bit map: [win=0][len=1] 00000010, [win=4][len=1] 10000000
  179. this->compare_set.push_back(this->fromText(this->getCommonText() +
  180. "SOA TYPE1024"));
  181. // Bit map: [win=0][len=1] 00100000
  182. this->compare_set.push_back(this->fromText(this->getCommonText() + "NS"));
  183. // Bit map: [win=0][len=1] 00100010
  184. this->compare_set.push_back(this->fromText(this->getCommonText() +
  185. "NS SOA"));
  186. // Bit map: [win=0][len=2] 00100000, 00000001
  187. this->compare_set.push_back(this->fromText(this->getCommonText() +
  188. "NS MX"));
  189. // Bit map: [win=4][len=1] 10000000
  190. this->compare_set.push_back(this->fromText(this->getCommonText() +
  191. "TYPE1024"));
  192. this->compareCheck();
  193. }
  194. // NSEC bitmaps must not be empty
  195. TEST_F(NSECBitmapTest, emptyMap) {
  196. EXPECT_THROW(this->fromText("next.example").toText(), InvalidRdataText);
  197. EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
  198. (this->getWireFilePrefix() +
  199. "fromWire16.wire").c_str()),
  200. DNSMessageFORMERR);
  201. }
  202. // NSEC3 bitmaps can be empty
  203. TEST_F(NSEC3BitmapTest, emptyMap) {
  204. // Read wire data wit an empty NSEC3 bitmap. This should succeed.
  205. vector<uint8_t> data;
  206. UnitTestUtil::readWireData((this->getWireFilePrefix() +
  207. "fromWire16.wire").c_str(), data);
  208. InputBuffer buffer(&data[0], data.size());
  209. const uint16_t rdlen = buffer.readUint16();
  210. const generic::NSEC3 empty_nsec3 =
  211. dynamic_cast<const generic::NSEC3&>(*createRdata(
  212. RRType::NSEC3(), RRClass::IN(),
  213. buffer, rdlen));
  214. // Check the toText() result.
  215. EXPECT_EQ("1 0 1 7373737373 D1K6GQ38D1K6GQ38D1K6GQ38D1K6GQ38",
  216. empty_nsec3.toText());
  217. // Check the toWire() result.
  218. OutputBuffer obuffer(0);
  219. obuffer.writeUint16(rdlen);
  220. empty_nsec3.toWire(obuffer);
  221. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, obuffer.getData(),
  222. obuffer.getLength(), &data[0], data.size());
  223. // Same for MessageRenderer.
  224. obuffer.clear();
  225. MessageRenderer renderer;
  226. renderer.writeUint16(rdlen);
  227. empty_nsec3.toWire(renderer);
  228. EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
  229. renderer.getLength(), &data[0], data.size());
  230. }
  231. }