data_source.cc 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321
  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. Message::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. Message::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, Message::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 Message::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() ||
  410. !m.hasRRset(sect, rrset->getName(), rrset->getClass(),
  411. rrset->getType())) {
  412. m.addRRset(sect, rrset, false);
  413. }
  414. } else {
  415. if (!m.hasRRset(sect, rrset->getName(), rrset->getClass(),
  416. rrset->getType())) {
  417. m.addRRset(sect, rrset, q.wantDnssec());
  418. }
  419. }
  420. }
  421. // Copy referral information into the authority section of a message
  422. inline void
  423. copyAuth(Query& q, RRsetList& auth) {
  424. BOOST_FOREACH(RRsetPtr rrset, auth) {
  425. if (rrset->getType() == RRType::DNAME()) {
  426. continue;
  427. }
  428. if (rrset->getType() == RRType::DS() && !q.wantDnssec()) {
  429. continue;
  430. }
  431. addToMessage(q, Message::SECTION_AUTHORITY, rrset);
  432. getAdditional(q, rrset);
  433. }
  434. }
  435. // Query for referrals (i.e., NS/DS or DNAME) at a given name
  436. inline bool
  437. refQuery(const Query& q, const Name& name, ZoneInfo& zoneinfo,
  438. RRsetList& target)
  439. {
  440. QueryTask newtask(q, name, QueryTask::REF_QUERY);
  441. if (doQueryTask(newtask, zoneinfo, target) != DataSrc::SUCCESS) {
  442. // Lookup failed
  443. return (false);
  444. }
  445. // Referral bit is expected, so clear it when checking flags
  446. if ((newtask.flags & ~DataSrc::REFERRAL) != 0) {
  447. return (false);
  448. }
  449. return (true);
  450. }
  451. // Match downward, from the zone apex to the query name, looking for
  452. // referrals. Note that we exclude the apex name and query name themselves;
  453. // they'll be handled in a normal lookup in the zone.
  454. inline bool
  455. hasDelegation(Query& q, QueryTaskPtr task, ZoneInfo& zoneinfo) {
  456. const Name* const zonename = zoneinfo.getEnclosingZone();
  457. if (zonename == NULL) {
  458. if (task->state == QueryTask::GETANSWER) {
  459. q.message().setRcode(Rcode::REFUSED());
  460. }
  461. return (false);
  462. }
  463. const int diff = task->qname.getLabelCount() - zonename->getLabelCount();
  464. if (diff > 1) {
  465. bool found = false;
  466. RRsetList ref;
  467. for (int i = diff - 1; i > 0; --i) {
  468. const Name sub(task->qname.split(i));
  469. if (refQuery(q, sub, zoneinfo, ref)) {
  470. found = true;
  471. break;
  472. }
  473. }
  474. // Found a referral while getting additional data
  475. // for something other than NS; we skip it.
  476. if (found && task->op == QueryTask::NOGLUE_QUERY) {
  477. return (true);
  478. }
  479. // Found a referral while getting answer data;
  480. // send a delegation.
  481. if (found) {
  482. RRsetPtr r = ref.findRRset(RRType::DNAME(), q.qclass());
  483. if (r != NULL) {
  484. RRsetList syn;
  485. addToMessage(q, Message::SECTION_ANSWER, r);
  486. q.message().setHeaderFlag(Message::HEADERFLAG_AA);
  487. synthesizeCname(task, r, syn);
  488. if (syn.size() == 1) {
  489. addToMessage(q, Message::SECTION_ANSWER,
  490. syn.findRRset(RRType::CNAME(), q.qclass()));
  491. chaseCname(q, task, syn.findRRset(RRType::CNAME(),
  492. q.qclass()));
  493. return (true);
  494. }
  495. }
  496. copyAuth(q, ref);
  497. return (true);
  498. }
  499. }
  500. // We appear to have authoritative data; set the header
  501. // flag. (We may clear it later if we find a referral
  502. // at the actual qname node.)
  503. if (task->op == QueryTask::AUTH_QUERY &&
  504. task->state == QueryTask::GETANSWER) {
  505. q.message().setHeaderFlag(Message::HEADERFLAG_AA);
  506. }
  507. return (false);
  508. }
  509. inline DataSrc::Result
  510. addSOA(Query& q, ZoneInfo& zoneinfo) {
  511. RRsetList soa;
  512. const Name* const zonename = zoneinfo.getEnclosingZone();
  513. QueryTask newtask(q, *zonename, RRType::SOA(), QueryTask::SIMPLE_QUERY);
  514. RETERR(doQueryTask(newtask, zoneinfo, soa));
  515. if (newtask.flags != 0) {
  516. return (DataSrc::ERROR);
  517. }
  518. addToMessage(q, Message::SECTION_AUTHORITY,
  519. soa.findRRset(RRType::SOA(), q.qclass()));
  520. return (DataSrc::SUCCESS);
  521. }
  522. inline DataSrc::Result
  523. addNSEC(Query& q, const Name& name, ZoneInfo& zoneinfo) {
  524. RRsetList nsec;
  525. QueryTask newtask(q, name, RRType::NSEC(), QueryTask::SIMPLE_QUERY);
  526. RETERR(doQueryTask(newtask, zoneinfo, nsec));
  527. if (newtask.flags == 0) {
  528. addToMessage(q, Message::SECTION_AUTHORITY,
  529. nsec.findRRset(RRType::NSEC(), q.qclass()));
  530. }
  531. return (DataSrc::SUCCESS);
  532. }
  533. inline DataSrc::Result
  534. getNsec3(Query& q, ZoneInfo& zoneinfo, string& hash, RRsetPtr& target) {
  535. const DataSrc* ds = zoneinfo.getDataSource();
  536. const Name* const zonename = zoneinfo.getEnclosingZone();
  537. if (ds == NULL) {
  538. q.message().setRcode(Rcode::SERVFAIL());
  539. return (DataSrc::ERROR);
  540. }
  541. RRsetList rl;
  542. RETERR(ds->findCoveringNSEC3(*zonename, hash, rl));
  543. target = rl.findRRset(RRType::NSEC3(), q.qclass());
  544. return (DataSrc::SUCCESS);
  545. }
  546. ConstNsec3ParamPtr
  547. getNsec3Param(Query& q, ZoneInfo& zoneinfo) {
  548. DataSrc::Result result;
  549. RRsetList nsec3param;
  550. const Name* const zonename = zoneinfo.getEnclosingZone();
  551. QueryTask newtask(q, *zonename, RRType::NSEC3PARAM(),
  552. QueryTask::SIMPLE_QUERY);
  553. result = doQueryTask(newtask, zoneinfo, nsec3param);
  554. newtask.flags &= ~DataSrc::REFERRAL;
  555. if (result != DataSrc::SUCCESS || newtask.flags != 0) {
  556. return (ConstNsec3ParamPtr());
  557. }
  558. RRsetPtr rrset = nsec3param.findRRset(RRType::NSEC3PARAM(), q.qclass());
  559. if (!rrset) {
  560. return (ConstNsec3ParamPtr());
  561. }
  562. // XXX: currently only one NSEC3 chain per zone is supported;
  563. // we will need to revisit this.
  564. RdataIteratorPtr it = rrset->getRdataIterator();
  565. it->first();
  566. if (it->isLast()) {
  567. return (ConstNsec3ParamPtr());
  568. }
  569. const generic::NSEC3PARAM& np =
  570. dynamic_cast<const generic::NSEC3PARAM&>(it->getCurrent());
  571. return (ConstNsec3ParamPtr(new Nsec3Param(np.getHashalg(), np.getFlags(),
  572. np.getIterations(),
  573. np.getSalt())));
  574. }
  575. inline DataSrc::Result
  576. proveNX(Query& q, QueryTaskPtr task, ZoneInfo& zoneinfo, const bool wildcard) {
  577. Message& m = q.message();
  578. const Name* const zonename = zoneinfo.getEnclosingZone();
  579. ConstNsec3ParamPtr nsec3 = getNsec3Param(q, zoneinfo);
  580. if (nsec3 != NULL) {
  581. // Attach the NSEC3 record covering the QNAME
  582. RRsetPtr rrset;
  583. string hash1(nsec3->getHash(task->qname));
  584. RETERR(getNsec3(q, zoneinfo, hash1, rrset));
  585. addToMessage(q, Message::SECTION_AUTHORITY, rrset);
  586. // If this is an NXRRSET or NOERROR/NODATA, we're done
  587. if ((task->flags & DataSrc::TYPE_NOT_FOUND) != 0) {
  588. return (DataSrc::SUCCESS);
  589. }
  590. // Find the closest provable enclosing name for QNAME
  591. Name enclosure(*zonename);
  592. const int diff = task->qname.getLabelCount() -
  593. enclosure.getLabelCount();
  594. string hash2;
  595. for (int i = 1; i <= diff; ++i) {
  596. enclosure = task->qname.split(i);
  597. string nodehash(nsec3->getHash(enclosure));
  598. if (nodehash == hash1) {
  599. break;
  600. }
  601. hash2 = nodehash;
  602. RRsetList rl;
  603. // hash2 will be overwritten with the actual hash found;
  604. // we don't want to use one until we find an exact match
  605. RETERR(getNsec3(q, zoneinfo, hash2, rrset));
  606. if (hash2 == nodehash) {
  607. addToMessage(q, Message::SECTION_AUTHORITY, rrset);
  608. break;
  609. }
  610. }
  611. // If we are processing a wildcard answer, we're done.
  612. if (wildcard) {
  613. return (DataSrc::SUCCESS);
  614. }
  615. // Otherwise, there is no wildcard record, so we must add a
  616. // covering NSEC3 to prove that it doesn't exist.
  617. string hash3(nsec3->getHash(Name("*").concatenate(enclosure)));
  618. RETERR(getNsec3(q, zoneinfo, hash3, rrset));
  619. if (hash3 != hash1 && hash3 != hash2) {
  620. addToMessage(q, Message::SECTION_AUTHORITY, rrset);
  621. }
  622. } else {
  623. Name nsecname(task->qname);
  624. if ((task->flags & DataSrc::NAME_NOT_FOUND) != 0 || wildcard) {
  625. const DataSrc* ds = zoneinfo.getDataSource();
  626. if (ds == NULL) {
  627. m.setRcode(Rcode::SERVFAIL());
  628. return (DataSrc::ERROR);
  629. }
  630. ds->findPreviousName(task->qname, nsecname, zonename);
  631. }
  632. RETERR(addNSEC(q, nsecname, zoneinfo));
  633. if ((task->flags & DataSrc::TYPE_NOT_FOUND) != 0 ||
  634. nsecname == *zonename)
  635. {
  636. return (DataSrc::SUCCESS);
  637. }
  638. // If we are processing a wildcard answer, we're done.
  639. if (wildcard) {
  640. return (DataSrc::SUCCESS);
  641. }
  642. // Otherwise, there is no wildcard record, so we must add an
  643. // NSEC for the zone to prove the wildcard doesn't exist.
  644. RETERR(addNSEC(q, *zonename, zoneinfo));
  645. }
  646. return (DataSrc::SUCCESS);
  647. }
  648. // Attempt a wildcard lookup
  649. inline DataSrc::Result
  650. tryWildcard(Query& q, QueryTaskPtr task, ZoneInfo& zoneinfo, bool& found) {
  651. Message& m = q.message();
  652. DataSrc::Result result;
  653. found = false;
  654. if ((task->flags & DataSrc::NAME_NOT_FOUND) == 0 ||
  655. (task->state != QueryTask::GETANSWER &&
  656. task->state != QueryTask::FOLLOWCNAME)) {
  657. return (DataSrc::SUCCESS);
  658. }
  659. const Name* const zonename = zoneinfo.getEnclosingZone();
  660. const int diff = task->qname.getLabelCount() - zonename->getLabelCount();
  661. if (diff < 1) {
  662. return (DataSrc::SUCCESS);
  663. }
  664. RRsetList wild;
  665. const Name star("*");
  666. bool cname = false;
  667. for (int i = 1; i <= diff; ++i) {
  668. const Name& wname(star.concatenate(task->qname.split(i)));
  669. QueryTask newtask(q, wname, task->qtype, Message::SECTION_ANSWER,
  670. QueryTask::AUTH_QUERY);
  671. result = doQueryTask(newtask, zoneinfo, wild);
  672. if (result == DataSrc::SUCCESS) {
  673. if (newtask.flags == 0) {
  674. task->flags &= ~DataSrc::NAME_NOT_FOUND;
  675. task->flags &= ~DataSrc::TYPE_NOT_FOUND;
  676. found = true;
  677. break;
  678. } else if ((newtask.flags & DataSrc::CNAME_FOUND) != 0) {
  679. task->flags &= ~DataSrc::NAME_NOT_FOUND;
  680. task->flags &= ~DataSrc::TYPE_NOT_FOUND;
  681. task->flags |= DataSrc::CNAME_FOUND;
  682. found = true;
  683. cname = true;
  684. break;
  685. } else if ((newtask.flags & DataSrc::TYPE_NOT_FOUND) != 0) {
  686. task->flags &= ~DataSrc::NAME_NOT_FOUND;
  687. task->flags |= DataSrc::TYPE_NOT_FOUND;
  688. break;
  689. }
  690. }
  691. }
  692. // A wildcard was found.
  693. if (found) {
  694. // Prove the nonexistence of the name we were looking for
  695. if (q.wantDnssec()) {
  696. result = proveNX(q, task, zoneinfo, true);
  697. if (result != DataSrc::SUCCESS) {
  698. m.setRcode(Rcode::SERVFAIL());
  699. return (DataSrc::ERROR);
  700. }
  701. }
  702. // Add the data to the answer section (but with the name changed to
  703. // match the qname), and then continue as if this were a normal
  704. // answer: if a CNAME, chase the target, otherwise add authority.
  705. if (cname) {
  706. RRsetPtr rrset = wild.findRRset(RRType::CNAME(), q.qclass());
  707. if (rrset != NULL) {
  708. rrset->setName(task->qname);
  709. addToMessage(q, Message::SECTION_ANSWER, rrset);
  710. chaseCname(q, task, rrset);
  711. }
  712. } else {
  713. BOOST_FOREACH (RRsetPtr rrset, wild) {
  714. rrset->setName(task->qname);
  715. addToMessage(q, Message::SECTION_ANSWER, rrset);
  716. }
  717. RRsetList auth;
  718. if (!refQuery(q, *zonename, zoneinfo, auth)) {
  719. return (DataSrc::ERROR);
  720. }
  721. copyAuth(q, auth);
  722. }
  723. }
  724. return (DataSrc::SUCCESS);
  725. }
  726. //
  727. // doQuery: Processes a query.
  728. //
  729. void
  730. DataSrc::doQuery(Query& q) {
  731. Message& m = q.message();
  732. vector<RRsetPtr> additional;
  733. // Record the fact that the query is being processed by the
  734. // current data source.
  735. q.setDatasrc(this);
  736. // Process the query task queue. (The queue is initialized
  737. // and the first task placed on it by the Query constructor.)
  738. m.setHeaderFlag(Message::HEADERFLAG_AA, false);
  739. while (!q.tasks().empty()) {
  740. QueryTaskPtr task = q.tasks().front();
  741. q.tasks().pop();
  742. // Can't query directly for RRSIG.
  743. if (task->qtype == RRType::RRSIG()) {
  744. m.setRcode(Rcode::REFUSED());
  745. return;
  746. }
  747. // These task types should never be on the task queue.
  748. if (task->op == QueryTask::SIMPLE_QUERY ||
  749. task->op == QueryTask::REF_QUERY) {
  750. m.setRcode(Rcode::SERVFAIL());
  751. return;
  752. }
  753. ZoneInfo zoneinfo(this, task->qname, task->qclass, task->qtype);
  754. RRsetList data;
  755. Result result = SUCCESS;
  756. // For these query task types, if there is more than
  757. // one level between the zone name and qname, we need to
  758. // check the intermediate nodes for referrals.
  759. if ((task->op == QueryTask::AUTH_QUERY ||
  760. task->op == QueryTask::NOGLUE_QUERY) &&
  761. hasDelegation(q, task, zoneinfo)) {
  762. continue;
  763. }
  764. result = doQueryTask(*task, zoneinfo, data);
  765. if (result != SUCCESS) {
  766. m.setRcode(Rcode::SERVFAIL());
  767. return;
  768. }
  769. // No such zone. If we're chasing cnames or adding additional
  770. // data, that's okay, but if doing an original query, return
  771. // REFUSED.
  772. if (task->flags == NO_SUCH_ZONE) {
  773. if (task->state == QueryTask::GETANSWER) {
  774. m.setRcode(Rcode::REFUSED());
  775. return;
  776. }
  777. continue;
  778. }
  779. // Query found a referral; let's find out if that was expected--
  780. // i.e., if an NS was at the zone apex, or if we were querying
  781. // specifically for, and found, a DS, NSEC, or DNAME record.
  782. const Name* const zonename = zoneinfo.getEnclosingZone();
  783. if ((task->flags & REFERRAL) != 0 &&
  784. (zonename->getLabelCount() == task->qname.getLabelCount() ||
  785. ((task->qtype == RRType::NSEC() ||
  786. task->qtype == RRType::DS() ||
  787. task->qtype == RRType::DNAME()) &&
  788. data.findRRset(task->qtype, task->qclass)))) {
  789. task->flags &= ~REFERRAL;
  790. }
  791. if (result == SUCCESS && task->flags == 0) {
  792. bool have_ns = false, need_auth = false;
  793. switch (task->state) {
  794. case QueryTask::GETANSWER:
  795. case QueryTask::FOLLOWCNAME:
  796. BOOST_FOREACH(RRsetPtr rrset, data) {
  797. addToMessage(q, task->section, rrset);
  798. if (q.tasks().empty()) {
  799. need_auth = true;
  800. }
  801. getAdditional(q, rrset);
  802. if (rrset->getType() == RRType::NS()) {
  803. have_ns = true;
  804. }
  805. }
  806. q.setStatus(Query::ANSWERED);
  807. if (need_auth && !have_ns) {
  808. // Data found, no additional processing needed.
  809. // Add the NS records for the enclosing zone to
  810. // the authority section.
  811. RRsetList auth;
  812. const DataSrc* ds = zoneinfo.getDataSource();
  813. if (!refQuery(q, Name(*zonename), zoneinfo, auth) ||
  814. !auth.findRRset(RRType::NS(), ds->getClass())) {
  815. isc_throw(DataSourceError,
  816. "NS RR not found in " << *zonename << "/" <<
  817. q.qclass());
  818. }
  819. copyAuth(q, auth);
  820. }
  821. continue;
  822. case QueryTask::GETADDITIONAL:
  823. // Got additional data. Do not add it to the message
  824. // yet; instead store it and copy it in at the end
  825. // (this allow RRSIGs to be omitted if necessary).
  826. BOOST_FOREACH(RRsetPtr rrset, data) {
  827. if (q.status() == Query::ANSWERED &&
  828. rrset->getName() == q.qname() &&
  829. rrset->getType() == q.qtype()) {
  830. continue;
  831. }
  832. additional.push_back(rrset);
  833. }
  834. continue;
  835. default:
  836. isc_throw (Unexpected, "unexpected query state");
  837. }
  838. } else if (result == ERROR || result == NOT_IMPLEMENTED) {
  839. m.setRcode(Rcode::SERVFAIL());
  840. return;
  841. } else if ((task->flags & CNAME_FOUND) != 0) {
  842. // The qname node contains a CNAME. Add a new task to the
  843. // queue to look up its target.
  844. RRsetPtr rrset = data.findRRset(RRType::CNAME(), q.qclass());
  845. if (rrset != NULL) {
  846. addToMessage(q, task->section, rrset);
  847. chaseCname(q, task, rrset);
  848. }
  849. continue;
  850. } else if ((task->flags & REFERRAL) != 0) {
  851. // The qname node contains an out-of-zone referral.
  852. if (task->state == QueryTask::GETANSWER) {
  853. RRsetList auth;
  854. m.setHeaderFlag(Message::HEADERFLAG_AA, false);
  855. if (!refQuery(q, task->qname, zoneinfo, auth)) {
  856. m.setRcode(Rcode::SERVFAIL());
  857. return;
  858. }
  859. BOOST_FOREACH (RRsetPtr rrset, auth) {
  860. if (rrset->getType() == RRType::NS()) {
  861. addToMessage(q, Message::SECTION_AUTHORITY, rrset);
  862. } else if (rrset->getType() == task->qtype) {
  863. addToMessage(q, Message::SECTION_ANSWER, rrset);
  864. } else if (rrset->getType() == RRType::DS() &&
  865. q.wantDnssec()) {
  866. addToMessage(q, Message::SECTION_AUTHORITY, rrset);
  867. }
  868. getAdditional(q, rrset);
  869. }
  870. }
  871. continue;
  872. } else if ((task->flags & (NAME_NOT_FOUND|TYPE_NOT_FOUND)) != 0) {
  873. // No data found at this qname/qtype.
  874. // If we were looking for answer data, not additional,
  875. // and the name was not found, we need to find out whether
  876. // there are any relevant wildcards.
  877. bool wildcard_found = false;
  878. result = tryWildcard(q, task, zoneinfo, wildcard_found);
  879. if (result != SUCCESS) {
  880. m.setRcode(Rcode::SERVFAIL());
  881. return;
  882. }
  883. if (wildcard_found) {
  884. continue;
  885. }
  886. // If we've reached this point, there is definitely no answer.
  887. // If we were chasing cnames or adding additional data, that's
  888. // okay, but if we were doing an original query, reply with the
  889. // SOA in the authority section. For NAME_NOT_FOUND, set
  890. // NXDOMAIN, and also add the previous NSEC to the authority
  891. // section. For TYPE_NOT_FOUND, do not set an error rcode,
  892. // and send the current NSEC in the authority section.
  893. if (task->state == QueryTask::GETANSWER) {
  894. if ((task->flags & NAME_NOT_FOUND) != 0) {
  895. m.setRcode(Rcode::NXDOMAIN());
  896. }
  897. result = addSOA(q, zoneinfo);
  898. if (result != SUCCESS) {
  899. isc_throw(DataSourceError,
  900. "SOA RR not found in " << *zonename <<
  901. "/" << q.qclass());
  902. }
  903. }
  904. Name nsecname(task->qname);
  905. if ((task->flags & NAME_NOT_FOUND) != 0) {
  906. const DataSrc* ds = zoneinfo.getDataSource();
  907. ds->findPreviousName(task->qname, nsecname, zonename);
  908. }
  909. if (q.wantDnssec()) {
  910. result = proveNX(q, task, zoneinfo, false);
  911. if (result != DataSrc::SUCCESS) {
  912. m.setRcode(Rcode::SERVFAIL());
  913. return;
  914. }
  915. }
  916. return;
  917. } else {
  918. // Should never be reached!
  919. m.setRcode(Rcode::SERVFAIL());
  920. return;
  921. }
  922. }
  923. // We're done, so now copy in the additional data:
  924. // data first, then signatures. (If we run out of
  925. // space, signatures in additional section are
  926. // optional.)
  927. BOOST_FOREACH(RRsetPtr rrset, additional) {
  928. addToMessage(q, Message::SECTION_ADDITIONAL, rrset, true);
  929. }
  930. if (q.wantDnssec()) {
  931. BOOST_FOREACH(RRsetPtr rrset, additional) {
  932. if (rrset->getRRsig()) {
  933. addToMessage(q, Message::SECTION_ADDITIONAL, rrset->getRRsig(),
  934. true);
  935. }
  936. }
  937. }
  938. }
  939. DataSrc::Result
  940. DataSrc::findAddrs(const Name& qname, const RRClass& qclass,
  941. RRsetList& target, uint32_t& flags,
  942. const Name* zonename) const
  943. {
  944. Result r;
  945. bool a = false, aaaa = false;
  946. flags = 0;
  947. r = findExactRRset(qname, qclass, RRType::A(), target, flags, zonename);
  948. if (r == SUCCESS && flags == 0) {
  949. a = true;
  950. }
  951. flags = 0;
  952. r = findExactRRset(qname, qclass, RRType::AAAA(), target, flags,
  953. zonename);
  954. if (r == SUCCESS && flags == 0) {
  955. aaaa = true;
  956. }
  957. if (!a && !aaaa) {
  958. flags = TYPE_NOT_FOUND;
  959. } else {
  960. flags = 0;
  961. }
  962. return (SUCCESS);
  963. }
  964. DataSrc::Result
  965. DataSrc::findReferral(const Name& qname, const RRClass& qclass,
  966. RRsetList& target, uint32_t& flags,
  967. const Name* zonename) const
  968. {
  969. Result r;
  970. bool ns = false, ds = false, dname = false;
  971. flags = 0;
  972. r = findExactRRset(qname, qclass, RRType::NS(), target, flags, zonename);
  973. if (r == SUCCESS && flags == 0) {
  974. ns = true;
  975. } else if ((flags & (NO_SUCH_ZONE|NAME_NOT_FOUND))) {
  976. return (SUCCESS);
  977. }
  978. flags = 0;
  979. r = findExactRRset(qname, qclass, RRType::DS(), target, flags, zonename);
  980. if (r == SUCCESS && flags == 0) {
  981. ds = true;
  982. } else if ((flags & (NO_SUCH_ZONE|NAME_NOT_FOUND))) {
  983. return (SUCCESS);
  984. }
  985. flags = 0;
  986. r = findExactRRset(qname, qclass, RRType::DNAME(), target, flags, zonename);
  987. if (r == SUCCESS && flags == 0) {
  988. dname = true;
  989. } else if ((flags & (NO_SUCH_ZONE|NAME_NOT_FOUND))) {
  990. return (SUCCESS);
  991. }
  992. if (!ns && !dname && !ds) {
  993. flags = TYPE_NOT_FOUND;
  994. } else {
  995. flags = 0;
  996. }
  997. return (SUCCESS);
  998. }
  999. void
  1000. MetaDataSrc::addDataSrc(ConstDataSrcPtr data_src) {
  1001. if (getClass() != RRClass::ANY() && data_src->getClass() != getClass()) {
  1002. isc_throw(Unexpected, "class mismatch");
  1003. }
  1004. data_sources.push_back(data_src);
  1005. }
  1006. void
  1007. MetaDataSrc::removeDataSrc(ConstDataSrcPtr data_src) {
  1008. std::vector<ConstDataSrcPtr>::iterator it, itr;
  1009. for (it = data_sources.begin(); it != data_sources.end(); it++) {
  1010. if (*it == data_src) {
  1011. itr = it;
  1012. }
  1013. }
  1014. data_sources.erase(itr);
  1015. }
  1016. void
  1017. MetaDataSrc::findClosestEnclosure(DataSrcMatch& match) const {
  1018. if (getClass() != match.getClass() &&
  1019. getClass() != RRClass::ANY() && match.getClass() != RRClass::ANY()) {
  1020. return;
  1021. }
  1022. BOOST_FOREACH (ConstDataSrcPtr data_src, data_sources) {
  1023. data_src->findClosestEnclosure(match);
  1024. }
  1025. }
  1026. DataSrcMatch::~DataSrcMatch() {
  1027. delete closest_name_;
  1028. }
  1029. void
  1030. DataSrcMatch::update(const DataSrc& new_source, const Name& container) {
  1031. if (getClass() != new_source.getClass() && getClass() != RRClass::ANY() &&
  1032. new_source.getClass() != RRClass::ANY())
  1033. {
  1034. return;
  1035. }
  1036. if (closest_name_ == NULL) {
  1037. const NameComparisonResult::NameRelation cmp =
  1038. getName().compare(container).getRelation();
  1039. if (cmp != NameComparisonResult::EQUAL &&
  1040. cmp != NameComparisonResult::SUBDOMAIN)
  1041. {
  1042. return;
  1043. }
  1044. closest_name_ = new Name(container);
  1045. best_source_ = &new_source;
  1046. return;
  1047. }
  1048. if (container.compare(*closest_name_).getRelation() ==
  1049. NameComparisonResult::SUBDOMAIN) {
  1050. Name* newname = new Name(container);
  1051. delete closest_name_;
  1052. closest_name_ = newname;
  1053. best_source_ = &new_source;
  1054. }
  1055. }
  1056. Nsec3Param::Nsec3Param(const uint8_t a, const uint8_t f, const uint16_t i,
  1057. const std::vector<uint8_t>& s) :
  1058. algorithm_(a), flags_(f), iterations_(i), salt_(s)
  1059. {}
  1060. string
  1061. Nsec3Param::getHash(const Name& name) const {
  1062. OutputBuffer buf(0);
  1063. name.toWire(buf);
  1064. uint8_t digest[SHA1_HASHSIZE];
  1065. const uint8_t* input = static_cast<const uint8_t*>(buf.getData());
  1066. size_t inlength = buf.getLength();
  1067. const uint8_t saltlen = salt_.size();
  1068. int n = 0;
  1069. SHA1Context sha;
  1070. do {
  1071. SHA1Reset(&sha);
  1072. SHA1Input(&sha, input, inlength);
  1073. SHA1Input(&sha, &salt_[0], saltlen);
  1074. SHA1Result(&sha, digest);
  1075. input = digest;
  1076. inlength = SHA1_HASHSIZE;
  1077. } while (n++ < iterations_);
  1078. return (encodeBase32Hex(vector<uint8_t>(digest, digest + SHA1_HASHSIZE)));
  1079. }
  1080. //
  1081. // The following methods are effectively empty, and their parameters are
  1082. // unused. To silence compilers that warn unused function parameters,
  1083. // we specify a (compiler dependent) special keyword when available.
  1084. // It's defined in config.h, and to avoid including this header file from
  1085. // installed files we define the methods here.
  1086. //
  1087. DataSrc::Result
  1088. DataSrc::init(isc::data::ConstElementPtr config UNUSED_PARAM) {
  1089. return (NOT_IMPLEMENTED);
  1090. }
  1091. DataSrc::Result
  1092. MetaDataSrc::findRRset(const isc::dns::Name& qname UNUSED_PARAM,
  1093. const isc::dns::RRClass& qclass UNUSED_PARAM,
  1094. const isc::dns::RRType& qtype UNUSED_PARAM,
  1095. isc::dns::RRsetList& target UNUSED_PARAM,
  1096. uint32_t& flags UNUSED_PARAM,
  1097. const isc::dns::Name* zonename UNUSED_PARAM) const
  1098. {
  1099. return (NOT_IMPLEMENTED);
  1100. }
  1101. DataSrc::Result
  1102. MetaDataSrc::findExactRRset(const isc::dns::Name& qname UNUSED_PARAM,
  1103. const isc::dns::RRClass& qclass UNUSED_PARAM,
  1104. const isc::dns::RRType& qtype UNUSED_PARAM,
  1105. isc::dns::RRsetList& target UNUSED_PARAM,
  1106. uint32_t& flags UNUSED_PARAM,
  1107. const isc::dns::Name* zonename UNUSED_PARAM) const
  1108. {
  1109. return (NOT_IMPLEMENTED);
  1110. }
  1111. DataSrc::Result
  1112. MetaDataSrc::findAddrs(const isc::dns::Name& qname UNUSED_PARAM,
  1113. const isc::dns::RRClass& qclass UNUSED_PARAM,
  1114. isc::dns::RRsetList& target UNUSED_PARAM,
  1115. uint32_t& flags UNUSED_PARAM,
  1116. const isc::dns::Name* zonename UNUSED_PARAM) const
  1117. {
  1118. return (NOT_IMPLEMENTED);
  1119. }
  1120. DataSrc::Result
  1121. MetaDataSrc::findReferral(const isc::dns::Name& qname UNUSED_PARAM,
  1122. const isc::dns::RRClass& qclass UNUSED_PARAM,
  1123. isc::dns::RRsetList& target UNUSED_PARAM,
  1124. uint32_t& flags UNUSED_PARAM,
  1125. const isc::dns::Name* zonename UNUSED_PARAM) const
  1126. {
  1127. return (NOT_IMPLEMENTED);
  1128. }
  1129. DataSrc::Result
  1130. MetaDataSrc::findPreviousName(const isc::dns::Name& qname UNUSED_PARAM,
  1131. isc::dns::Name& target UNUSED_PARAM,
  1132. const isc::dns::Name* zonename UNUSED_PARAM) const
  1133. {
  1134. return (NOT_IMPLEMENTED);
  1135. }
  1136. DataSrc::Result
  1137. MetaDataSrc::findCoveringNSEC3(const isc::dns::Name& zonename UNUSED_PARAM,
  1138. std::string& hash UNUSED_PARAM,
  1139. isc::dns::RRsetList& target UNUSED_PARAM) const
  1140. {
  1141. return (NOT_IMPLEMENTED);
  1142. }
  1143. }
  1144. }