data_source.cc 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476
  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 <config.h>
  15. #include <cassert>
  16. #include <iomanip>
  17. #include <iostream>
  18. #include <vector>
  19. #include <boost/shared_ptr.hpp>
  20. #include <boost/foreach.hpp>
  21. #include <datasrc/cache.h>
  22. #include <datasrc/data_source.h>
  23. #include <datasrc/query.h>
  24. #include <datasrc/logger.h>
  25. #include <util/encode/base32hex.h>
  26. #include <util/hash/sha1.h>
  27. #include <util/buffer.h>
  28. #include <dns/message.h>
  29. #include <dns/name.h>
  30. #include <dns/rcode.h>
  31. #include <dns/rdataclass.h>
  32. #include <dns/rrset.h>
  33. #include <dns/rrsetlist.h>
  34. #include <cc/data.h>
  35. #define RETERR(x) do { \
  36. DataSrc::Result r = (x); \
  37. if (r != DataSrc::SUCCESS) \
  38. return (r); \
  39. } while (0)
  40. using namespace std;
  41. using namespace isc::util;
  42. using namespace isc::util::encode;
  43. using namespace isc::util::hash;
  44. using namespace isc::dns;
  45. using namespace isc::dns::rdata;
  46. namespace {
  47. struct MatchRRsetForType {
  48. MatchRRsetForType(const RRType rrtype) : rrtype_(rrtype) {}
  49. bool operator()(RRsetPtr rrset) {
  50. return (rrset->getType() == rrtype_);
  51. }
  52. const RRType rrtype_;
  53. };
  54. // This is a helper to retrieve a specified RR type of RRset from RRsetList.
  55. // In our case the data source search logic should ensure that the class is
  56. // valid. We use this find logic of our own so that we can support both
  57. // specific RR class queries (normal case) and class ANY queries.
  58. RRsetPtr
  59. findRRsetFromList(RRsetList& list, const RRType rrtype) {
  60. RRsetList::iterator it(find_if(list.begin(), list.end(),
  61. MatchRRsetForType(rrtype)));
  62. return (it != list.end() ? *it : RRsetPtr());
  63. }
  64. }
  65. namespace isc {
  66. namespace datasrc {
  67. typedef boost::shared_ptr<const Nsec3Param> ConstNsec3ParamPtr;
  68. class ZoneInfo {
  69. public:
  70. ZoneInfo(DataSrc* ts,
  71. const isc::dns::Name& n,
  72. const isc::dns::RRClass& c,
  73. const isc::dns::RRType& t = isc::dns::RRType::ANY()) :
  74. top_source_(ts),
  75. dsm_(((t == RRType::DS() && n.getLabelCount() != 1)
  76. ? n.split(1, n.getLabelCount() - 1) : n),
  77. c)
  78. {}
  79. const Name* getEnclosingZone() {
  80. if (dsm_.getEnclosingZone() == NULL) {
  81. top_source_->findClosestEnclosure(dsm_);
  82. }
  83. return (dsm_.getEnclosingZone());
  84. }
  85. const DataSrc* getDataSource() {
  86. if (dsm_.getDataSource() == NULL) {
  87. top_source_->findClosestEnclosure(dsm_);
  88. }
  89. return (dsm_.getDataSource());
  90. }
  91. private:
  92. const DataSrc* top_source_;
  93. DataSrcMatch dsm_;
  94. };
  95. // Add a task to the query task queue to look up additional data
  96. // (i.e., address records for the names included in NS or MX records)
  97. void
  98. getAdditional(Query& q, ConstRRsetPtr rrset) {
  99. if (!q.wantAdditional()) {
  100. return;
  101. }
  102. RdataIteratorPtr it = rrset->getRdataIterator();
  103. for (; !it->isLast(); it->next()) {
  104. const Rdata& rd(it->getCurrent());
  105. if (rrset->getType() == RRType::NS()) {
  106. const generic::NS& ns = dynamic_cast<const generic::NS&>(rd);
  107. if (logger.isDebugEnabled(DBG_TRACE_DATA)) {
  108. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_GET_NS_ADDITIONAL,
  109. ns.getNSName().toText().c_str(),
  110. rrset->getName().toText().c_str());
  111. }
  112. q.tasks().push(QueryTaskPtr(
  113. new QueryTask(q, ns.getNSName(),
  114. Message::SECTION_ADDITIONAL,
  115. QueryTask::GLUE_QUERY,
  116. QueryTask::GETADDITIONAL)));
  117. } else if (rrset->getType() == RRType::MX()) {
  118. const generic::MX& mx = dynamic_cast<const generic::MX&>(rd);
  119. if (logger.isDebugEnabled(DBG_TRACE_DATA)) {
  120. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_GET_MX_ADDITIONAL,
  121. mx.getMXName().toText().c_str(),
  122. rrset->getName().toText().c_str());
  123. }
  124. q.tasks().push(QueryTaskPtr(
  125. new QueryTask(q, mx.getMXName(),
  126. Message::SECTION_ADDITIONAL,
  127. QueryTask::NOGLUE_QUERY,
  128. QueryTask::GETADDITIONAL)));
  129. }
  130. }
  131. }
  132. // Synthesize a CNAME answer, for the benefit of clients that don't
  133. // understand DNAME
  134. void
  135. synthesizeCname(QueryTaskPtr task, RRsetPtr rrset, RRsetList& target) {
  136. if (logger.isDebugEnabled(DBG_TRACE_DATA)) {
  137. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_SYNTH_CNAME,
  138. rrset->getName().toText().c_str());
  139. }
  140. RdataIteratorPtr it = rrset->getRdataIterator();
  141. // More than one DNAME RR in the RRset is illegal, so we only have
  142. // to process the first one.
  143. if (it->isLast()) {
  144. logger.error(DATASRC_QUERY_EMPTY_DNAME,
  145. rrset->getName().toText().c_str());
  146. return;
  147. }
  148. const Rdata& rd(it->getCurrent());
  149. const generic::DNAME& dname = dynamic_cast<const generic::DNAME&>(rd);
  150. const Name& dname_target(dname.getDname());
  151. RRsetPtr cname(new RRset(task->qname, rrset->getClass(), RRType::CNAME(),
  152. rrset->getTTL()));
  153. const int qnlen = task->qname.getLabelCount();
  154. const int dnlen = rrset->getName().getLabelCount();
  155. assert(qnlen > dnlen);
  156. const Name& prefix(task->qname.split(0, qnlen - dnlen));
  157. cname->addRdata(generic::CNAME(prefix.concatenate(dname_target)));
  158. target.addRRset(cname);
  159. }
  160. // Add a task to the query task queue to look up the data pointed
  161. // to by a CNAME record
  162. void
  163. chaseCname(Query& q, QueryTaskPtr task, RRsetPtr rrset) {
  164. if (logger.isDebugEnabled(DBG_TRACE_DATA)) {
  165. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_FOLLOW_CNAME,
  166. rrset->getName().toText().c_str());
  167. }
  168. RdataIteratorPtr it = rrset->getRdataIterator();
  169. // More than one CNAME RR in the RRset is illegal, so we only have
  170. // to process the first one.
  171. if (it->isLast()) {
  172. logger.error(DATASRC_QUERY_EMPTY_CNAME,
  173. rrset->getName().toText().c_str());
  174. return;
  175. }
  176. // Stop chasing CNAMES after 16 lookups, to prevent loops
  177. if (q.tooMany()) {
  178. logger.error(DATASRC_QUERY_TOO_MANY_CNAMES,
  179. rrset->getName().toText().c_str());
  180. return;
  181. }
  182. q.tasks().push(QueryTaskPtr(
  183. new QueryTask(q, dynamic_cast<const generic::CNAME&>
  184. (it->getCurrent()).getCname(),
  185. task->qtype, Message::SECTION_ANSWER,
  186. QueryTask::FOLLOWCNAME)));
  187. }
  188. // Check the cache for data which can answer the current query task.
  189. bool
  190. checkCache(QueryTask& task, RRsetList& target) {
  191. if (logger.isDebugEnabled(DBG_TRACE_DATA)) {
  192. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_CHECK_CACHE,
  193. task.qname.toText().c_str(), task.qtype.toText().c_str());
  194. }
  195. HotCache& cache = task.q.getCache();
  196. RRsetList rrsets;
  197. RRsetPtr rrset;
  198. int count = 0;
  199. uint32_t flags = 0, cflags = 0;
  200. bool hit = false, found = false;
  201. switch (task.op) {
  202. case QueryTask::SIMPLE_QUERY: // Find exact RRset
  203. // ANY queries must be handled by the low-level data source,
  204. // or the results won't be guaranteed to be complete
  205. if (task.qtype == RRType::ANY() || task.qclass == RRClass::ANY()) {
  206. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_NO_CACHE_ANY_SIMPLE);
  207. break;
  208. }
  209. hit = cache.retrieve(task.qname, task.qclass, task.qtype, rrset, flags);
  210. if (hit) {
  211. if (rrset) {
  212. rrsets.addRRset(rrset);
  213. target.append(rrsets);
  214. }
  215. // Reset the referral flag and treat CNAME as "not found".
  216. // This emulates the behavior of the sqlite3 data source.
  217. // XXX: this is not ideal in that the responsibility for handling
  218. // operation specific cases is spread over various classes at
  219. // different abstraction levels. For longer terms we should
  220. // revisit the whole datasource/query design, and clarify this
  221. // point better.
  222. flags &= ~DataSrc::REFERRAL;
  223. if ((flags & DataSrc::CNAME_FOUND) != 0) {
  224. flags &= ~DataSrc::CNAME_FOUND;
  225. flags |= DataSrc::TYPE_NOT_FOUND;
  226. }
  227. task.flags = flags;
  228. return (true);
  229. }
  230. break;
  231. case QueryTask::AUTH_QUERY: // Find exact RRset or CNAME
  232. if (task.qtype == RRType::ANY() || task.qclass == RRClass::ANY()) {
  233. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_NO_CACHE_ANY_AUTH);
  234. break;
  235. }
  236. hit = cache.retrieve(task.qname, task.qclass, task.qtype, rrset, flags);
  237. if (!hit || !rrset || (flags & DataSrc::CNAME_FOUND) != 0) {
  238. hit = cache.retrieve(task.qname, task.qclass, RRType::CNAME(),
  239. rrset, flags);
  240. if (!rrset) {
  241. // If we don't have a positive cache, forget it; otherwise the
  242. // intermediate result may confuse the subsequent processing.
  243. hit = false;
  244. }
  245. }
  246. if (hit) {
  247. if (rrset) {
  248. rrsets.addRRset(rrset);
  249. target.append(rrsets);
  250. }
  251. task.flags = flags;
  252. return (true);
  253. }
  254. break;
  255. case QueryTask::GLUE_QUERY: // Find addresses
  256. case QueryTask::NOGLUE_QUERY:
  257. // (XXX: need to figure out how to deal with noglue case)
  258. flags = 0;
  259. hit = cache.retrieve(task.qname, task.qclass, RRType::A(),
  260. rrset, cflags);
  261. if (hit) {
  262. flags |= cflags;
  263. ++count;
  264. if (rrset) {
  265. rrsets.addRRset(rrset);
  266. found = true;
  267. }
  268. }
  269. hit = cache.retrieve(task.qname, task.qclass, RRType::AAAA(),
  270. rrset, flags);
  271. if (hit) {
  272. flags |= cflags;
  273. ++count;
  274. if (rrset) {
  275. rrsets.addRRset(rrset);
  276. found = true;
  277. }
  278. }
  279. if (count == 2) {
  280. if (found) {
  281. flags &= ~DataSrc::TYPE_NOT_FOUND;
  282. target.append(rrsets);
  283. }
  284. task.flags = flags;
  285. return (true);
  286. }
  287. break;
  288. case QueryTask::REF_QUERY: // Find NS, DS and/or DNAME
  289. flags = count = 0;
  290. hit = cache.retrieve(task.qname, task.qclass, RRType::NS(),
  291. rrset, cflags);
  292. if (hit) {
  293. flags |= cflags;
  294. ++count;
  295. if (rrset) {
  296. rrsets.addRRset(rrset);
  297. found = true;
  298. }
  299. }
  300. hit = cache.retrieve(task.qname, task.qclass, RRType::DS(),
  301. rrset, flags);
  302. if (hit) {
  303. flags |= cflags;
  304. ++count;
  305. if (rrset) {
  306. rrsets.addRRset(rrset);
  307. found = true;
  308. }
  309. }
  310. hit = cache.retrieve(task.qname, task.qclass, RRType::DNAME(),
  311. rrset, flags);
  312. if (hit) {
  313. flags |= cflags;
  314. ++count;
  315. if (rrset) {
  316. rrsets.addRRset(rrset);
  317. found = true;
  318. }
  319. }
  320. if (count == 3) {
  321. if (found) {
  322. flags &= ~DataSrc::TYPE_NOT_FOUND;
  323. flags &= DataSrc::REFERRAL;
  324. target.append(rrsets);
  325. }
  326. task.flags = flags;
  327. return (true);
  328. }
  329. break;
  330. }
  331. return (false);
  332. }
  333. // Carry out the query specified in a QueryTask object
  334. DataSrc::Result
  335. doQueryTask(QueryTask& task, ZoneInfo& zoneinfo, RRsetList& target) {
  336. HotCache& cache = task.q.getCache();
  337. RRsetPtr rrset;
  338. if (logger.isDebugEnabled(DBG_TRACE_DATA)) {
  339. logger.debug(DBG_TRACE_DATA, DATASRC_DO_QUERY,
  340. task.qname.toText().c_str(), task.qtype.toText().c_str());
  341. }
  342. // First off, make sure at least we have a matching zone in some data
  343. // source. We must do this before checking the cache, because it can
  344. // happen that the matching zone has been removed after an RRset of that
  345. // zone is cached. Such inconsistency will cause various problems,
  346. // including a crash.
  347. const DataSrc* ds = zoneinfo.getDataSource();
  348. const Name* const zonename = zoneinfo.getEnclosingZone();
  349. if (ds == NULL) {
  350. task.flags |= DataSrc::NO_SUCH_ZONE;
  351. if (logger.isInfoEnabled()) {
  352. logger.info(DATASRC_QUERY_NO_ZONE, task.qname.toText().c_str(),
  353. task.qclass.toText().c_str());
  354. }
  355. return (DataSrc::SUCCESS);
  356. }
  357. // Then check the cache for matching data
  358. if (checkCache(task, target)) {
  359. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_CACHED);
  360. return (DataSrc::SUCCESS);
  361. }
  362. // Requested data weren't in the cache (or were, but had expired),
  363. // so now we proceed with the low-level data source lookup, and cache
  364. // whatever we find.
  365. DataSrc::Result result;
  366. switch (task.op) {
  367. case QueryTask::SIMPLE_QUERY:
  368. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_IS_SIMPLE);
  369. result = ds->findExactRRset(task.qname, task.qclass, task.qtype,
  370. target, task.flags, zonename);
  371. if (result != DataSrc::SUCCESS) {
  372. logger.error(DATASRC_QUERY_SIMPLE_FAIL, unsigned(result));
  373. return (result);
  374. }
  375. if (task.qclass == RRClass::ANY()) {
  376. // XXX: Currently, RRsetList::findRRset() doesn't handle
  377. // ANY queries, and without that we can't cache the results,
  378. // so we just return in that case.
  379. return (result);
  380. }
  381. if (task.flags == 0) {
  382. rrset = target.findRRset(task.qtype, task.qclass);
  383. assert(rrset);
  384. cache.addPositive(rrset, task.flags);
  385. } else {
  386. cache.addNegative(task.qname, task.qclass, task.qtype, task.flags);
  387. }
  388. return (result);
  389. case QueryTask::AUTH_QUERY:
  390. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_IS_AUTH);
  391. result = ds->findRRset(task.qname, task.qclass, task.qtype,
  392. target, task.flags, zonename);
  393. if (result != DataSrc::SUCCESS) {
  394. logger.error(DATASRC_QUERY_AUTH_FAIL, unsigned(result));
  395. return (result);
  396. }
  397. if (task.qclass == RRClass::ANY()) {
  398. return (result);
  399. }
  400. if (task.qtype == RRType::ANY()) {
  401. BOOST_FOREACH(RRsetPtr rr, target) {
  402. cache.addPositive(rr, task.flags);
  403. }
  404. } else if ((task.flags & DataSrc::CNAME_FOUND) != 0) {
  405. cache.addNegative(task.qname, task.qclass, task.qtype, task.flags);
  406. rrset = target.findRRset(RRType::CNAME(), task.qclass);
  407. assert(rrset);
  408. cache.addPositive(rrset, task.flags);
  409. } else if ((task.flags & DataSrc::DATA_NOT_FOUND) == 0) {
  410. if (task.qtype != RRType::CNAME()) {
  411. cache.addNegative(task.qname, task.qclass, RRType::CNAME(),
  412. task.flags);
  413. }
  414. rrset = target.findRRset(task.qtype, task.qclass);
  415. assert(rrset);
  416. cache.addPositive(rrset, task.flags);
  417. } else {
  418. cache.addNegative(task.qname, task.qclass, task.qtype, task.flags);
  419. }
  420. return (result);
  421. case QueryTask::GLUE_QUERY:
  422. case QueryTask::NOGLUE_QUERY:
  423. logger.debug(DBG_TRACE_DATA, task.op == QueryTask::GLUE_QUERY ?
  424. DATASRC_QUERY_IS_GLUE : DATASRC_QUERY_IS_NOGLUE);
  425. result = ds->findAddrs(task.qname, task.qclass, target,
  426. task.flags, zonename);
  427. if (result != DataSrc::SUCCESS) {
  428. logger.error(task.op == QueryTask::GLUE_QUERY ?
  429. DATASRC_QUERY_GLUE_FAIL : DATASRC_QUERY_NOGLUE_FAIL,
  430. unsigned(result));
  431. return (result);
  432. }
  433. if (task.qclass == RRClass::ANY()) {
  434. return (result);
  435. }
  436. rrset = target.findRRset(RRType::A(), task.qclass);
  437. if (rrset) {
  438. cache.addPositive(rrset, task.flags);
  439. } else {
  440. cache.addNegative(task.qname, task.qclass, RRType::A(), task.flags);
  441. }
  442. rrset = target.findRRset(RRType::AAAA(), task.qclass);
  443. if (rrset) {
  444. cache.addPositive(rrset, task.flags);
  445. } else {
  446. cache.addNegative(task.qname, task.qclass, RRType::AAAA(),
  447. task.flags);
  448. }
  449. return (result);
  450. case QueryTask::REF_QUERY:
  451. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_IS_REF);
  452. result = ds->findReferral(task.qname, task.qclass, target,
  453. task.flags, zonename);
  454. if (result != DataSrc::SUCCESS) {
  455. logger.error(DATASRC_QUERY_REF_FAIL, unsigned(result));
  456. return (result);
  457. }
  458. if (task.qclass == RRClass::ANY()) {
  459. return (result);
  460. }
  461. rrset = target.findRRset(RRType::NS(), task.qclass);
  462. if (rrset) {
  463. cache.addPositive(rrset, task.flags);
  464. } else {
  465. cache.addNegative(task.qname, task.qclass, RRType::NS(),
  466. task.flags);
  467. }
  468. rrset = target.findRRset(RRType::DS(), task.qclass);
  469. if (rrset) {
  470. cache.addPositive(rrset, task.flags);
  471. } else {
  472. cache.addNegative(task.qname, task.qclass, RRType::DS(),
  473. task.flags);
  474. }
  475. rrset = target.findRRset(RRType::DNAME(), task.qclass);
  476. if (rrset) {
  477. cache.addPositive(rrset, task.flags);
  478. } else {
  479. cache.addNegative(task.qname, task.qclass, RRType::DNAME(),
  480. task.flags);
  481. }
  482. return (result);
  483. }
  484. // Not reached
  485. logger.error(DATASRC_QUERY_INVALID_OP);
  486. return (DataSrc::ERROR);
  487. }
  488. // Add an RRset (and its associated RRSIG) to a message section,
  489. // checking first to ensure that there isn't already an RRset with
  490. // the same name and type.
  491. inline void
  492. addToMessage(Query& q, const Message::Section sect, RRsetPtr rrset,
  493. bool no_dnssec = false)
  494. {
  495. if (logger.isDebugEnabled(DBG_TRACE_DATA)) {
  496. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_ADD_RRSET,
  497. rrset->getName().toText().c_str(),
  498. rrset->getType().toText().c_str());
  499. }
  500. Message& m = q.message();
  501. if (no_dnssec) {
  502. if (rrset->getType() == RRType::RRSIG() ||
  503. !m.hasRRset(sect, rrset->getName(), rrset->getClass(),
  504. rrset->getType())) {
  505. m.addRRset(sect, rrset, false);
  506. }
  507. } else {
  508. if (!m.hasRRset(sect, rrset->getName(), rrset->getClass(),
  509. rrset->getType())) {
  510. m.addRRset(sect, rrset, q.wantDnssec());
  511. }
  512. }
  513. }
  514. // Copy referral information into the authority section of a message
  515. inline void
  516. copyAuth(Query& q, RRsetList& auth) {
  517. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_COPY_AUTH);
  518. BOOST_FOREACH(RRsetPtr rrset, auth) {
  519. if (rrset->getType() == RRType::DNAME()) {
  520. continue;
  521. }
  522. if (rrset->getType() == RRType::DS() && !q.wantDnssec()) {
  523. continue;
  524. }
  525. addToMessage(q, Message::SECTION_AUTHORITY, rrset);
  526. getAdditional(q, rrset);
  527. }
  528. }
  529. // Query for referrals (i.e., NS/DS or DNAME) at a given name
  530. inline bool
  531. refQuery(const Query& q, const Name& name, ZoneInfo& zoneinfo,
  532. RRsetList& target)
  533. {
  534. QueryTask newtask(q, name, QueryTask::REF_QUERY);
  535. if (doQueryTask(newtask, zoneinfo, target) != DataSrc::SUCCESS) {
  536. // Lookup failed
  537. return (false);
  538. }
  539. // Referral bit is expected, so clear it when checking flags
  540. if ((newtask.flags & ~DataSrc::REFERRAL) != 0) {
  541. return (false);
  542. }
  543. return (true);
  544. }
  545. // Match downward, from the zone apex to the query name, looking for
  546. // referrals. Note that we exclude the apex name and query name themselves;
  547. // they'll be handled in a normal lookup in the zone.
  548. inline bool
  549. hasDelegation(Query& q, QueryTaskPtr task, ZoneInfo& zoneinfo) {
  550. if (logger.isDebugEnabled(DBG_TRACE_DATA)) {
  551. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_DELEGATION,
  552. task->qname.toText().c_str());
  553. }
  554. const Name* const zonename = zoneinfo.getEnclosingZone();
  555. if (zonename == NULL) {
  556. if (task->state == QueryTask::GETANSWER) {
  557. q.message().setRcode(Rcode::REFUSED());
  558. }
  559. return (false);
  560. }
  561. const int diff = task->qname.getLabelCount() - zonename->getLabelCount();
  562. if (diff > 1) {
  563. bool found = false;
  564. RRsetList ref;
  565. for (int i = diff - 1; i > 0; --i) {
  566. const Name sub(task->qname.split(i));
  567. if (refQuery(q, sub, zoneinfo, ref)) {
  568. found = true;
  569. break;
  570. }
  571. }
  572. // Found a referral while getting additional data
  573. // for something other than NS; we skip it.
  574. if (found && task->op == QueryTask::NOGLUE_QUERY) {
  575. return (true);
  576. }
  577. // Found a referral while getting answer data;
  578. // send a delegation.
  579. if (found) {
  580. RRsetPtr r = findRRsetFromList(ref, RRType::DNAME());
  581. if (r != NULL) {
  582. RRsetList syn;
  583. addToMessage(q, Message::SECTION_ANSWER, r);
  584. q.message().setHeaderFlag(Message::HEADERFLAG_AA);
  585. synthesizeCname(task, r, syn);
  586. if (syn.size() == 1) {
  587. RRsetPtr cname_rrset = findRRsetFromList(syn,
  588. RRType::CNAME());
  589. addToMessage(q, Message::SECTION_ANSWER, cname_rrset);
  590. chaseCname(q, task, cname_rrset);
  591. return (true);
  592. }
  593. }
  594. copyAuth(q, ref);
  595. return (true);
  596. }
  597. }
  598. // We appear to have authoritative data; set the header
  599. // flag. (We may clear it later if we find a referral
  600. // at the actual qname node.)
  601. if (task->op == QueryTask::AUTH_QUERY &&
  602. task->state == QueryTask::GETANSWER) {
  603. q.message().setHeaderFlag(Message::HEADERFLAG_AA);
  604. }
  605. return (false);
  606. }
  607. inline DataSrc::Result
  608. addSOA(Query& q, ZoneInfo& zoneinfo) {
  609. RRsetList soa;
  610. const Name* const zonename = zoneinfo.getEnclosingZone();
  611. if (logger.isDebugEnabled(DBG_TRACE_DATA)) {
  612. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_ADD_SOA,
  613. zonename->toText().c_str());
  614. }
  615. QueryTask newtask(q, *zonename, RRType::SOA(), QueryTask::SIMPLE_QUERY);
  616. RETERR(doQueryTask(newtask, zoneinfo, soa));
  617. if (newtask.flags != 0) {
  618. return (DataSrc::ERROR);
  619. }
  620. addToMessage(q, Message::SECTION_AUTHORITY,
  621. findRRsetFromList(soa, RRType::SOA()));
  622. return (DataSrc::SUCCESS);
  623. }
  624. inline DataSrc::Result
  625. addNSEC(Query& q, const Name& name, ZoneInfo& zoneinfo) {
  626. if (logger.isDebugEnabled(DBG_TRACE_DATA)) {
  627. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_ADD_NSEC,
  628. name.toText().c_str());
  629. }
  630. RRsetList nsec;
  631. QueryTask newtask(q, name, RRType::NSEC(), QueryTask::SIMPLE_QUERY);
  632. RETERR(doQueryTask(newtask, zoneinfo, nsec));
  633. if (newtask.flags == 0) {
  634. addToMessage(q, Message::SECTION_AUTHORITY,
  635. findRRsetFromList(nsec, RRType::NSEC()));
  636. }
  637. return (DataSrc::SUCCESS);
  638. }
  639. inline DataSrc::Result
  640. getNsec3(Query& q, ZoneInfo& zoneinfo, string& hash, RRsetPtr& target) {
  641. const DataSrc* ds = zoneinfo.getDataSource();
  642. const Name* const zonename = zoneinfo.getEnclosingZone();
  643. if (logger.isDebugEnabled(DBG_TRACE_DATA)) {
  644. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_ADD_NSEC3,
  645. zonename->toText().c_str());
  646. }
  647. if (ds == NULL) {
  648. q.message().setRcode(Rcode::SERVFAIL());
  649. logger.error(DATASRC_QUERY_NO_DS_NSEC3, zonename->toText().c_str());
  650. return (DataSrc::ERROR);
  651. }
  652. RRsetList rl;
  653. RETERR(ds->findCoveringNSEC3(*zonename, hash, rl));
  654. target = rl.findRRset(RRType::NSEC3(), q.qclass());
  655. return (DataSrc::SUCCESS);
  656. }
  657. ConstNsec3ParamPtr
  658. getNsec3Param(Query& q, ZoneInfo& zoneinfo) {
  659. DataSrc::Result result;
  660. RRsetList nsec3param;
  661. const Name* const zonename = zoneinfo.getEnclosingZone();
  662. QueryTask newtask(q, *zonename, RRType::NSEC3PARAM(),
  663. QueryTask::SIMPLE_QUERY);
  664. result = doQueryTask(newtask, zoneinfo, nsec3param);
  665. newtask.flags &= ~DataSrc::REFERRAL;
  666. if (result != DataSrc::SUCCESS || newtask.flags != 0) {
  667. return (ConstNsec3ParamPtr());
  668. }
  669. RRsetPtr rrset = nsec3param.findRRset(RRType::NSEC3PARAM(), q.qclass());
  670. if (!rrset) {
  671. return (ConstNsec3ParamPtr());
  672. }
  673. // XXX: currently only one NSEC3 chain per zone is supported;
  674. // we will need to revisit this.
  675. RdataIteratorPtr it = rrset->getRdataIterator();
  676. if (it->isLast()) {
  677. return (ConstNsec3ParamPtr());
  678. }
  679. const generic::NSEC3PARAM& np =
  680. dynamic_cast<const generic::NSEC3PARAM&>(it->getCurrent());
  681. return (ConstNsec3ParamPtr(new Nsec3Param(np.getHashalg(), np.getFlags(),
  682. np.getIterations(),
  683. np.getSalt())));
  684. }
  685. inline DataSrc::Result
  686. proveNX(Query& q, QueryTaskPtr task, ZoneInfo& zoneinfo, const bool wildcard) {
  687. Message& m = q.message();
  688. const Name* const zonename = zoneinfo.getEnclosingZone();
  689. ConstNsec3ParamPtr nsec3 = getNsec3Param(q, zoneinfo);
  690. if (nsec3 != NULL) {
  691. // Attach the NSEC3 record covering the QNAME
  692. RRsetPtr rrset;
  693. string hash1(nsec3->getHash(task->qname));
  694. RETERR(getNsec3(q, zoneinfo, hash1, rrset));
  695. addToMessage(q, Message::SECTION_AUTHORITY, rrset);
  696. // If this is an NXRRSET or NOERROR/NODATA, we're done
  697. if ((task->flags & DataSrc::TYPE_NOT_FOUND) != 0) {
  698. return (DataSrc::SUCCESS);
  699. }
  700. // Find the closest provable enclosing name for QNAME
  701. Name enclosure(*zonename);
  702. const int diff = task->qname.getLabelCount() -
  703. enclosure.getLabelCount();
  704. string hash2;
  705. for (int i = 1; i <= diff; ++i) {
  706. enclosure = task->qname.split(i);
  707. string nodehash(nsec3->getHash(enclosure));
  708. if (nodehash == hash1) {
  709. break;
  710. }
  711. hash2 = nodehash;
  712. RRsetList rl;
  713. // hash2 will be overwritten with the actual hash found;
  714. // we don't want to use one until we find an exact match
  715. RETERR(getNsec3(q, zoneinfo, hash2, rrset));
  716. if (hash2 == nodehash) {
  717. addToMessage(q, Message::SECTION_AUTHORITY, rrset);
  718. break;
  719. }
  720. }
  721. // If we are processing a wildcard answer, we're done.
  722. if (wildcard) {
  723. return (DataSrc::SUCCESS);
  724. }
  725. // Otherwise, there is no wildcard record, so we must add a
  726. // covering NSEC3 to prove that it doesn't exist.
  727. string hash3(nsec3->getHash(Name("*").concatenate(enclosure)));
  728. RETERR(getNsec3(q, zoneinfo, hash3, rrset));
  729. if (hash3 != hash1 && hash3 != hash2) {
  730. addToMessage(q, Message::SECTION_AUTHORITY, rrset);
  731. }
  732. } else {
  733. Name nsecname(task->qname);
  734. if ((task->flags & DataSrc::NAME_NOT_FOUND) != 0 || wildcard) {
  735. const DataSrc* ds = zoneinfo.getDataSource();
  736. if (ds == NULL) {
  737. m.setRcode(Rcode::SERVFAIL());
  738. logger.error(DATASRC_QUERY_NO_DS_NSEC,
  739. zonename->toText().c_str());
  740. return (DataSrc::ERROR);
  741. }
  742. ds->findPreviousName(task->qname, nsecname, zonename);
  743. }
  744. RETERR(addNSEC(q, nsecname, zoneinfo));
  745. if ((task->flags & DataSrc::TYPE_NOT_FOUND) != 0 ||
  746. nsecname == *zonename)
  747. {
  748. return (DataSrc::SUCCESS);
  749. }
  750. // If we are processing a wildcard answer, we're done.
  751. if (wildcard) {
  752. return (DataSrc::SUCCESS);
  753. }
  754. // Otherwise, there is no wildcard record, so we must add an
  755. // NSEC for the zone to prove the wildcard doesn't exist.
  756. RETERR(addNSEC(q, *zonename, zoneinfo));
  757. }
  758. return (DataSrc::SUCCESS);
  759. }
  760. // Attempt a wildcard lookup
  761. inline DataSrc::Result
  762. tryWildcard(Query& q, QueryTaskPtr task, ZoneInfo& zoneinfo, bool& found) {
  763. if (logger.isDebugEnabled(DBG_TRACE_DATA)) {
  764. logger.debug(DBG_TRACE_DATA, DATASRC_QUERY_WILDCARD,
  765. task->qname.toText().c_str());
  766. }
  767. Message& m = q.message();
  768. DataSrc::Result result;
  769. found = false;
  770. if ((task->flags & DataSrc::NAME_NOT_FOUND) == 0 ||
  771. (task->state != QueryTask::GETANSWER &&
  772. task->state != QueryTask::FOLLOWCNAME)) {
  773. return (DataSrc::SUCCESS);
  774. }
  775. const Name* const zonename = zoneinfo.getEnclosingZone();
  776. const int diff = task->qname.getLabelCount() - zonename->getLabelCount();
  777. if (diff < 1) {
  778. return (DataSrc::SUCCESS);
  779. }
  780. RRsetList wild;
  781. const Name star("*");
  782. bool cname = false;
  783. for (int i = 1; i <= diff; ++i) {
  784. const Name& wname(star.concatenate(task->qname.split(i)));
  785. QueryTask newtask(q, wname, task->qtype, Message::SECTION_ANSWER,
  786. QueryTask::AUTH_QUERY);
  787. result = doQueryTask(newtask, zoneinfo, wild);
  788. if (result == DataSrc::SUCCESS) {
  789. if (newtask.flags == 0) {
  790. task->flags &= ~DataSrc::NAME_NOT_FOUND;
  791. task->flags &= ~DataSrc::TYPE_NOT_FOUND;
  792. found = true;
  793. break;
  794. } else if ((newtask.flags & DataSrc::CNAME_FOUND) != 0) {
  795. task->flags &= ~DataSrc::NAME_NOT_FOUND;
  796. task->flags &= ~DataSrc::TYPE_NOT_FOUND;
  797. task->flags |= DataSrc::CNAME_FOUND;
  798. found = true;
  799. cname = true;
  800. break;
  801. } else if ((newtask.flags & DataSrc::TYPE_NOT_FOUND) != 0) {
  802. task->flags &= ~DataSrc::NAME_NOT_FOUND;
  803. task->flags |= DataSrc::TYPE_NOT_FOUND;
  804. break;
  805. }
  806. }
  807. }
  808. // A wildcard was found.
  809. if (found) {
  810. // Prove the nonexistence of the name we were looking for
  811. if (q.wantDnssec()) {
  812. result = proveNX(q, task, zoneinfo, true);
  813. if (result != DataSrc::SUCCESS) {
  814. m.setRcode(Rcode::SERVFAIL());
  815. logger.error(DATASRC_QUERY_WILDCARD_PROVENX_FAIL,
  816. task->qname.toText().c_str(),
  817. unsigned(result));
  818. return (DataSrc::ERROR);
  819. }
  820. }
  821. // Add the data to the answer section (but with the name changed to
  822. // match the qname), and then continue as if this were a normal
  823. // answer: if a CNAME, chase the target, otherwise add authority.
  824. if (cname) {
  825. RRsetPtr rrset = findRRsetFromList(wild, RRType::CNAME());
  826. if (rrset != NULL) {
  827. rrset->setName(task->qname);
  828. addToMessage(q, Message::SECTION_ANSWER, rrset);
  829. chaseCname(q, task, rrset);
  830. }
  831. } else {
  832. BOOST_FOREACH (RRsetPtr rrset, wild) {
  833. rrset->setName(task->qname);
  834. addToMessage(q, Message::SECTION_ANSWER, rrset);
  835. }
  836. RRsetList auth;
  837. if (!refQuery(q, *zonename, zoneinfo, auth)) {
  838. logger.error(DATASRC_QUERY_WILDCARD_REFERRAL,
  839. task->qname.toText().c_str(),
  840. unsigned(result));
  841. return (DataSrc::ERROR);
  842. }
  843. copyAuth(q, auth);
  844. }
  845. }
  846. return (DataSrc::SUCCESS);
  847. }
  848. //
  849. // doQuery: Processes a query.
  850. //
  851. void
  852. DataSrc::doQuery(Query& q) {
  853. if (logger.isDebugEnabled(DBG_TRACE_BASIC)) {
  854. logger.debug(DBG_TRACE_BASIC, DATASRC_QUERY_PROCESS,
  855. q.qname().toText().c_str(), q.qtype().toText().c_str(),
  856. q.qclass().toText().c_str());
  857. }
  858. Message& m = q.message();
  859. vector<RRsetPtr> additional;
  860. // Record the fact that the query is being processed by the
  861. // current data source.
  862. q.setDatasrc(this);
  863. // Process the query task queue. (The queue is initialized
  864. // and the first task placed on it by the Query constructor.)
  865. m.setHeaderFlag(Message::HEADERFLAG_AA, false);
  866. while (!q.tasks().empty()) {
  867. QueryTaskPtr task = q.tasks().front();
  868. q.tasks().pop();
  869. // Can't query directly for RRSIG.
  870. if (task->qtype == RRType::RRSIG()) {
  871. m.setRcode(Rcode::REFUSED());
  872. if (logger.isWarnEnabled()) {
  873. logger.warn(DATASRC_QUERY_RRSIG, task->qname.toText().c_str());
  874. }
  875. return;
  876. }
  877. // These task types should never be on the task queue.
  878. if (task->op == QueryTask::SIMPLE_QUERY ||
  879. task->op == QueryTask::REF_QUERY) {
  880. m.setRcode(Rcode::SERVFAIL());
  881. logger.error(DATASRC_QUERY_MISPLACED_TASK);
  882. return;
  883. }
  884. ZoneInfo zoneinfo(this, task->qname, task->qclass, task->qtype);
  885. RRsetList data;
  886. Result result = SUCCESS;
  887. // For these query task types, if there is more than
  888. // one level between the zone name and qname, we need to
  889. // check the intermediate nodes for referrals.
  890. if ((task->op == QueryTask::AUTH_QUERY ||
  891. task->op == QueryTask::NOGLUE_QUERY) &&
  892. hasDelegation(q, task, zoneinfo)) {
  893. continue;
  894. }
  895. result = doQueryTask(*task, zoneinfo, data);
  896. if (result != SUCCESS) {
  897. m.setRcode(Rcode::SERVFAIL());
  898. logger.error(DATASRC_QUERY_TASK_FAIL, unsigned(result));
  899. return;
  900. }
  901. // No such zone. If we're chasing cnames or adding additional
  902. // data, that's okay, but if doing an original query, return
  903. // REFUSED.
  904. if (task->flags == NO_SUCH_ZONE) {
  905. if (task->state == QueryTask::GETANSWER) {
  906. m.setRcode(Rcode::REFUSED());
  907. // No need to log it here, it was already logged in doQueryTask
  908. return;
  909. }
  910. continue;
  911. }
  912. // Query found a referral; let's find out if that was expected--
  913. // i.e., if an NS was at the zone apex, or if we were querying
  914. // specifically for, and found, a DS, NSEC, or DNAME record.
  915. const Name* const zonename = zoneinfo.getEnclosingZone();
  916. if ((task->flags & REFERRAL) != 0 &&
  917. (zonename->getLabelCount() == task->qname.getLabelCount() ||
  918. ((task->qtype == RRType::NSEC() ||
  919. task->qtype == RRType::DS() ||
  920. task->qtype == RRType::DNAME()) &&
  921. findRRsetFromList(data, task->qtype)))) {
  922. task->flags &= ~REFERRAL;
  923. }
  924. if (result == SUCCESS && task->flags == 0) {
  925. bool have_ns = false, need_auth = false;
  926. switch (task->state) {
  927. case QueryTask::GETANSWER:
  928. case QueryTask::FOLLOWCNAME:
  929. BOOST_FOREACH(RRsetPtr rrset, data) {
  930. addToMessage(q, task->section, rrset);
  931. if (q.tasks().empty()) {
  932. need_auth = true;
  933. }
  934. getAdditional(q, rrset);
  935. if (rrset->getType() == RRType::NS()) {
  936. have_ns = true;
  937. }
  938. }
  939. q.setStatus(Query::ANSWERED);
  940. if (need_auth && !have_ns) {
  941. // Data found, no additional processing needed.
  942. // Add the NS records for the enclosing zone to
  943. // the authority section.
  944. RRsetList auth;
  945. if (!refQuery(q, Name(*zonename), zoneinfo, auth) ||
  946. !findRRsetFromList(auth, RRType::NS())) {
  947. logger.error(DATASRC_QUERY_MISSING_NS,
  948. zonename->toText().c_str());
  949. isc_throw(DataSourceError,
  950. "NS RR not found in " << *zonename << "/" <<
  951. q.qclass());
  952. }
  953. copyAuth(q, auth);
  954. }
  955. continue;
  956. case QueryTask::GETADDITIONAL:
  957. // Got additional data. Do not add it to the message
  958. // yet; instead store it and copy it in at the end
  959. // (this allow RRSIGs to be omitted if necessary).
  960. BOOST_FOREACH(RRsetPtr rrset, data) {
  961. if (q.status() == Query::ANSWERED &&
  962. rrset->getName() == q.qname() &&
  963. rrset->getType() == q.qtype()) {
  964. continue;
  965. }
  966. additional.push_back(rrset);
  967. }
  968. continue;
  969. default:
  970. logger.error(DATASRC_UNEXPECTED_QUERY_STATE);
  971. isc_throw (Unexpected, "unexpected query state");
  972. }
  973. } else if (result == ERROR || result == NOT_IMPLEMENTED) {
  974. m.setRcode(Rcode::SERVFAIL());
  975. logger.error(DATASRC_QUERY_FAIL);
  976. return;
  977. } else if ((task->flags & CNAME_FOUND) != 0) {
  978. // The qname node contains a CNAME. Add a new task to the
  979. // queue to look up its target.
  980. RRsetPtr rrset = findRRsetFromList(data, RRType::CNAME());
  981. if (rrset != NULL) {
  982. addToMessage(q, task->section, rrset);
  983. chaseCname(q, task, rrset);
  984. }
  985. continue;
  986. } else if ((task->flags & REFERRAL) != 0) {
  987. // The qname node contains an out-of-zone referral.
  988. if (task->state == QueryTask::GETANSWER) {
  989. RRsetList auth;
  990. m.setHeaderFlag(Message::HEADERFLAG_AA, false);
  991. if (!refQuery(q, task->qname, zoneinfo, auth)) {
  992. m.setRcode(Rcode::SERVFAIL());
  993. logger.error(DATASRC_QUERY_BAD_REFERRAL,
  994. task->qname.toText().c_str());
  995. return;
  996. }
  997. BOOST_FOREACH (RRsetPtr rrset, auth) {
  998. if (rrset->getType() == RRType::NS()) {
  999. addToMessage(q, Message::SECTION_AUTHORITY, rrset);
  1000. } else if (rrset->getType() == task->qtype) {
  1001. addToMessage(q, Message::SECTION_ANSWER, rrset);
  1002. } else if (rrset->getType() == RRType::DS() &&
  1003. q.wantDnssec()) {
  1004. addToMessage(q, Message::SECTION_AUTHORITY, rrset);
  1005. }
  1006. getAdditional(q, rrset);
  1007. }
  1008. }
  1009. continue;
  1010. } else if ((task->flags & (NAME_NOT_FOUND|TYPE_NOT_FOUND)) != 0) {
  1011. // No data found at this qname/qtype.
  1012. // If we were looking for additional data, we should simply
  1013. // ignore this result.
  1014. if (task->state == QueryTask::GETADDITIONAL) {
  1015. continue;
  1016. }
  1017. // If we were looking for answer data, not additional,
  1018. // and the name was not found, we need to find out whether
  1019. // there are any relevant wildcards.
  1020. bool wildcard_found = false;
  1021. result = tryWildcard(q, task, zoneinfo, wildcard_found);
  1022. if (result != SUCCESS) {
  1023. m.setRcode(Rcode::SERVFAIL());
  1024. logger.error(DATASRC_QUERY_WILDCARD_FAIL,
  1025. task->qname.toText().c_str());
  1026. return;
  1027. }
  1028. if (wildcard_found) {
  1029. continue;
  1030. }
  1031. // If we've reached this point, there is definitely no answer.
  1032. // If we were chasing cnames or adding additional data, that's
  1033. // okay, but if we were doing an original query, reply with the
  1034. // SOA in the authority section. For NAME_NOT_FOUND, set
  1035. // NXDOMAIN, and also add the previous NSEC to the authority
  1036. // section. For TYPE_NOT_FOUND, do not set an error rcode,
  1037. // and send the current NSEC in the authority section.
  1038. if (task->state == QueryTask::GETANSWER) {
  1039. if ((task->flags & NAME_NOT_FOUND) != 0) {
  1040. m.setRcode(Rcode::NXDOMAIN());
  1041. }
  1042. result = addSOA(q, zoneinfo);
  1043. if (result != SUCCESS) {
  1044. logger.error(DATASRC_QUERY_MISSING_SOA,
  1045. zonename->toText().c_str());
  1046. isc_throw(DataSourceError,
  1047. "SOA RR not found in " << *zonename <<
  1048. "/" << q.qclass());
  1049. }
  1050. }
  1051. Name nsecname(task->qname);
  1052. if ((task->flags & NAME_NOT_FOUND) != 0) {
  1053. const DataSrc* ds = zoneinfo.getDataSource();
  1054. ds->findPreviousName(task->qname, nsecname, zonename);
  1055. }
  1056. if (q.wantDnssec()) {
  1057. result = proveNX(q, task, zoneinfo, false);
  1058. if (result != DataSrc::SUCCESS) {
  1059. m.setRcode(Rcode::SERVFAIL());
  1060. logger.error(DATASRC_QUERY_PROVENX_FAIL,
  1061. task->qname.toText().c_str());
  1062. return;
  1063. }
  1064. }
  1065. return;
  1066. } else {
  1067. // Should never be reached!
  1068. m.setRcode(Rcode::SERVFAIL());
  1069. logger.error(DATASRC_QUERY_UNKNOWN_RESULT);
  1070. return;
  1071. }
  1072. }
  1073. // We're done, so now copy in the additional data:
  1074. // data first, then signatures. (If we run out of
  1075. // space, signatures in additional section are
  1076. // optional.)
  1077. BOOST_FOREACH(RRsetPtr rrset, additional) {
  1078. addToMessage(q, Message::SECTION_ADDITIONAL, rrset, true);
  1079. }
  1080. if (q.wantDnssec()) {
  1081. BOOST_FOREACH(RRsetPtr rrset, additional) {
  1082. if (rrset->getRRsig()) {
  1083. addToMessage(q, Message::SECTION_ADDITIONAL, rrset->getRRsig(),
  1084. true);
  1085. }
  1086. }
  1087. }
  1088. }
  1089. DataSrc::Result
  1090. DataSrc::findAddrs(const Name& qname, const RRClass& qclass,
  1091. RRsetList& target, uint32_t& flags,
  1092. const Name* zonename) const
  1093. {
  1094. Result r;
  1095. bool a = false, aaaa = false;
  1096. flags = 0;
  1097. r = findExactRRset(qname, qclass, RRType::A(), target, flags, zonename);
  1098. if (r == SUCCESS && flags == 0) {
  1099. a = true;
  1100. }
  1101. flags = 0;
  1102. r = findExactRRset(qname, qclass, RRType::AAAA(), target, flags,
  1103. zonename);
  1104. if (r == SUCCESS && flags == 0) {
  1105. aaaa = true;
  1106. }
  1107. if (!a && !aaaa) {
  1108. flags = TYPE_NOT_FOUND;
  1109. } else {
  1110. flags = 0;
  1111. }
  1112. return (SUCCESS);
  1113. }
  1114. DataSrc::Result
  1115. DataSrc::findReferral(const Name& qname, const RRClass& qclass,
  1116. RRsetList& target, uint32_t& flags,
  1117. const Name* zonename) const
  1118. {
  1119. Result r;
  1120. bool ns = false, ds = false, dname = false;
  1121. flags = 0;
  1122. r = findExactRRset(qname, qclass, RRType::NS(), target, flags, zonename);
  1123. if (r == SUCCESS && flags == 0) {
  1124. ns = true;
  1125. } else if ((flags & (NO_SUCH_ZONE|NAME_NOT_FOUND))) {
  1126. return (SUCCESS);
  1127. }
  1128. flags = 0;
  1129. r = findExactRRset(qname, qclass, RRType::DS(), target, flags, zonename);
  1130. if (r == SUCCESS && flags == 0) {
  1131. ds = true;
  1132. } else if ((flags & (NO_SUCH_ZONE|NAME_NOT_FOUND))) {
  1133. return (SUCCESS);
  1134. }
  1135. flags = 0;
  1136. r = findExactRRset(qname, qclass, RRType::DNAME(), target, flags, zonename);
  1137. if (r == SUCCESS && flags == 0) {
  1138. dname = true;
  1139. } else if ((flags & (NO_SUCH_ZONE|NAME_NOT_FOUND))) {
  1140. return (SUCCESS);
  1141. }
  1142. if (!ns && !dname && !ds) {
  1143. flags = TYPE_NOT_FOUND;
  1144. } else {
  1145. flags = 0;
  1146. }
  1147. return (SUCCESS);
  1148. }
  1149. void
  1150. MetaDataSrc::addDataSrc(ConstDataSrcPtr data_src) {
  1151. logger.debug(DBG_TRACE_BASIC, DATASRC_META_ADD);
  1152. if (getClass() != RRClass::ANY() && data_src->getClass() != getClass()) {
  1153. logger.error(DATASRC_META_ADD_CLASS_MISMATCH,
  1154. data_src->getClass().toText().c_str(),
  1155. getClass().toText().c_str());
  1156. isc_throw(Unexpected, "class mismatch");
  1157. }
  1158. data_sources.push_back(data_src);
  1159. }
  1160. void
  1161. MetaDataSrc::removeDataSrc(ConstDataSrcPtr data_src) {
  1162. logger.debug(DBG_TRACE_BASIC, DATASRC_META_REMOVE);
  1163. std::vector<ConstDataSrcPtr>::iterator it, itr;
  1164. for (it = data_sources.begin(); it != data_sources.end(); ++it) {
  1165. if (*it == data_src) {
  1166. itr = it;
  1167. }
  1168. }
  1169. data_sources.erase(itr);
  1170. }
  1171. void
  1172. MetaDataSrc::findClosestEnclosure(DataSrcMatch& match) const {
  1173. if (getClass() != match.getClass() &&
  1174. getClass() != RRClass::ANY() && match.getClass() != RRClass::ANY()) {
  1175. return;
  1176. }
  1177. BOOST_FOREACH (ConstDataSrcPtr data_src, data_sources) {
  1178. data_src->findClosestEnclosure(match);
  1179. }
  1180. }
  1181. DataSrcMatch::~DataSrcMatch() {
  1182. delete closest_name_;
  1183. }
  1184. void
  1185. DataSrcMatch::update(const DataSrc& new_source, const Name& container) {
  1186. if (getClass() != new_source.getClass() && getClass() != RRClass::ANY() &&
  1187. new_source.getClass() != RRClass::ANY())
  1188. {
  1189. return;
  1190. }
  1191. if (closest_name_ == NULL) {
  1192. const NameComparisonResult::NameRelation cmp =
  1193. getName().compare(container).getRelation();
  1194. if (cmp != NameComparisonResult::EQUAL &&
  1195. cmp != NameComparisonResult::SUBDOMAIN)
  1196. {
  1197. return;
  1198. }
  1199. closest_name_ = new Name(container);
  1200. best_source_ = &new_source;
  1201. return;
  1202. }
  1203. if (container.compare(*closest_name_).getRelation() ==
  1204. NameComparisonResult::SUBDOMAIN) {
  1205. Name* newname = new Name(container);
  1206. delete closest_name_;
  1207. closest_name_ = newname;
  1208. best_source_ = &new_source;
  1209. }
  1210. }
  1211. Nsec3Param::Nsec3Param(const uint8_t a, const uint8_t f, const uint16_t i,
  1212. const std::vector<uint8_t>& s) :
  1213. algorithm_(a), flags_(f), iterations_(i), salt_(s)
  1214. {}
  1215. string
  1216. Nsec3Param::getHash(const Name& name) const {
  1217. OutputBuffer buf(0);
  1218. name.toWire(buf);
  1219. uint8_t digest[SHA1_HASHSIZE];
  1220. const uint8_t* input = static_cast<const uint8_t*>(buf.getData());
  1221. size_t inlength = buf.getLength();
  1222. const uint8_t saltlen = salt_.size();
  1223. int n = 0;
  1224. SHA1Context sha;
  1225. do {
  1226. SHA1Reset(&sha);
  1227. SHA1Input(&sha, input, inlength);
  1228. SHA1Input(&sha, &salt_[0], saltlen);
  1229. SHA1Result(&sha, digest);
  1230. input = digest;
  1231. inlength = SHA1_HASHSIZE;
  1232. } while (n++ < iterations_);
  1233. return (encodeBase32Hex(vector<uint8_t>(digest, digest + SHA1_HASHSIZE)));
  1234. }
  1235. DataSrc::Result
  1236. DataSrc::init(isc::data::ConstElementPtr) {
  1237. return (NOT_IMPLEMENTED);
  1238. }
  1239. DataSrc::Result
  1240. MetaDataSrc::findRRset(const isc::dns::Name&,
  1241. const isc::dns::RRClass&,
  1242. const isc::dns::RRType&,
  1243. isc::dns::RRsetList&,
  1244. uint32_t&,
  1245. const isc::dns::Name*) const
  1246. {
  1247. return (NOT_IMPLEMENTED);
  1248. }
  1249. DataSrc::Result
  1250. MetaDataSrc::findExactRRset(const isc::dns::Name&,
  1251. const isc::dns::RRClass&,
  1252. const isc::dns::RRType&,
  1253. isc::dns::RRsetList&,
  1254. uint32_t&,
  1255. const isc::dns::Name*) const
  1256. {
  1257. return (NOT_IMPLEMENTED);
  1258. }
  1259. DataSrc::Result
  1260. MetaDataSrc::findAddrs(const isc::dns::Name&,
  1261. const isc::dns::RRClass&,
  1262. isc::dns::RRsetList&,
  1263. uint32_t&,
  1264. const isc::dns::Name*) const
  1265. {
  1266. return (NOT_IMPLEMENTED);
  1267. }
  1268. DataSrc::Result
  1269. MetaDataSrc::findReferral(const isc::dns::Name&,
  1270. const isc::dns::RRClass&,
  1271. isc::dns::RRsetList&,
  1272. uint32_t&,
  1273. const isc::dns::Name*) const
  1274. {
  1275. return (NOT_IMPLEMENTED);
  1276. }
  1277. DataSrc::Result
  1278. MetaDataSrc::findPreviousName(const isc::dns::Name&,
  1279. isc::dns::Name&,
  1280. const isc::dns::Name*) const
  1281. {
  1282. return (NOT_IMPLEMENTED);
  1283. }
  1284. DataSrc::Result
  1285. MetaDataSrc::findCoveringNSEC3(const isc::dns::Name&,
  1286. std::string&,
  1287. isc::dns::RRsetList&) const
  1288. {
  1289. return (NOT_IMPLEMENTED);
  1290. }
  1291. }
  1292. }