query_unittest.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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. #include <dns/message.h>
  15. #include <dns/name.h>
  16. #include <dns/rcode.h>
  17. #include <dns/rrttl.h>
  18. #include <dns/rrtype.h>
  19. #include <dns/rdataclass.h>
  20. #include <datasrc/memory_datasrc.h>
  21. #include <auth/query.h>
  22. #include <gtest/gtest.h>
  23. using namespace isc::dns;
  24. using namespace isc::datasrc;
  25. using namespace isc::auth;
  26. namespace {
  27. RRsetPtr a_rrset = RRsetPtr(new RRset(Name("www.example.com"),
  28. RRClass::IN(), RRType::A(),
  29. RRTTL(3600)));
  30. RRsetPtr ns_rrset(RRsetPtr(new RRset(Name("ns.example.com"),
  31. RRClass::IN(), RRType::NS(),
  32. RRTTL(3600))));
  33. RRsetPtr glue_a_rrset(RRsetPtr(new RRset(Name("glue.ns.example.com"),
  34. RRClass::IN(), RRType::A(),
  35. RRTTL(3600))));
  36. RRsetPtr glue_aaaa_rrset(RRsetPtr(new RRset(Name("glue.ns.example.com"),
  37. RRClass::IN(), RRType::AAAA(),
  38. RRTTL(3600))));
  39. RRsetPtr noglue_a_rrset(RRsetPtr(new RRset(Name("noglue.example.com"),
  40. RRClass::IN(), RRType::A(),
  41. RRTTL(3600))));
  42. RRsetPtr soa_rrset = RRsetPtr(new RRset(Name("example.com"),
  43. RRClass::IN(), RRType::SOA(),
  44. RRTTL(3600)));
  45. // This is a mock Zone class for testing.
  46. // It is a derived class of Zone, and simply hardcode the results of find()
  47. // return SUCCESS for "www.example.com",
  48. // return NXDOMAIN for "nxdomain.example.com",
  49. // return NXRRSET for "nxrrset.example.com",
  50. // return CNAME for "cname.example.com",
  51. // otherwise return DNAME
  52. class MockZone : public Zone {
  53. public:
  54. MockZone(bool has_SOA = true) :
  55. origin_(Name("example.com")),
  56. has_SOA_(has_SOA),
  57. delegation_rrset(RRsetPtr(new RRset(Name("delegation.example.com"),
  58. RRClass::IN(), RRType::NS(),
  59. RRTTL(3600)))),
  60. cname_rrset(RRsetPtr(new RRset(Name("cname.example.com"),
  61. RRClass::IN(), RRType::CNAME(),
  62. RRTTL(3600))))
  63. {
  64. delegation_rrset->addRdata(rdata::generic::NS(
  65. Name("glue.ns.example.com")));
  66. delegation_rrset->addRdata(rdata::generic::NS(
  67. Name("noglue.example.com")));
  68. delegation_rrset->addRdata(rdata::generic::NS(
  69. Name("cname.example.com")));
  70. delegation_rrset->addRdata(rdata::generic::NS(
  71. Name("example.org")));
  72. cname_rrset->addRdata(rdata::generic::CNAME(
  73. Name("www.example.com")));
  74. }
  75. virtual const isc::dns::Name& getOrigin() const;
  76. virtual const isc::dns::RRClass& getClass() const;
  77. FindResult find(const isc::dns::Name& name,
  78. const isc::dns::RRType& type,
  79. const FindOptions options = FIND_DEFAULT) const;
  80. private:
  81. Name origin_;
  82. bool has_SOA_;
  83. RRsetPtr delegation_rrset;
  84. RRsetPtr cname_rrset;
  85. };
  86. const Name&
  87. MockZone::getOrigin() const {
  88. return (origin_);
  89. }
  90. const RRClass&
  91. MockZone::getClass() const {
  92. return (RRClass::IN());
  93. }
  94. Zone::FindResult
  95. MockZone::find(const Name& name, const RRType& type, const FindOptions) const {
  96. // hardcode the find results
  97. if (name == Name("www.example.com")) {
  98. return (FindResult(SUCCESS, a_rrset));
  99. } else if (name == Name("glue.ns.example.com") && type == RRType::A()) {
  100. return (FindResult(SUCCESS, glue_a_rrset));
  101. } else if (name == Name("noglue.example.com") && type == RRType::A()) {
  102. return (FindResult(SUCCESS, noglue_a_rrset));
  103. } else if (name == Name("glue.ns.example.com") && type == RRType::AAAA()) {
  104. return (FindResult(SUCCESS, glue_aaaa_rrset));
  105. } else if (name == Name("example.com") && type == RRType::SOA() &&
  106. has_SOA_)
  107. {
  108. return (FindResult(SUCCESS, soa_rrset));
  109. } else if (name == Name("delegation.example.com")) {
  110. return (FindResult(DELEGATION, delegation_rrset));
  111. } else if (name == Name("ns.example.com")) {
  112. return (FindResult(DELEGATION, ns_rrset));
  113. } else if (name == Name("nxdomain.example.com")) {
  114. return (FindResult(NXDOMAIN, RRsetPtr()));
  115. } else if (name == Name("nxrrset.example.com")) {
  116. return (FindResult(NXRRSET, RRsetPtr()));
  117. } else if ((name == Name("cname.example.com"))) {
  118. return (FindResult(CNAME, cname_rrset));
  119. } else {
  120. return (FindResult(DNAME, RRsetPtr()));
  121. }
  122. }
  123. class QueryTest : public ::testing::Test {
  124. protected:
  125. QueryTest() :
  126. qname(Name("www.example.com")), qclass(RRClass::IN()),
  127. qtype(RRType::A()), response(Message::RENDER),
  128. query(memory_datasrc, qname, qtype, response)
  129. {
  130. response.setRcode(Rcode::NOERROR());
  131. }
  132. MemoryDataSrc memory_datasrc;
  133. const Name qname;
  134. const RRClass qclass;
  135. const RRType qtype;
  136. Message response;
  137. Query query;
  138. };
  139. TEST_F(QueryTest, noZone) {
  140. // There's no zone in the memory datasource. So the response should have
  141. // REFUSED.
  142. query.process();
  143. EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
  144. }
  145. TEST_F(QueryTest, matchZone) {
  146. // add a matching zone.
  147. memory_datasrc.addZone(ZonePtr(new MockZone()));
  148. query.process();
  149. EXPECT_TRUE(response.getHeaderFlag(Message::HEADERFLAG_AA));
  150. EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
  151. EXPECT_TRUE(response.hasRRset(Message::SECTION_ANSWER,
  152. Name("www.example.com"), RRClass::IN(),
  153. RRType::A()));
  154. // Delegation
  155. const Name delegation_name(Name("delegation.example.com"));
  156. Query delegation_query(memory_datasrc, delegation_name, qtype, response);
  157. delegation_query.process();
  158. EXPECT_FALSE(response.getHeaderFlag(Message::HEADERFLAG_AA));
  159. EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
  160. EXPECT_TRUE(response.hasRRset(Message::SECTION_AUTHORITY,
  161. Name("delegation.example.com"),
  162. RRClass::IN(), RRType::NS()));
  163. // glue address records
  164. EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
  165. Name("glue.ns.example.com"),
  166. RRClass::IN(), RRType::A()));
  167. EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
  168. Name("glue.ns.example.com"),
  169. RRClass::IN(), RRType::AAAA()));
  170. // noglue address records
  171. EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
  172. Name("noglue.example.com"),
  173. RRClass::IN(), RRType::A()));
  174. // NS name has a CNAME
  175. EXPECT_FALSE(response.hasRRset(Message::SECTION_ADDITIONAL,
  176. Name("www.example.com"),
  177. RRClass::IN(), RRType::A()));
  178. // NS name is out of zone
  179. EXPECT_FALSE(response.hasRRset(Message::SECTION_ADDITIONAL,
  180. Name("example.org"),
  181. RRClass::IN(), RRType::A()));
  182. // NXDOMAIN
  183. const Name nxdomain_name(Name("nxdomain.example.com"));
  184. Query nxdomain_query(memory_datasrc, nxdomain_name, qtype, response);
  185. nxdomain_query.process();
  186. EXPECT_EQ(Rcode::NXDOMAIN(), response.getRcode());
  187. EXPECT_EQ(0, response.getRRCount(Message::SECTION_ANSWER));
  188. EXPECT_EQ(0, response.getRRCount(Message::SECTION_ADDITIONAL));
  189. EXPECT_TRUE(response.hasRRset(Message::SECTION_AUTHORITY,
  190. Name("example.com"), RRClass::IN(), RRType::SOA()));
  191. // NXRRSET
  192. const Name nxrrset_name(Name("nxrrset.example.com"));
  193. Query nxrrset_query(memory_datasrc, nxrrset_name, qtype, response);
  194. nxrrset_query.process();
  195. EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
  196. EXPECT_EQ(0, response.getRRCount(Message::SECTION_ANSWER));
  197. EXPECT_EQ(0, response.getRRCount(Message::SECTION_ADDITIONAL));
  198. EXPECT_TRUE(response.hasRRset(Message::SECTION_AUTHORITY,
  199. Name("example.com"), RRClass::IN(), RRType::SOA()));
  200. }
  201. /*
  202. * This tests that when there's no SOA and we need a negative answer. It should
  203. * throw in that case.
  204. */
  205. TEST_F(QueryTest, noSOA) {
  206. memory_datasrc.addZone(ZonePtr(new MockZone(false)));
  207. // The NX Domain
  208. const Name nxdomain_name(Name("nxdomain.example.com"));
  209. Query nxdomain_query(memory_datasrc, nxdomain_name, qtype, response);
  210. EXPECT_THROW(nxdomain_query.process(), Query::NoSOA);
  211. // Of course, we don't look into the response, as it throwed
  212. // NXRRSET
  213. const Name nxrrset_name(Name("nxrrset.example.com"));
  214. Query nxrrset_query(memory_datasrc, nxrrset_name, qtype, response);
  215. EXPECT_THROW(nxrrset_query.process(), Query::NoSOA);
  216. }
  217. TEST_F(QueryTest, noMatchZone) {
  218. // there's a zone in the memory datasource but it doesn't match the qname.
  219. // should result in REFUSED.
  220. memory_datasrc.addZone(ZonePtr(new MockZone()));
  221. const Name nomatch_name(Name("example.org"));
  222. Query nomatch_query(memory_datasrc, nomatch_name, qtype, response);
  223. nomatch_query.process();
  224. EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
  225. }
  226. }