sqlite3_datasrc.cc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  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 <string>
  15. #include <sstream>
  16. #include <sqlite3.h>
  17. #include <datasrc/sqlite3_datasrc.h>
  18. #include <datasrc/logger.h>
  19. #include <dns/rrttl.h>
  20. #include <dns/rdata.h>
  21. #include <dns/rdataclass.h>
  22. #include <dns/rrset.h>
  23. #include <dns/rrsetlist.h>
  24. using namespace std;
  25. using namespace isc::dns;
  26. using namespace isc::dns::rdata;
  27. namespace isc {
  28. namespace datasrc {
  29. struct Sqlite3Parameters {
  30. Sqlite3Parameters() : db_(NULL), version_(-1),
  31. q_zone_(NULL), q_record_(NULL), q_addrs_(NULL), q_referral_(NULL),
  32. q_any_(NULL), q_count_(NULL), q_previous_(NULL), q_nsec3_(NULL),
  33. q_prevnsec3_(NULL)
  34. {}
  35. sqlite3* db_;
  36. int version_;
  37. sqlite3_stmt* q_zone_;
  38. sqlite3_stmt* q_record_;
  39. sqlite3_stmt* q_addrs_;
  40. sqlite3_stmt* q_referral_;
  41. sqlite3_stmt* q_any_;
  42. sqlite3_stmt* q_count_;
  43. sqlite3_stmt* q_previous_;
  44. sqlite3_stmt* q_nsec3_;
  45. sqlite3_stmt* q_prevnsec3_;
  46. };
  47. namespace {
  48. const char* const SCHEMA_LIST[] = {
  49. "CREATE TABLE schema_version (version INTEGER NOT NULL)",
  50. "INSERT INTO schema_version VALUES (1)",
  51. "CREATE TABLE zones (id INTEGER PRIMARY KEY, "
  52. "name STRING NOT NULL COLLATE NOCASE, "
  53. "rdclass STRING NOT NULL COLLATE NOCASE DEFAULT 'IN', "
  54. "dnssec BOOLEAN NOT NULL DEFAULT 0)",
  55. "CREATE INDEX zones_byname ON zones (name)",
  56. "CREATE TABLE records (id INTEGER PRIMARY KEY, "
  57. "zone_id INTEGER NOT NULL, name STRING NOT NULL COLLATE NOCASE, "
  58. "rname STRING NOT NULL COLLATE NOCASE, ttl INTEGER NOT NULL, "
  59. "rdtype STRING NOT NULL COLLATE NOCASE, sigtype STRING COLLATE NOCASE, "
  60. "rdata STRING NOT NULL)",
  61. "CREATE INDEX records_byname ON records (name)",
  62. "CREATE INDEX records_byrname ON records (rname)",
  63. "CREATE TABLE nsec3 (id INTEGER PRIMARY KEY, zone_id INTEGER NOT NULL, "
  64. "hash STRING NOT NULL COLLATE NOCASE, "
  65. "owner STRING NOT NULL COLLATE NOCASE, "
  66. "ttl INTEGER NOT NULL, rdtype STRING NOT NULL COLLATE NOCASE, "
  67. "rdata STRING NOT NULL)",
  68. "CREATE INDEX nsec3_byhash ON nsec3 (hash)",
  69. NULL
  70. };
  71. const char* const q_zone_str = "SELECT id FROM zones WHERE name=?1";
  72. const char* const q_record_str = "SELECT rdtype, ttl, sigtype, rdata "
  73. "FROM records WHERE zone_id=?1 AND name=?2 AND "
  74. "((rdtype=?3 OR sigtype=?3) OR "
  75. "(rdtype='CNAME' OR sigtype='CNAME') OR "
  76. "(rdtype='NS' OR sigtype='NS'))";
  77. const char* const q_addrs_str = "SELECT rdtype, ttl, sigtype, rdata "
  78. "FROM records WHERE zone_id=?1 AND name=?2 AND "
  79. "(rdtype='A' OR sigtype='A' OR rdtype='AAAA' OR sigtype='AAAA')";
  80. const char* const q_referral_str = "SELECT rdtype, ttl, sigtype, rdata FROM "
  81. "records WHERE zone_id=?1 AND name=?2 AND"
  82. "(rdtype='NS' OR sigtype='NS' OR rdtype='DS' OR sigtype='DS' OR "
  83. "rdtype='DNAME' OR sigtype='DNAME')";
  84. const char* const q_any_str = "SELECT rdtype, ttl, sigtype, rdata "
  85. "FROM records WHERE zone_id=?1 AND name=?2";
  86. const char* const q_count_str = "SELECT COUNT(*) FROM records "
  87. "WHERE zone_id=?1 AND rname LIKE (?2 || '%');";
  88. const char* const q_previous_str = "SELECT name FROM records "
  89. "WHERE zone_id=?1 AND rdtype = 'NSEC' AND "
  90. "rname < $2 ORDER BY rname DESC LIMIT 1";
  91. const char* const q_nsec3_str = "SELECT rdtype, ttl, rdata FROM nsec3 "
  92. "WHERE zone_id = ?1 AND hash = $2";
  93. const char* const q_prevnsec3_str = "SELECT hash FROM nsec3 "
  94. "WHERE zone_id = ?1 AND hash <= $2 ORDER BY hash DESC LIMIT 1";
  95. }
  96. //
  97. // Find the exact zone match. Return -1 if not found, or the zone's
  98. // ID if found. This will always be >= 0 if found.
  99. //
  100. int
  101. Sqlite3DataSrc::hasExactZone(const char* const name) const {
  102. int rc;
  103. sqlite3_reset(dbparameters->q_zone_);
  104. rc = sqlite3_bind_text(dbparameters->q_zone_, 1, name, -1, SQLITE_STATIC);
  105. if (rc != SQLITE_OK) {
  106. isc_throw(Sqlite3Error, "Could not bind " << name <<
  107. " to SQL statement (zone)");
  108. }
  109. rc = sqlite3_step(dbparameters->q_zone_);
  110. const int i = (rc == SQLITE_ROW) ?
  111. sqlite3_column_int(dbparameters->q_zone_, 0) : -1;
  112. sqlite3_reset(dbparameters->q_zone_);
  113. return (i);
  114. }
  115. namespace {
  116. int
  117. importSqlite3Rows(sqlite3_stmt* query, const Name& qname, const RRClass& qclass,
  118. const RRType& qtype, const bool nsec3_tree,
  119. RRsetList& result_sets, uint32_t& flags)
  120. {
  121. int rows = 0;
  122. int rc = sqlite3_step(query);
  123. const bool qtype_is_any = (qtype == RRType::ANY());
  124. while (rc == SQLITE_ROW) {
  125. const char* type = (const char*)sqlite3_column_text(query, 0);
  126. int ttl = sqlite3_column_int(query, 1);
  127. const char* sigtype = NULL;
  128. const char* rdata;
  129. if (nsec3_tree) {
  130. rdata = (const char*)sqlite3_column_text(query, 2);
  131. if (RRType(type) == RRType::RRSIG()) {
  132. sigtype = "NSEC3";
  133. }
  134. } else {
  135. sigtype = (const char*)sqlite3_column_text(query, 2);
  136. rdata = (const char*)sqlite3_column_text(query, 3);
  137. }
  138. const RRType base_rrtype(sigtype != NULL ? sigtype : type);
  139. // found an NS; we need to inform the caller that this might be a
  140. // referral, but we do not return the NS RRset to the caller
  141. // unless asked for it.
  142. if (base_rrtype == RRType::NS()) {
  143. flags |= DataSrc::REFERRAL;
  144. if (!qtype_is_any && qtype != RRType::NS()) {
  145. rc = sqlite3_step(query);
  146. continue;
  147. }
  148. }
  149. ++rows;
  150. // Looking for something else but found CNAME
  151. if (base_rrtype == RRType::CNAME() && qtype != RRType::CNAME()) {
  152. if (qtype == RRType::NSEC()) {
  153. // NSEC query, just skip the CNAME
  154. rc = sqlite3_step(query);
  155. continue;
  156. } else if (!qtype_is_any) {
  157. // include the CNAME, but don't flag it for chasing if
  158. // this is an ANY query
  159. flags |= DataSrc::CNAME_FOUND;
  160. }
  161. }
  162. RRsetPtr rrset = result_sets.findRRset(base_rrtype, qclass);
  163. if (rrset == NULL) {
  164. rrset = RRsetPtr(new RRset(qname, qclass, base_rrtype, RRTTL(ttl)));
  165. result_sets.addRRset(rrset);
  166. }
  167. if (sigtype == NULL && base_rrtype == rrset->getType()) {
  168. rrset->addRdata(createRdata(rrset->getType(), qclass, rdata));
  169. if (ttl > rrset->getTTL().getValue()) {
  170. rrset->setTTL(RRTTL(ttl));
  171. }
  172. } else if (sigtype != NULL && base_rrtype == rrset->getType()) {
  173. RdataPtr rrsig = createRdata(RRType::RRSIG(), qclass, rdata);
  174. if (rrset->getRRsig()) {
  175. rrset->getRRsig()->addRdata(rrsig);
  176. } else {
  177. RRsetPtr sigs = RRsetPtr(new RRset(qname, qclass,
  178. RRType::RRSIG(),
  179. RRTTL(ttl)));
  180. sigs->addRdata(rrsig);
  181. rrset->addRRsig(sigs);
  182. }
  183. if (ttl > rrset->getRRsig()->getTTL().getValue()) {
  184. rrset->getRRsig()->setTTL(RRTTL(ttl));
  185. }
  186. }
  187. rc = sqlite3_step(query);
  188. }
  189. return (rows);
  190. }
  191. }
  192. int
  193. Sqlite3DataSrc::findRecords(const Name& name, const RRType& rdtype,
  194. RRsetList& target, const Name* zonename,
  195. const Mode mode, uint32_t& flags) const
  196. {
  197. LOG_DEBUG(logger, DBG_TRACE_DETAILED, DATASRC_SQLITE_FINDREC).arg(name).
  198. arg(rdtype);
  199. flags = 0;
  200. int zone_id = (zonename == NULL) ? findClosest(name, NULL) :
  201. findClosest(*zonename, NULL);
  202. if (zone_id < 0) {
  203. flags = NO_SUCH_ZONE;
  204. return (0);
  205. }
  206. sqlite3_stmt* query;
  207. switch (mode) {
  208. case ADDRESS:
  209. query = dbparameters->q_addrs_;
  210. break;
  211. case DELEGATION:
  212. query = dbparameters->q_referral_;
  213. break;
  214. default:
  215. if (rdtype == RRType::ANY()) {
  216. query = dbparameters->q_any_;
  217. } else {
  218. query = dbparameters->q_record_;
  219. }
  220. break;
  221. }
  222. sqlite3_reset(query);
  223. sqlite3_clear_bindings(query);
  224. int rc;
  225. rc = sqlite3_bind_int(query, 1, zone_id);
  226. if (rc != SQLITE_OK) {
  227. isc_throw(Sqlite3Error, "Could not bind zone ID " << zone_id <<
  228. " to SQL statement (query)");
  229. }
  230. const string name_text = name.toText();
  231. rc = sqlite3_bind_text(query, 2, name_text.c_str(), -1, SQLITE_STATIC);
  232. if (rc != SQLITE_OK) {
  233. isc_throw(Sqlite3Error, "Could not bind name " << name_text <<
  234. " to SQL statement (query)");
  235. }
  236. const string rdtype_text = rdtype.toText();
  237. if (query == dbparameters->q_record_) {
  238. rc = sqlite3_bind_text(query, 3, rdtype_text.c_str(), -1,
  239. SQLITE_STATIC);
  240. if (rc != SQLITE_OK) {
  241. isc_throw(Sqlite3Error, "Could not bind RR type " <<
  242. rdtype.toText() << " to SQL statement (query)");
  243. }
  244. }
  245. const int rows = importSqlite3Rows(query, name, getClass(), rdtype, false,
  246. target, flags);
  247. sqlite3_reset(query);
  248. if (rows > 0) {
  249. return (rows);
  250. }
  251. //
  252. // No rows were found. We need to find out whether there are
  253. // any RRs with that name to determine whether this is NXDOMAIN or
  254. // NXRRSET
  255. //
  256. sqlite3_reset(dbparameters->q_count_);
  257. sqlite3_clear_bindings(dbparameters->q_count_);
  258. rc = sqlite3_bind_int(dbparameters->q_count_, 1, zone_id);
  259. if (rc != SQLITE_OK) {
  260. isc_throw(Sqlite3Error, "Could not bind zone ID " << zone_id <<
  261. " to SQL statement (qcount)");
  262. }
  263. const string revname_text = name.reverse().toText();
  264. rc = sqlite3_bind_text(dbparameters->q_count_, 2, revname_text.c_str(),
  265. -1, SQLITE_STATIC);
  266. if (rc != SQLITE_OK) {
  267. isc_throw(Sqlite3Error, "Could not bind name " << name.reverse() <<
  268. " to SQL statement (qcount)");
  269. }
  270. rc = sqlite3_step(dbparameters->q_count_);
  271. if (rc == SQLITE_ROW) {
  272. if (sqlite3_column_int(dbparameters->q_count_, 0) != 0) {
  273. flags |= TYPE_NOT_FOUND;
  274. sqlite3_reset(dbparameters->q_count_);
  275. return (0);
  276. }
  277. }
  278. flags |= NAME_NOT_FOUND;
  279. sqlite3_reset(dbparameters->q_count_);
  280. return (0);
  281. }
  282. //
  283. // Search for the closest enclosing zone. Will return -1 if not found,
  284. // >= 0 if found. If position is not NULL, it will be filled in with the
  285. // longest match found.
  286. //
  287. int
  288. Sqlite3DataSrc::findClosest(const Name& name, unsigned int* position) const {
  289. const unsigned int nlabels = name.getLabelCount();
  290. for (unsigned int i = 0; i < nlabels; ++i) {
  291. const Name matchname(name.split(i));
  292. const int rc = hasExactZone(matchname.toText().c_str());
  293. if (rc >= 0) {
  294. if (position != NULL) {
  295. *position = i;
  296. }
  297. return (rc);
  298. }
  299. }
  300. return (-1);
  301. }
  302. void
  303. Sqlite3DataSrc::findClosestEnclosure(DataSrcMatch& match) const {
  304. LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_SQLITE_ENCLOSURE).
  305. arg(match.getName());
  306. if (match.getClass() != getClass() && match.getClass() != RRClass::ANY()) {
  307. return;
  308. }
  309. unsigned int position;
  310. if (findClosest(match.getName(), &position) == -1) {
  311. LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_SQLITE_ENCLOSURE_NOTFOUND);
  312. return;
  313. }
  314. match.update(*this, match.getName().split(position));
  315. }
  316. DataSrc::Result
  317. Sqlite3DataSrc::findPreviousName(const Name& qname,
  318. Name& target,
  319. const Name* zonename) const
  320. {
  321. LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_SQLITE_PREVIOUS).arg(qname);
  322. const int zone_id = (zonename == NULL) ?
  323. findClosest(qname, NULL) : findClosest(*zonename, NULL);
  324. if (zone_id < 0) {
  325. LOG_ERROR(logger, DATASRC_SQLITE_PREVIOUS_NO_ZONE).arg(qname.toText());
  326. return (ERROR);
  327. }
  328. sqlite3_reset(dbparameters->q_previous_);
  329. sqlite3_clear_bindings(dbparameters->q_previous_);
  330. int rc = sqlite3_bind_int(dbparameters->q_previous_, 1, zone_id);
  331. if (rc != SQLITE_OK) {
  332. isc_throw(Sqlite3Error, "Could not bind zone ID " << zone_id <<
  333. " to SQL statement (qprevious)");
  334. }
  335. const string revname_text = qname.reverse().toText();
  336. rc = sqlite3_bind_text(dbparameters->q_previous_, 2,
  337. revname_text.c_str(), -1, SQLITE_STATIC);
  338. if (rc != SQLITE_OK) {
  339. isc_throw(Sqlite3Error, "Could not bind name " << qname <<
  340. " to SQL statement (qprevious)");
  341. }
  342. rc = sqlite3_step(dbparameters->q_previous_);
  343. if (rc != SQLITE_ROW) {
  344. sqlite3_reset(dbparameters->q_previous_);
  345. return (ERROR);
  346. }
  347. // XXX: bad cast. we should revisit this.
  348. target = Name((const char*)sqlite3_column_text(dbparameters->q_previous_,
  349. 0));
  350. sqlite3_reset(dbparameters->q_previous_);
  351. return (SUCCESS);
  352. }
  353. DataSrc::Result
  354. Sqlite3DataSrc::findCoveringNSEC3(const Name& zonename,
  355. string& hashstr,
  356. RRsetList& target) const
  357. {
  358. LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_SQLITE_FIND_NSEC3).
  359. arg(zonename).arg(hashstr);
  360. const int zone_id = findClosest(zonename, NULL);
  361. if (zone_id < 0) {
  362. LOG_ERROR(logger, DATASRC_SQLITE_FIND_NSEC3_NO_ZONE).arg(zonename);
  363. return (ERROR);
  364. }
  365. sqlite3_reset(dbparameters->q_prevnsec3_);
  366. sqlite3_clear_bindings(dbparameters->q_prevnsec3_);
  367. int rc = sqlite3_bind_int(dbparameters->q_prevnsec3_, 1, zone_id);
  368. if (rc != SQLITE_OK) {
  369. isc_throw(Sqlite3Error, "Could not bind zone ID " << zone_id <<
  370. " to SQL statement (previous NSEC3)");
  371. }
  372. rc = sqlite3_bind_text(dbparameters->q_prevnsec3_, 2, hashstr.c_str(),
  373. -1, SQLITE_STATIC);
  374. if (rc != SQLITE_OK) {
  375. isc_throw(Sqlite3Error, "Could not bind hash " << hashstr <<
  376. " to SQL statement (previous NSEC3)");
  377. }
  378. rc = sqlite3_step(dbparameters->q_prevnsec3_);
  379. const char* hash;
  380. if (rc == SQLITE_ROW) {
  381. hash = (const char*) sqlite3_column_text(dbparameters->q_prevnsec3_, 0);
  382. } else {
  383. // We need to find the final NSEC3 in the chain.
  384. // A valid NSEC3 hash is in base32, which contains no
  385. // letters higher than V, so a search for the previous
  386. // NSEC3 from "w" will always find it.
  387. sqlite3_reset(dbparameters->q_prevnsec3_);
  388. rc = sqlite3_bind_text(dbparameters->q_prevnsec3_, 2, "w", -1,
  389. SQLITE_STATIC);
  390. if (rc != SQLITE_OK) {
  391. isc_throw(Sqlite3Error, "Could not bind \"w\""
  392. " to SQL statement (previous NSEC3)");
  393. }
  394. rc = sqlite3_step(dbparameters->q_prevnsec3_);
  395. if (rc != SQLITE_ROW) {
  396. return (ERROR);
  397. }
  398. hash = (const char*) sqlite3_column_text(dbparameters->q_prevnsec3_, 0);
  399. }
  400. sqlite3_reset(dbparameters->q_nsec3_);
  401. sqlite3_clear_bindings(dbparameters->q_nsec3_);
  402. rc = sqlite3_bind_int(dbparameters->q_nsec3_, 1, zone_id);
  403. if (rc != SQLITE_OK) {
  404. isc_throw(Sqlite3Error, "Could not bind zone ID " << zone_id <<
  405. " to SQL statement (NSEC3)");
  406. }
  407. rc = sqlite3_bind_text(dbparameters->q_nsec3_, 2, hash, -1, SQLITE_STATIC);
  408. if (rc != SQLITE_OK) {
  409. isc_throw(Sqlite3Error, "Could not bind hash " << hash <<
  410. " to SQL statement (NSEC3)");
  411. }
  412. DataSrc::Result result = SUCCESS;
  413. uint32_t flags = 0;
  414. if (importSqlite3Rows(dbparameters->q_nsec3_,
  415. Name(hash).concatenate(zonename),
  416. getClass(), RRType::NSEC3(), true, target,
  417. flags) == 0 || flags != 0) {
  418. result = ERROR;
  419. }
  420. hashstr = string(hash);
  421. sqlite3_reset(dbparameters->q_nsec3_);
  422. return (result);
  423. }
  424. DataSrc::Result
  425. Sqlite3DataSrc::findRRset(const Name& qname,
  426. const RRClass& qclass,
  427. const RRType& qtype,
  428. RRsetList& target,
  429. uint32_t& flags,
  430. const Name* zonename) const
  431. {
  432. LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_SQLITE_FIND).arg(qname).
  433. arg(qtype);
  434. if (qclass != getClass() && qclass != RRClass::ANY()) {
  435. LOG_ERROR(logger, DATASRC_SQLITE_FIND_BAD_CLASS).arg(getClass()).
  436. arg(qclass);
  437. return (ERROR);
  438. }
  439. findRecords(qname, qtype, target, zonename, NORMAL, flags);
  440. return (SUCCESS);
  441. }
  442. DataSrc::Result
  443. Sqlite3DataSrc::findExactRRset(const Name& qname,
  444. const RRClass& qclass,
  445. const RRType& qtype,
  446. RRsetList& target,
  447. uint32_t& flags,
  448. const Name* zonename) const
  449. {
  450. LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_SQLITE_FINDEXACT).arg(qname).
  451. arg(qtype);
  452. if (qclass != getClass() && qclass != RRClass::ANY()) {
  453. LOG_ERROR(logger, DATASRC_SQLITE_FINDEXACT_BAD_CLASS).arg(getClass()).
  454. arg(qclass);
  455. return (ERROR);
  456. }
  457. findRecords(qname, qtype, target, zonename, NORMAL, flags);
  458. // Ignore referrals in this case
  459. flags &= ~REFERRAL;
  460. // CNAMEs don't count in this case
  461. if (flags & CNAME_FOUND) {
  462. flags &= ~CNAME_FOUND;
  463. flags |= TYPE_NOT_FOUND;
  464. }
  465. return (SUCCESS);
  466. }
  467. DataSrc::Result
  468. Sqlite3DataSrc::findAddrs(const Name& qname,
  469. const RRClass& qclass,
  470. RRsetList& target,
  471. uint32_t& flags,
  472. const Name* zonename) const
  473. {
  474. LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_SQLITE_FINDADDRS).arg(qname);
  475. if (qclass != getClass() && qclass != RRClass::ANY()) {
  476. LOG_ERROR(logger, DATASRC_SQLITE_FINDADDRS_BAD_CLASS).arg(getClass()).
  477. arg(qclass);
  478. return (ERROR);
  479. }
  480. findRecords(qname, RRType::ANY(), target, zonename, ADDRESS, flags);
  481. return (SUCCESS);
  482. }
  483. DataSrc::Result
  484. Sqlite3DataSrc::findReferral(const Name& qname,
  485. const RRClass& qclass,
  486. RRsetList& target,
  487. uint32_t& flags,
  488. const Name* zonename) const
  489. {
  490. LOG_DEBUG(logger, DBG_TRACE_DATA, DATASRC_SQLITE_FINDREF).arg(qname);
  491. if (qclass != getClass() && qclass != RRClass::ANY()) {
  492. LOG_ERROR(logger, DATASRC_SQLITE_FINDREF_BAD_CLASS).arg(getClass()).
  493. arg(qclass);
  494. return (ERROR);
  495. }
  496. findRecords(qname, RRType::ANY(), target, zonename, DELEGATION, flags);
  497. return (SUCCESS);
  498. }
  499. Sqlite3DataSrc::Sqlite3DataSrc() :
  500. dbparameters(new Sqlite3Parameters)
  501. {
  502. LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_SQLITE_CREATE);
  503. }
  504. Sqlite3DataSrc::~Sqlite3DataSrc() {
  505. LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_SQLITE_DESTROY);
  506. if (dbparameters->db_ != NULL) {
  507. close();
  508. }
  509. delete dbparameters;
  510. }
  511. DataSrc::Result
  512. Sqlite3DataSrc::init(isc::data::ConstElementPtr config) {
  513. if (config && config->contains("database_file")) {
  514. open(config->get("database_file")->stringValue());
  515. } else {
  516. isc_throw(DataSourceError, "No SQLite database file specified");
  517. }
  518. return (SUCCESS);
  519. }
  520. namespace {
  521. // This is a helper class to initialize a Sqlite3 DB safely. An object of
  522. // this class encapsulates all temporary resources that are necessary for
  523. // the initialization, and release them in the destructor. Once everything
  524. // is properly initialized, the move() method moves the allocated resources
  525. // to the main object in an exception free manner. This way, the main code
  526. // for the initialization can be exception safe, and can provide the strong
  527. // exception guarantee.
  528. class Sqlite3Initializer {
  529. public:
  530. ~Sqlite3Initializer() {
  531. if (params_.q_zone_ != NULL) {
  532. sqlite3_finalize(params_.q_zone_);
  533. }
  534. if (params_.q_record_ != NULL) {
  535. sqlite3_finalize(params_.q_record_);
  536. }
  537. if (params_.q_addrs_ != NULL) {
  538. sqlite3_finalize(params_.q_addrs_);
  539. }
  540. if (params_.q_referral_ != NULL) {
  541. sqlite3_finalize(params_.q_referral_);
  542. }
  543. if (params_.q_any_ != NULL) {
  544. sqlite3_finalize(params_.q_any_);
  545. }
  546. if (params_.q_count_ != NULL) {
  547. sqlite3_finalize(params_.q_count_);
  548. }
  549. if (params_.q_previous_ != NULL) {
  550. sqlite3_finalize(params_.q_previous_);
  551. }
  552. if (params_.q_nsec3_ != NULL) {
  553. sqlite3_finalize(params_.q_nsec3_);
  554. }
  555. if (params_.q_prevnsec3_ != NULL) {
  556. sqlite3_finalize(params_.q_prevnsec3_);
  557. }
  558. if (params_.db_ != NULL) {
  559. sqlite3_close(params_.db_);
  560. }
  561. }
  562. void move(Sqlite3Parameters* dst) {
  563. *dst = params_;
  564. params_ = Sqlite3Parameters(); // clear everything
  565. }
  566. Sqlite3Parameters params_;
  567. };
  568. sqlite3_stmt*
  569. prepare(sqlite3* const db, const char* const statement) {
  570. sqlite3_stmt* prepared = NULL;
  571. if (sqlite3_prepare_v2(db, statement, -1, &prepared, NULL) != SQLITE_OK) {
  572. isc_throw(Sqlite3Error, "Could not prepare SQLite statement: " <<
  573. statement);
  574. }
  575. return (prepared);
  576. }
  577. void
  578. checkAndSetupSchema(Sqlite3Initializer* initializer) {
  579. sqlite3* const db = initializer->params_.db_;
  580. sqlite3_stmt* prepared = NULL;
  581. if (sqlite3_prepare_v2(db, "SELECT version FROM schema_version", -1,
  582. &prepared, NULL) == SQLITE_OK &&
  583. sqlite3_step(prepared) == SQLITE_ROW) {
  584. initializer->params_.version_ = sqlite3_column_int(prepared, 0);
  585. sqlite3_finalize(prepared);
  586. } else {
  587. logger.info(DATASRC_SQLITE_SETUP);
  588. if (prepared != NULL) {
  589. sqlite3_finalize(prepared);
  590. }
  591. for (int i = 0; SCHEMA_LIST[i] != NULL; ++i) {
  592. if (sqlite3_exec(db, SCHEMA_LIST[i], NULL, NULL, NULL) !=
  593. SQLITE_OK) {
  594. isc_throw(Sqlite3Error,
  595. "Failed to set up schema " << SCHEMA_LIST[i]);
  596. }
  597. }
  598. }
  599. initializer->params_.q_zone_ = prepare(db, q_zone_str);
  600. initializer->params_.q_record_ = prepare(db, q_record_str);
  601. initializer->params_.q_addrs_ = prepare(db, q_addrs_str);
  602. initializer->params_.q_referral_ = prepare(db, q_referral_str);
  603. initializer->params_.q_any_ = prepare(db, q_any_str);
  604. initializer->params_.q_count_ = prepare(db, q_count_str);
  605. initializer->params_.q_previous_ = prepare(db, q_previous_str);
  606. initializer->params_.q_nsec3_ = prepare(db, q_nsec3_str);
  607. initializer->params_.q_prevnsec3_ = prepare(db, q_prevnsec3_str);
  608. }
  609. }
  610. //
  611. // Open the database.
  612. //
  613. void
  614. Sqlite3DataSrc::open(const string& name) {
  615. LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_SQLITE_OPEN).arg(name);
  616. if (dbparameters->db_ != NULL) {
  617. isc_throw(DataSourceError, "Duplicate SQLite open with " << name);
  618. }
  619. Sqlite3Initializer initializer;
  620. if (sqlite3_open(name.c_str(), &initializer.params_.db_) != 0) {
  621. isc_throw(Sqlite3Error, "Cannot open SQLite database file: " << name);
  622. }
  623. checkAndSetupSchema(&initializer);
  624. initializer.move(dbparameters);
  625. }
  626. //
  627. // Close the database.
  628. //
  629. DataSrc::Result
  630. Sqlite3DataSrc::close(void) {
  631. LOG_DEBUG(logger, DBG_TRACE_BASIC, DATASRC_SQLITE_CLOSE);
  632. if (dbparameters->db_ == NULL) {
  633. isc_throw(DataSourceError,
  634. "SQLite data source is being closed before open");
  635. }
  636. // XXX: sqlite3_finalize() could fail. What should we do in that case?
  637. sqlite3_finalize(dbparameters->q_zone_);
  638. dbparameters->q_zone_ = NULL;
  639. sqlite3_finalize(dbparameters->q_record_);
  640. dbparameters->q_record_ = NULL;
  641. sqlite3_finalize(dbparameters->q_addrs_);
  642. dbparameters->q_addrs_ = NULL;
  643. sqlite3_finalize(dbparameters->q_referral_);
  644. dbparameters->q_referral_ = NULL;
  645. sqlite3_finalize(dbparameters->q_any_);
  646. dbparameters->q_any_ = NULL;
  647. sqlite3_finalize(dbparameters->q_count_);
  648. dbparameters->q_count_ = NULL;
  649. sqlite3_finalize(dbparameters->q_previous_);
  650. dbparameters->q_previous_ = NULL;
  651. sqlite3_finalize(dbparameters->q_prevnsec3_);
  652. dbparameters->q_prevnsec3_ = NULL;
  653. sqlite3_finalize(dbparameters->q_nsec3_);
  654. dbparameters->q_nsec3_ = NULL;
  655. sqlite3_close(dbparameters->db_);
  656. dbparameters->db_ = NULL;
  657. return (SUCCESS);
  658. }
  659. }
  660. }