data_source.cc 42 KB

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