zone_finder_context_unittest.cc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. // Copyright (C) 2012 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 <exceptions/exceptions.h>
  15. #include <util/memory_segment_local.h>
  16. #include <dns/masterload.h>
  17. #include <dns/name.h>
  18. #include <dns/rrclass.h>
  19. #include <datasrc/zone.h>
  20. #include <datasrc/memory/memory_client.h>
  21. #include <datasrc/database.h>
  22. #include <datasrc/sqlite3_accessor.h>
  23. #include "test_client.h"
  24. #include <testutils/dnsmessage_test.h>
  25. #include <gtest/gtest.h>
  26. #include <boost/bind.hpp>
  27. #include <boost/foreach.hpp>
  28. #include <boost/shared_ptr.hpp>
  29. #include <fstream>
  30. #include <sstream>
  31. #include <vector>
  32. using namespace std;
  33. using boost::shared_ptr;
  34. using namespace isc::util;
  35. using namespace isc::dns;
  36. using namespace isc::datasrc;
  37. using isc::datasrc::memory::InMemoryClient;
  38. using namespace isc::testutils;
  39. namespace {
  40. // Commonly used test zone file.
  41. const char* const TEST_ZONE_FILE = TEST_DATA_DIR "/contexttest.zone";
  42. // Convenient shortcut
  43. typedef shared_ptr<DataSourceClient> DataSourceClientPtr;
  44. // This is the type used as the test parameter. Note that this is
  45. // intentionally a plain old type (i.e. a function pointer), not a class;
  46. // otherwise it could cause initialization fiasco at the instantiation time.
  47. typedef DataSourceClientPtr (*ClientCreator)(MemorySegment&, RRClass,
  48. const Name&);
  49. // Creator for the in-memory client to be tested
  50. DataSourceClientPtr
  51. createInMemoryClient(MemorySegment& mem_sgmt, RRClass zclass,
  52. const Name& zname)
  53. {
  54. shared_ptr<InMemoryClient> client(new InMemoryClient(mem_sgmt, zclass));
  55. client->load(zname, TEST_ZONE_FILE);
  56. return (client);
  57. }
  58. void
  59. addRRset(ZoneUpdaterPtr updater, ConstRRsetPtr rrset) {
  60. updater->addRRset(*rrset);
  61. }
  62. DataSourceClientPtr
  63. createSQLite3Client(MemorySegment&, RRClass zclass, const Name& zname) {
  64. // We always begin with an empty template SQLite3 DB file and install
  65. // the zone data from the zone file to ensure both cases have the
  66. // same test data.
  67. DataSourceClientPtr client = unittest::createSQLite3Client(
  68. zclass, zname, TEST_DATA_BUILDDIR "/contexttest.sqlite3.copied",
  69. TEST_ZONE_FILE);
  70. // Insert an out-of-zone name to test if it's incorrectly returned.
  71. // Note that neither updater nor SQLite3 accessor checks this condition,
  72. // so this should succeed.
  73. ZoneUpdaterPtr updater = client->getUpdater(zname, false);
  74. stringstream ss("ns.example.com. 3600 IN A 192.0.2.7");
  75. masterLoad(ss, Name::ROOT_NAME(), zclass,
  76. boost::bind(addRRset, updater, _1));
  77. updater->commit();
  78. return (client);
  79. }
  80. // The test class. Its parameterized so we can share the test scnearios
  81. // for any concrete data source implementaitons.
  82. class ZoneFinderContextTest :
  83. public ::testing::TestWithParam<ClientCreator>
  84. {
  85. protected:
  86. ZoneFinderContextTest() : qclass_(RRClass::IN()), qzone_("example.org") {
  87. client_ = (*GetParam())(mem_sgmt_, qclass_, qzone_);
  88. REQUESTED_A.push_back(RRType::A());
  89. REQUESTED_AAAA.push_back(RRType::AAAA());
  90. REQUESTED_BOTH.push_back(RRType::A());
  91. REQUESTED_BOTH.push_back(RRType::AAAA());
  92. }
  93. void SetUp() {
  94. finder_ = client_->findZone(qzone_).zone_finder;
  95. ASSERT_TRUE(finder_);
  96. }
  97. MemorySegmentLocal mem_sgmt_;
  98. const RRClass qclass_;
  99. const Name qzone_;
  100. DataSourceClientPtr client_;
  101. ZoneFinderPtr finder_;
  102. vector<RRType> requested_types_;
  103. vector<RRType> REQUESTED_A;
  104. vector<RRType> REQUESTED_AAAA;
  105. vector<RRType> REQUESTED_BOTH;
  106. vector<ConstRRsetPtr> result_sets_;
  107. };
  108. // We test the in-memory and SQLite3 data source implementations.
  109. INSTANTIATE_TEST_CASE_P(, ZoneFinderContextTest,
  110. ::testing::Values(createInMemoryClient,
  111. createSQLite3Client));
  112. TEST_P(ZoneFinderContextTest, getAdditionalAuthNS) {
  113. ZoneFinderContextPtr ctx = finder_->find(qzone_, RRType::NS());
  114. EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
  115. // Getting both A and AAAA NS addresses
  116. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  117. rrsetsCheck("ns1.example.org. 3600 IN A 192.0.2.1\n"
  118. "ns1.example.org. 3600 IN AAAA 2001:db8::1\n"
  119. "ns2.example.org. 3600 IN A 192.0.2.2\n",
  120. result_sets_.begin(), result_sets_.end());
  121. // Getting only A
  122. result_sets_.clear();
  123. ctx->getAdditional(REQUESTED_A, result_sets_);
  124. rrsetsCheck("ns1.example.org. 3600 IN A 192.0.2.1\n"
  125. "ns2.example.org. 3600 IN A 192.0.2.2\n",
  126. result_sets_.begin(), result_sets_.end());
  127. // Getting only AAAA
  128. result_sets_.clear();
  129. ctx->getAdditional(REQUESTED_AAAA, result_sets_);
  130. rrsetsCheck("ns1.example.org. 3600 IN AAAA 2001:db8::1\n",
  131. result_sets_.begin(), result_sets_.end());
  132. // Getting A again, without clearing the result sets. This confirms
  133. // getAdditional() doesn't change the existing vector content.
  134. ctx->getAdditional(REQUESTED_A, result_sets_);
  135. // The first element should be the existing AAAA RR, followed by the A's.
  136. EXPECT_EQ(RRType::AAAA(), result_sets_[0]->getType());
  137. rrsetsCheck("ns1.example.org. 3600 IN AAAA 2001:db8::1\n"
  138. "ns1.example.org. 3600 IN A 192.0.2.1\n"
  139. "ns2.example.org. 3600 IN A 192.0.2.2\n",
  140. result_sets_.begin(), result_sets_.end());
  141. // Normally expected type set contain only A and/or AAAA, but others aren't
  142. // excluded.
  143. result_sets_.clear();
  144. requested_types_.push_back(RRType::TXT());
  145. ctx->getAdditional(requested_types_, result_sets_);
  146. rrsetsCheck("ns2.example.org. 3600 IN TXT \"text data\"",
  147. result_sets_.begin(), result_sets_.end());
  148. // Even empty set is okay. The result should also be empty.
  149. result_sets_.clear();
  150. ctx->getAdditional(vector<RRType>(), result_sets_);
  151. EXPECT_TRUE(result_sets_.empty());
  152. }
  153. TEST_P(ZoneFinderContextTest, getAdditionalDelegation) {
  154. // Basically similar to the AuthNS case, but NS names are glues.
  155. // It contains an out-of-zone NS name. Its address (even if it's somehow
  156. // inserted to the zone data) shouldn't be returned.
  157. const Name qname("www.a.example.org");
  158. ZoneFinderContextPtr ctx = finder_->find(qname, RRType::AAAA());
  159. EXPECT_EQ(ZoneFinder::DELEGATION, ctx->code);
  160. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  161. rrsetsCheck("ns1.a.example.org. 3600 IN A 192.0.2.5\n"
  162. "ns2.a.example.org. 3600 IN A 192.0.2.6\n"
  163. "ns2.a.example.org. 3600 IN AAAA 2001:db8::6\n",
  164. result_sets_.begin(), result_sets_.end());
  165. result_sets_.clear();
  166. ctx->getAdditional(REQUESTED_A, result_sets_);
  167. rrsetsCheck("ns1.a.example.org. 3600 IN A 192.0.2.5\n"
  168. "ns2.a.example.org. 3600 IN A 192.0.2.6\n",
  169. result_sets_.begin(), result_sets_.end());
  170. result_sets_.clear();
  171. ctx->getAdditional(REQUESTED_AAAA, result_sets_);
  172. rrsetsCheck("ns2.a.example.org. 3600 IN AAAA 2001:db8::6\n",
  173. result_sets_.begin(), result_sets_.end());
  174. }
  175. TEST_P(ZoneFinderContextTest, getAdditionalDelegationAtZoneCut) {
  176. // Similar to the previous case, but one of the NS addresses is at the
  177. // zone cut.
  178. ZoneFinderContextPtr ctx = finder_->find(Name("www.b.example.org"),
  179. RRType::SOA());
  180. EXPECT_EQ(ZoneFinder::DELEGATION, ctx->code);
  181. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  182. rrsetsCheck("b.example.org. 3600 IN AAAA 2001:db8::8\n"
  183. "ns.b.example.org. 3600 IN A 192.0.2.9\n",
  184. result_sets_.begin(), result_sets_.end());
  185. }
  186. TEST_P(ZoneFinderContextTest, getAdditionalDelegationWithDname) {
  187. // Delegation: One of the NS names under a DNAME delegation; another
  188. // is at the delegation point; yet another is under DNAME below a zone cut.
  189. // The first should be hidden.
  190. ZoneFinderContextPtr ctx = finder_->find(Name("www.c.example.org"),
  191. RRType::TXT());
  192. EXPECT_EQ(ZoneFinder::DELEGATION, ctx->code);
  193. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  194. rrsetsCheck("dname.example.org. 3600 IN A 192.0.2.12\n"
  195. "ns.deepdname.example.org. 3600 IN AAAA 2001:db8::9\n",
  196. result_sets_.begin(), result_sets_.end());
  197. }
  198. TEST_P(ZoneFinderContextTest, getAdditionalOnDname) {
  199. // The additional name has a DNAME as well as the additional record.
  200. // The existence of DNAME shouldn't hide the additional record.
  201. ZoneFinderContextPtr ctx = finder_->find(Name("dnamemx.example.org"),
  202. RRType::MX());
  203. EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
  204. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  205. rrsetsCheck("dname.example.org. 3600 IN A 192.0.2.12\n",
  206. result_sets_.begin(), result_sets_.end());
  207. }
  208. TEST_P(ZoneFinderContextTest, getAdditionalDelegationWithEmptyName) {
  209. // One of NS names is at an empty non terminal node. It shouldn't cause
  210. // any disruption.
  211. ZoneFinderContextPtr ctx = finder_->find(Name("www.d.example.org"),
  212. RRType::A());
  213. EXPECT_EQ(ZoneFinder::DELEGATION, ctx->code);
  214. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  215. rrsetsCheck("ns1.example.org. 3600 IN A 192.0.2.1\n"
  216. "ns1.example.org. 3600 IN AAAA 2001:db8::1\n",
  217. result_sets_.begin(), result_sets_.end());
  218. }
  219. TEST_P(ZoneFinderContextTest, getAdditionalDelegationWithWild) {
  220. // An NS name needs to be expanded by a wildcard. Another NS name
  221. // also matches a wildcard, but it's an empty node, so there's no
  222. // corresponding additional RR. The other NS name isn't subject to
  223. // wildcard expansion, which shouldn't cause any disruption.
  224. ZoneFinderContextPtr ctx = finder_->find(Name("www.e.example.org"),
  225. RRType::AAAA());
  226. EXPECT_EQ(ZoneFinder::DELEGATION, ctx->code);
  227. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  228. rrsetsCheck("ns.wild.example.org. 3600 IN A 192.0.2.15\n"
  229. "ns2.example.org. 3600 IN A 192.0.2.2\n",
  230. result_sets_.begin(), result_sets_.end());
  231. // ns.wild.example.org/A (expanded from a wildcard) should be considered
  232. // the same kind, whether it's a direct result of find() or a result of
  233. // getAdditional().
  234. ctx = finder_->find(Name("ns.wild.example.org"), RRType::A());
  235. EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
  236. for (vector<ConstRRsetPtr>::const_iterator it = result_sets_.begin();
  237. it != result_sets_.end(); ++it) {
  238. const bool same_kind = (*it)->isSameKind(*ctx->rrset);
  239. EXPECT_EQ((*it)->getName() == ctx->rrset->getName(), same_kind);
  240. }
  241. }
  242. TEST_P(ZoneFinderContextTest, getAdditionalDelegationForWild) {
  243. // additional for an answer RRset (MX) as a result of wildcard expansion.
  244. // note the difference from the previous test. in this case wildcard
  245. // applies to the owner name of the answer, not the owner name of the
  246. // additional.
  247. ZoneFinderContextPtr ctx = finder_->find(Name("mx.wildmx.example.org"),
  248. RRType::MX());
  249. EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
  250. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  251. rrsetsCheck("mx1.example.org. 3600 IN A 192.0.2.10\n",
  252. result_sets_.begin(), result_sets_.end());
  253. }
  254. TEST_P(ZoneFinderContextTest, getAdditionalMX) {
  255. // Similar to the previous cases, but for MX addresses. The test zone
  256. // contains MX name under a zone cut. Its address shouldn't be returned.
  257. ZoneFinderContextPtr ctx = finder_->find(qzone_, RRType::MX());
  258. EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
  259. // Getting both A and AAAA NS addresses
  260. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  261. rrsetsCheck("mx1.example.org. 3600 IN A 192.0.2.10\n"
  262. "mx2.example.org. 3600 IN AAAA 2001:db8::10\n",
  263. result_sets_.begin(), result_sets_.end());
  264. // Getting only A
  265. result_sets_.clear();
  266. ctx->getAdditional(REQUESTED_A, result_sets_);
  267. rrsetsCheck("mx1.example.org. 3600 IN A 192.0.2.10\n",
  268. result_sets_.begin(), result_sets_.end());
  269. // Getting only AAAA
  270. result_sets_.clear();
  271. ctx->getAdditional(REQUESTED_AAAA, result_sets_);
  272. rrsetsCheck("mx2.example.org. 3600 IN AAAA 2001:db8::10\n",
  273. result_sets_.begin(), result_sets_.end());
  274. }
  275. TEST_P(ZoneFinderContextTest, getAdditionalMXAtZoneCut) {
  276. ZoneFinderContextPtr ctx = finder_->find(Name("mxatcut.example.org."),
  277. RRType::MX());
  278. EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
  279. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  280. EXPECT_TRUE(result_sets_.empty());
  281. }
  282. TEST_P(ZoneFinderContextTest, getAdditionalWithSIG) {
  283. // Similar to the AuthNS test, but the original find() requested DNSSEC
  284. // RRSIGs. Then additional records will also have RRSIGs.
  285. ZoneFinderContextPtr ctx = finder_->find(qzone_, RRType::NS(),
  286. ZoneFinder::FIND_DNSSEC);
  287. EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
  288. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  289. rrsetsCheck("ns1.example.org. 3600 IN A 192.0.2.1\n"
  290. "ns1.example.org. 3600 IN RRSIG A 7 3 3600 20150420235959 "
  291. "20051021000000 40430 example.org. FAKEFAKE\n"
  292. "ns1.example.org. 3600 IN AAAA 2001:db8::1\n"
  293. "ns1.example.org. 3600 IN RRSIG AAAA 7 3 3600 20150420235959 "
  294. "20051021000000 40430 example.org. FAKEFAKEFAKE\n"
  295. "ns2.example.org. 3600 IN A 192.0.2.2\n",
  296. result_sets_.begin(), result_sets_.end());
  297. vector<ConstRRsetPtr> sigresult_sets;
  298. BOOST_FOREACH(ConstRRsetPtr rrset, result_sets_) {
  299. ConstRRsetPtr sig_rrset = rrset->getRRsig();
  300. if (sig_rrset) {
  301. sigresult_sets.push_back(sig_rrset);
  302. }
  303. }
  304. rrsetsCheck("ns1.example.org. 3600 IN RRSIG A 7 3 3600 20150420235959 "
  305. "20051021000000 40430 example.org. FAKEFAKE\n"
  306. "ns1.example.org. 3600 IN RRSIG AAAA 7 3 3600 20150420235959 "
  307. "20051021000000 40430 example.org. FAKEFAKEFAKE\n",
  308. sigresult_sets.begin(), sigresult_sets.end());
  309. }
  310. TEST_P(ZoneFinderContextTest, getAdditionalNoOP) {
  311. // getAdditional() is only meaningful after SUCCESS or DELEGATION.
  312. ZoneFinderContextPtr ctx = finder_->find(Name("nxdomain.example.org"),
  313. RRType::NS());
  314. EXPECT_EQ(ZoneFinder::NXDOMAIN, ctx->code);
  315. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  316. EXPECT_TRUE(result_sets_.empty());
  317. ctx = finder_->find(qzone_, RRType::TXT());
  318. EXPECT_EQ(ZoneFinder::NXRRSET, ctx->code);
  319. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  320. EXPECT_TRUE(result_sets_.empty());
  321. ctx = finder_->find(Name("alias.example.org."), RRType::A());
  322. EXPECT_EQ(ZoneFinder::CNAME, ctx->code);
  323. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  324. EXPECT_TRUE(result_sets_.empty());
  325. ctx = finder_->find(Name("www.dname.example.org."), RRType::A());
  326. EXPECT_EQ(ZoneFinder::DNAME, ctx->code);
  327. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  328. EXPECT_TRUE(result_sets_.empty());
  329. }
  330. TEST_P(ZoneFinderContextTest, getAdditionalForAny) {
  331. // getAdditional() after successful type ANY query should return
  332. // the additional records of all returned RRsets.
  333. vector<ConstRRsetPtr> all_rrsets;
  334. ZoneFinderContextPtr ctx = finder_->findAll(qzone_, all_rrsets);
  335. EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
  336. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  337. rrsetsCheck("ns1.example.org. 3600 IN A 192.0.2.1\n"
  338. "ns1.example.org. 3600 IN AAAA 2001:db8::1\n"
  339. "ns2.example.org. 3600 IN A 192.0.2.2\n"
  340. "mx1.example.org. 3600 IN A 192.0.2.10\n"
  341. "mx2.example.org. 3600 IN AAAA 2001:db8::10\n",
  342. result_sets_.begin(), result_sets_.end());
  343. // If the type ANY query results in DELEGATION, the result should be the
  344. // same as normal query.
  345. all_rrsets.clear();
  346. result_sets_.clear();
  347. ctx = finder_->findAll(Name("www.a.example.org"), all_rrsets);
  348. EXPECT_EQ(ZoneFinder::DELEGATION, ctx->code);
  349. ctx->getAdditional(REQUESTED_BOTH, result_sets_);
  350. rrsetsCheck("ns1.a.example.org. 3600 IN A 192.0.2.5\n"
  351. "ns2.a.example.org. 3600 IN A 192.0.2.6\n"
  352. "ns2.a.example.org. 3600 IN AAAA 2001:db8::6\n",
  353. result_sets_.begin(), result_sets_.end());
  354. }
  355. }