query_unittest.cc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  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 soa_rrset = RRsetPtr(new RRset(Name("example.com"),
  31. RRClass::IN(), RRType::SOA(),
  32. RRTTL(3600)));
  33. RRsetPtr ns_rrset(RRsetPtr(new RRset(Name("ns.example.com"),
  34. RRClass::IN(), RRType::NS(),
  35. RRTTL(3600))));
  36. RRsetPtr glue_a_rrset(RRsetPtr(new RRset(Name("glue.ns.example.com"),
  37. RRClass::IN(), RRType::A(),
  38. RRTTL(3600))));
  39. RRsetPtr glue_aaaa_rrset(RRsetPtr(new RRset(Name("glue.ns.example.com"),
  40. RRClass::IN(), RRType::AAAA(),
  41. RRTTL(3600))));
  42. RRsetPtr noglue_a_rrset(RRsetPtr(new RRset(Name("noglue.example.com"),
  43. RRClass::IN(), RRType::A(),
  44. RRTTL(3600))));
  45. RRsetPtr delegated_mx_a_rrset(RRsetPtr(new RRset(
  46. Name("mx.delegation.example.com"), RRClass::IN(), RRType::A(),
  47. RRTTL(3600))));
  48. // This is a mock Zone class for testing.
  49. // It is a derived class of Zone, and simply hardcodes the results of find()
  50. // See the find() implementation if you want to know its content.
  51. class MockZone : public Zone {
  52. public:
  53. MockZone(bool has_SOA = true, bool has_apex_NS = true) :
  54. origin_(Name("example.com")),
  55. has_SOA_(has_SOA),
  56. has_apex_NS_(has_apex_NS),
  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. auth_ns_rrset(RRsetPtr(new RRset(Name("example.com"),
  64. RRClass::IN(), RRType::NS(),
  65. RRTTL(3600)))),
  66. mx_cname_rrset_(new RRset(Name("cnamemailer.example.com"),
  67. RRClass::IN(), RRType::CNAME(), RRTTL(3600))),
  68. mx_rrset_(new RRset(Name("mx.example.com"), RRClass::IN(),
  69. RRType::MX(), RRTTL(3600)))
  70. {
  71. delegation_rrset->addRdata(rdata::generic::NS(
  72. Name("glue.ns.example.com")));
  73. delegation_rrset->addRdata(rdata::generic::NS(
  74. Name("noglue.example.com")));
  75. delegation_rrset->addRdata(rdata::generic::NS(
  76. Name("cname.example.com")));
  77. delegation_rrset->addRdata(rdata::generic::NS(
  78. Name("example.org")));
  79. cname_rrset->addRdata(rdata::generic::CNAME(
  80. Name("www.example.com")));
  81. auth_ns_rrset->addRdata(rdata::generic::NS(
  82. Name("glue.ns.example.com")));
  83. auth_ns_rrset->addRdata(rdata::generic::NS(
  84. Name("noglue.example.com")));
  85. auth_ns_rrset->addRdata(rdata::generic::NS(
  86. Name("example.net")));
  87. mx_rrset_->addRdata(isc::dns::rdata::generic::MX(10,
  88. Name("www.example.com")));
  89. mx_rrset_->addRdata(isc::dns::rdata::generic::MX(20,
  90. Name("mailer.example.org")));
  91. mx_rrset_->addRdata(isc::dns::rdata::generic::MX(30,
  92. Name("mx.delegation.example.com")));
  93. mx_cname_rrset_->addRdata(rdata::generic::CNAME(
  94. Name("mx.example.com")));
  95. }
  96. virtual const isc::dns::Name& getOrigin() const;
  97. virtual const isc::dns::RRClass& getClass() const;
  98. FindResult find(const isc::dns::Name& name,
  99. const isc::dns::RRType& type,
  100. RRsetList* target = NULL,
  101. const FindOptions options = FIND_DEFAULT) const;
  102. private:
  103. Name origin_;
  104. bool has_SOA_;
  105. bool has_apex_NS_;
  106. RRsetPtr delegation_rrset;
  107. RRsetPtr cname_rrset;
  108. RRsetPtr auth_ns_rrset;
  109. RRsetPtr mx_cname_rrset_;
  110. RRsetPtr mx_rrset_;
  111. };
  112. const Name&
  113. MockZone::getOrigin() const {
  114. return (origin_);
  115. }
  116. const RRClass&
  117. MockZone::getClass() const {
  118. return (RRClass::IN());
  119. }
  120. Zone::FindResult
  121. MockZone::find(const Name& name, const RRType& type,
  122. RRsetList* target, const FindOptions options) const
  123. {
  124. // hardcode the find results
  125. if (name == Name("www.example.com") && type == RRType::A()) {
  126. return (FindResult(SUCCESS, a_rrset));
  127. } else if (name == Name("www.example.com")) {
  128. return (FindResult(NXRRSET, RRsetPtr()));
  129. } else if (name == Name("glue.ns.example.com") && type == RRType::A() &&
  130. (options & FIND_GLUE_OK) != 0) {
  131. return (FindResult(SUCCESS, glue_a_rrset));
  132. } else if (name == Name("noglue.example.com") && (type == RRType::A() ||
  133. type == RRType::ANY())) {
  134. return (FindResult(SUCCESS, noglue_a_rrset));
  135. } else if (name == Name("glue.ns.example.com") && type == RRType::AAAA() &&
  136. (options & FIND_GLUE_OK) != 0) {
  137. return (FindResult(SUCCESS, glue_aaaa_rrset));
  138. } else if (name == Name("example.com") && type == RRType::SOA() &&
  139. has_SOA_)
  140. {
  141. return (FindResult(SUCCESS, soa_rrset));
  142. } else if (name == Name("example.com") && type == RRType::NS() &&
  143. has_apex_NS_)
  144. {
  145. return (FindResult(SUCCESS, auth_ns_rrset));
  146. } else if (name == Name("example.com") && type == RRType::ANY()) {
  147. target->addRRset(soa_rrset);
  148. target->addRRset(auth_ns_rrset);
  149. return (FindResult(SUCCESS, RRsetPtr()));
  150. } else if (name == Name("mx.delegation.example.com") &&
  151. type == RRType::A() && (options & FIND_GLUE_OK) != 0)
  152. {
  153. return (FindResult(SUCCESS, delegated_mx_a_rrset));
  154. } else if (name == Name("delegation.example.com") ||
  155. name.compare(Name("delegation.example.com")).getRelation() ==
  156. NameComparisonResult::SUBDOMAIN)
  157. {
  158. return (FindResult(DELEGATION, delegation_rrset));
  159. } else if (name == Name("ns.example.com")) {
  160. return (FindResult(DELEGATION, ns_rrset));
  161. } else if (name == Name("nxdomain.example.com")) {
  162. return (FindResult(NXDOMAIN, RRsetPtr()));
  163. } else if (name == Name("nxrrset.example.com")) {
  164. return (FindResult(NXRRSET, RRsetPtr()));
  165. } else if ((name == Name("cname.example.com"))) {
  166. return (FindResult(CNAME, cname_rrset));
  167. } else if (name == Name("cnamemailer.example.com")) {
  168. return (FindResult(CNAME, mx_cname_rrset_));
  169. } else if (name == Name("mx.example.com")) {
  170. return (FindResult(SUCCESS, mx_rrset_));
  171. } else {
  172. return (FindResult(DNAME, RRsetPtr()));
  173. }
  174. }
  175. class QueryTest : public ::testing::Test {
  176. protected:
  177. QueryTest() :
  178. qname(Name("www.example.com")), qclass(RRClass::IN()),
  179. qtype(RRType::A()), response(Message::RENDER),
  180. query(memory_datasrc, qname, qtype, response)
  181. {
  182. response.setRcode(Rcode::NOERROR());
  183. }
  184. MemoryDataSrc memory_datasrc;
  185. const Name qname;
  186. const RRClass qclass;
  187. const RRType qtype;
  188. Message response;
  189. Query query;
  190. };
  191. TEST_F(QueryTest, noZone) {
  192. // There's no zone in the memory datasource. So the response should have
  193. // REFUSED.
  194. EXPECT_NO_THROW(query.process());
  195. EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
  196. }
  197. TEST_F(QueryTest, exactMatch) {
  198. // add a matching zone.
  199. memory_datasrc.addZone(ZonePtr(new MockZone()));
  200. EXPECT_NO_THROW(query.process());
  201. // find match rrset
  202. EXPECT_TRUE(response.getHeaderFlag(Message::HEADERFLAG_AA));
  203. EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
  204. EXPECT_TRUE(response.hasRRset(Message::SECTION_ANSWER,
  205. Name("www.example.com"), RRClass::IN(),
  206. RRType::A()));
  207. EXPECT_TRUE(response.hasRRset(Message::SECTION_AUTHORITY,
  208. Name("example.com"), RRClass::IN(),
  209. RRType::NS()));
  210. EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
  211. Name("glue.ns.example.com"),
  212. RRClass::IN(), RRType::A()));
  213. EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
  214. Name("glue.ns.example.com"),
  215. RRClass::IN(), RRType::AAAA()));
  216. EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
  217. Name("noglue.example.com"),
  218. RRClass::IN(), RRType::A()));
  219. }
  220. TEST_F(QueryTest, exactAddrMatch) {
  221. // find match rrset, omit additional data which has already been provided
  222. // in the answer section from the additional.
  223. memory_datasrc.addZone(ZonePtr(new MockZone()));
  224. const Name noglue_name(Name("noglue.example.com"));
  225. Query noglue_query(memory_datasrc, noglue_name, qtype, response);
  226. EXPECT_NO_THROW(noglue_query.process());
  227. EXPECT_TRUE(response.getHeaderFlag(Message::HEADERFLAG_AA));
  228. EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
  229. EXPECT_TRUE(response.hasRRset(Message::SECTION_ANSWER,
  230. Name("noglue.example.com"), RRClass::IN(),
  231. RRType::A()));
  232. EXPECT_TRUE(response.hasRRset(Message::SECTION_AUTHORITY,
  233. Name("example.com"), RRClass::IN(),
  234. RRType::NS()));
  235. EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
  236. Name("glue.ns.example.com"),
  237. RRClass::IN(), RRType::A()));
  238. EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
  239. Name("glue.ns.example.com"),
  240. RRClass::IN(), RRType::AAAA()));
  241. EXPECT_FALSE(response.hasRRset(Message::SECTION_ADDITIONAL,
  242. Name("noglue.example.com"),
  243. RRClass::IN(), RRType::A()));
  244. }
  245. TEST_F(QueryTest, apexNSMatch) {
  246. // find match rrset, omit authority data which has already been provided
  247. // in the answer section from the authority section.
  248. memory_datasrc.addZone(ZonePtr(new MockZone()));
  249. const Name apex_name(Name("example.com"));
  250. Query apex_ns_query(memory_datasrc, apex_name, RRType::NS(), response);
  251. EXPECT_NO_THROW(apex_ns_query.process());
  252. EXPECT_TRUE(response.getHeaderFlag(Message::HEADERFLAG_AA));
  253. EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
  254. EXPECT_TRUE(response.hasRRset(Message::SECTION_ANSWER,
  255. Name("example.com"), RRClass::IN(),
  256. RRType::NS()));
  257. EXPECT_FALSE(response.hasRRset(Message::SECTION_AUTHORITY,
  258. Name("example.com"), RRClass::IN(),
  259. RRType::NS()));
  260. EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
  261. Name("glue.ns.example.com"),
  262. RRClass::IN(), RRType::A()));
  263. EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
  264. Name("glue.ns.example.com"),
  265. RRClass::IN(), RRType::AAAA()));
  266. EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
  267. Name("noglue.example.com"),
  268. RRClass::IN(), RRType::A()));
  269. }
  270. TEST_F(QueryTest, exactAnyMatch) {
  271. // find match rrset, omit additional data which has already been provided
  272. // in the answer section from the additional.
  273. memory_datasrc.addZone(ZonePtr(new MockZone()));
  274. const Name noglue_name(Name("noglue.example.com"));
  275. Query noglue_query(memory_datasrc, noglue_name, RRType::ANY(), response);
  276. EXPECT_NO_THROW(noglue_query.process());
  277. EXPECT_TRUE(response.getHeaderFlag(Message::HEADERFLAG_AA));
  278. EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
  279. EXPECT_TRUE(response.hasRRset(Message::SECTION_ANSWER,
  280. Name("noglue.example.com"), RRClass::IN(),
  281. RRType::A()));
  282. EXPECT_TRUE(response.hasRRset(Message::SECTION_AUTHORITY,
  283. Name("example.com"), RRClass::IN(),
  284. RRType::NS()));
  285. EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
  286. Name("glue.ns.example.com"),
  287. RRClass::IN(), RRType::A()));
  288. EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
  289. Name("glue.ns.example.com"),
  290. RRClass::IN(), RRType::AAAA()));
  291. EXPECT_FALSE(response.hasRRset(Message::SECTION_ADDITIONAL,
  292. Name("noglue.example.com"),
  293. RRClass::IN(), RRType::A()));
  294. }
  295. // This tests that when we need to look up Zone's apex NS records for
  296. // authoritative answer, and there is no apex NS records. It should
  297. // throw in that case.
  298. TEST_F(QueryTest, noApexNS) {
  299. // Add a zone without apex NS records
  300. memory_datasrc.addZone(ZonePtr(new MockZone(true, false)));
  301. const Name noglue_name(Name("noglue.example.com"));
  302. Query noglue_query(memory_datasrc, noglue_name, qtype, response);
  303. EXPECT_THROW(noglue_query.process(), Query::NoApexNS);
  304. // We don't look into the response, as it throwed
  305. }
  306. TEST_F(QueryTest, delegation) {
  307. // add a matching zone.
  308. memory_datasrc.addZone(ZonePtr(new MockZone()));
  309. const Name delegation_name(Name("delegation.example.com"));
  310. Query delegation_query(memory_datasrc, delegation_name, qtype, response);
  311. EXPECT_NO_THROW(delegation_query.process());
  312. EXPECT_FALSE(response.getHeaderFlag(Message::HEADERFLAG_AA));
  313. EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
  314. EXPECT_TRUE(response.hasRRset(Message::SECTION_AUTHORITY,
  315. Name("delegation.example.com"),
  316. RRClass::IN(), RRType::NS()));
  317. // glue address records
  318. EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
  319. Name("glue.ns.example.com"),
  320. RRClass::IN(), RRType::A()));
  321. EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
  322. Name("glue.ns.example.com"),
  323. RRClass::IN(), RRType::AAAA()));
  324. // noglue address records
  325. EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
  326. Name("noglue.example.com"),
  327. RRClass::IN(), RRType::A()));
  328. // NS name has a CNAME
  329. EXPECT_FALSE(response.hasRRset(Message::SECTION_ADDITIONAL,
  330. Name("www.example.com"),
  331. RRClass::IN(), RRType::A()));
  332. // NS name is out of zone
  333. EXPECT_FALSE(response.hasRRset(Message::SECTION_ADDITIONAL,
  334. Name("example.org"),
  335. RRClass::IN(), RRType::A()));
  336. }
  337. TEST_F(QueryTest, nxdomain) {
  338. // add a matching zone.
  339. memory_datasrc.addZone(ZonePtr(new MockZone()));
  340. const Name nxdomain_name(Name("nxdomain.example.com"));
  341. Query nxdomain_query(memory_datasrc, nxdomain_name, qtype, response);
  342. EXPECT_NO_THROW(nxdomain_query.process());
  343. EXPECT_EQ(Rcode::NXDOMAIN(), response.getRcode());
  344. EXPECT_EQ(0, response.getRRCount(Message::SECTION_ANSWER));
  345. EXPECT_EQ(0, response.getRRCount(Message::SECTION_ADDITIONAL));
  346. EXPECT_TRUE(response.hasRRset(Message::SECTION_AUTHORITY,
  347. Name("example.com"), RRClass::IN(), RRType::SOA()));
  348. }
  349. TEST_F(QueryTest, nxrrset) {
  350. // add a matching zone.
  351. memory_datasrc.addZone(ZonePtr(new MockZone()));
  352. const Name nxrrset_name(Name("nxrrset.example.com"));
  353. Query nxrrset_query(memory_datasrc, nxrrset_name, qtype, response);
  354. EXPECT_NO_THROW(nxrrset_query.process());
  355. EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
  356. EXPECT_EQ(0, response.getRRCount(Message::SECTION_ANSWER));
  357. EXPECT_EQ(0, response.getRRCount(Message::SECTION_ADDITIONAL));
  358. EXPECT_TRUE(response.hasRRset(Message::SECTION_AUTHORITY,
  359. Name("example.com"), RRClass::IN(), RRType::SOA()));
  360. }
  361. /*
  362. * This tests that when there's no SOA and we need a negative answer. It should
  363. * throw in that case.
  364. */
  365. TEST_F(QueryTest, noSOA) {
  366. memory_datasrc.addZone(ZonePtr(new MockZone(false)));
  367. // The NX Domain
  368. const Name nxdomain_name(Name("nxdomain.example.com"));
  369. Query nxdomain_query(memory_datasrc, nxdomain_name, qtype, response);
  370. EXPECT_THROW(nxdomain_query.process(), Query::NoSOA);
  371. // Of course, we don't look into the response, as it throwed
  372. // NXRRSET
  373. const Name nxrrset_name(Name("nxrrset.example.com"));
  374. Query nxrrset_query(memory_datasrc, nxrrset_name, qtype, response);
  375. EXPECT_THROW(nxrrset_query.process(), Query::NoSOA);
  376. }
  377. TEST_F(QueryTest, noMatchZone) {
  378. // there's a zone in the memory datasource but it doesn't match the qname.
  379. // should result in REFUSED.
  380. memory_datasrc.addZone(ZonePtr(new MockZone()));
  381. const Name nomatch_name(Name("example.org"));
  382. Query nomatch_query(memory_datasrc, nomatch_name, qtype, response);
  383. nomatch_query.process();
  384. EXPECT_EQ(Rcode::REFUSED(), response.getRcode());
  385. }
  386. /*
  387. * Test MX additional processing.
  388. *
  389. * The MX RRset has two RRs, one pointing to a known domain with
  390. * A record, other to unknown out of zone one.
  391. */
  392. TEST_F(QueryTest, MX) {
  393. memory_datasrc.addZone(ZonePtr(new MockZone()));
  394. Name qname("mx.example.com");
  395. Query mx_query(memory_datasrc, qname, RRType::MX(), response);
  396. EXPECT_NO_THROW(mx_query.process());
  397. EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
  398. EXPECT_TRUE(response.hasRRset(Message::SECTION_ANSWER,
  399. Name("mx.example.com"), RRClass::IN(), RRType::MX()));
  400. EXPECT_TRUE(response.hasRRset(Message::SECTION_ADDITIONAL,
  401. Name("www.example.com"), RRClass::IN(), RRType::A()));
  402. // We want to skip the additional ones related to authoritative
  403. RRsetPtr ns;
  404. for (SectionIterator<RRsetPtr> ai(response.beginSection(
  405. Message::SECTION_AUTHORITY)); ai != response.endSection(
  406. Message::SECTION_AUTHORITY); ++ai)
  407. {
  408. if ((*ai)->getName() == Name("example.com") && (*ai)->getType() ==
  409. RRType::NS())
  410. {
  411. ns = *ai;
  412. break;
  413. }
  414. }
  415. /*
  416. * In fact, the MX RRset mentions three names, but we don't know anything
  417. * about one of them and one is under a zone cut, so we should have just
  418. * one RRset (A for www.example.com)
  419. */
  420. // We can't use getRRCount, as it counts RRs, not RRsets
  421. unsigned additional_count(0);
  422. for (SectionIterator<RRsetPtr> ai(response.beginSection(
  423. Message::SECTION_ADDITIONAL)); ai != response.endSection(
  424. Message::SECTION_ADDITIONAL); ++ai)
  425. {
  426. // Skip the ones for the NS record
  427. if (ns) {
  428. for (RdataIteratorPtr nsi(ns->getRdataIterator()); !nsi->isLast();
  429. nsi->next())
  430. {
  431. if ((*ai)->getName() ==
  432. dynamic_cast<const isc::dns::rdata::generic::NS&>(
  433. nsi->getCurrent()).getNSName())
  434. {
  435. goto NS_ADDITIONAL_DATA;
  436. }
  437. }
  438. }
  439. // It is not related to the NS, then it must be related to the MX
  440. ++additional_count;
  441. EXPECT_EQ(Name("www.example.com"), (*ai)->getName());
  442. EXPECT_EQ(RRType::A(), (*ai)->getType());
  443. NS_ADDITIONAL_DATA:;
  444. }
  445. EXPECT_EQ(1, additional_count);
  446. }
  447. /*
  448. * Test when we ask for MX and encounter an alias (CNAME in this case).
  449. *
  450. * This should not trigger the additional processing.
  451. */
  452. TEST_F(QueryTest, MXAlias) {
  453. memory_datasrc.addZone(ZonePtr(new MockZone()));
  454. Name qname("cnamemailer.example.com");
  455. Query mx_query(memory_datasrc, qname, RRType::MX(), response);
  456. EXPECT_NO_THROW(mx_query.process());
  457. EXPECT_EQ(Rcode::NOERROR(), response.getRcode());
  458. // We should not have the IP address in additional section
  459. // Currently, the section should be completely empty
  460. EXPECT_TRUE(response.beginSection(Message::SECTION_ADDITIONAL) ==
  461. response.endSection(Message::SECTION_ADDITIONAL));
  462. }
  463. }