data_source_sqlite3.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  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 "data_source_sqlite3.h"
  16. #include <dns/rrttl.h>
  17. #include <dns/rdata.h>
  18. #include <dns/rdataclass.h>
  19. #include <dns/rrset.h>
  20. #include <dns/rrsetlist.h>
  21. #include <iostream>
  22. using namespace std;
  23. using namespace isc::dns;
  24. using namespace isc::dns::rdata;
  25. namespace isc {
  26. namespace auth {
  27. //
  28. // Prepare a statement. Can call release() or sqlite3_finalize()
  29. // directly.
  30. //
  31. sqlite3_stmt* Sqlite3DataSrc::prepare(const char *statement) {
  32. int rc;
  33. sqlite3_stmt *prepared = NULL;
  34. rc = sqlite3_prepare_v2(db, statement, -1, &prepared, NULL);
  35. if (rc != SQLITE_OK) {
  36. throw("could not prepare");
  37. }
  38. return (prepared);
  39. }
  40. //
  41. // Release memory associated with a prepared query.
  42. //
  43. void Sqlite3DataSrc::release(sqlite3_stmt* prepared) {
  44. sqlite3_finalize(prepared);
  45. }
  46. //
  47. // Get the database schema version.
  48. //
  49. int Sqlite3DataSrc::getVersion(void) {
  50. if (database_version == -1) {
  51. loadVersion();
  52. }
  53. return (database_version);
  54. }
  55. //
  56. // Find the exact zone match. Return -1 if not found, or the zone's
  57. // ID if found. This will always be >= 0 if found.
  58. //
  59. int Sqlite3DataSrc::hasExactZone(const char *name) const {
  60. int rc, i;
  61. sqlite3_reset(q_zone);
  62. rc = sqlite3_bind_text(q_zone, 1, name, -1, SQLITE_STATIC);
  63. if (rc != SQLITE_OK) {
  64. throw("Could not bind");
  65. }
  66. rc = sqlite3_step(q_zone);
  67. if (rc == SQLITE_ROW) {
  68. i = sqlite3_column_int(q_zone, 0);
  69. } else {
  70. i = -1;
  71. }
  72. sqlite3_reset(q_zone);
  73. return (i);
  74. }
  75. int
  76. Sqlite3DataSrc::
  77. findRecords(const Name& name, const RRType& rdtype, RRsetList& target,
  78. Name* zone, const Mode mode, uint32_t& flags) const
  79. {
  80. int rc;
  81. const string s_name = name.toText();
  82. const char *c_name = s_name.c_str();
  83. const string s_rdtype = rdtype.toText();
  84. const char *c_rdtype = s_rdtype.c_str();
  85. sqlite3_stmt *query;
  86. switch (mode) {
  87. case ADDRESS:
  88. query = q_addrs;
  89. break;
  90. case DELEGATION:
  91. query = q_referral;
  92. break;
  93. default:
  94. if (rdtype == RRType::ANY()) {
  95. query = q_any;
  96. } else {
  97. query = q_record;
  98. }
  99. break;
  100. }
  101. flags = 0;
  102. int zone_id;
  103. if (zone == NULL) {
  104. zone_id = findClosest(c_name, NULL);
  105. } else {
  106. const string s_zone = zone->toText();
  107. const char *c_zone = s_zone.c_str();
  108. zone_id = findClosest(c_zone, NULL);
  109. }
  110. if (zone_id < 0) {
  111. flags = NO_SUCH_ZONE;
  112. return (0);
  113. }
  114. sqlite3_reset(query);
  115. sqlite3_clear_bindings(query);
  116. rc = sqlite3_bind_int(query, 1, zone_id);
  117. if (rc != SQLITE_OK) {
  118. throw("Could not bind 1 (record)");
  119. }
  120. rc = sqlite3_bind_text(query, 2, c_name, -1, SQLITE_STATIC);
  121. if (rc != SQLITE_OK) {
  122. throw("Could not bind 2 (record)");
  123. }
  124. if (query == q_record) {
  125. rc = sqlite3_bind_text(query, 3, c_rdtype, -1, SQLITE_STATIC);
  126. if (rc != SQLITE_OK) {
  127. throw("Could not bind 3 (record)");
  128. }
  129. }
  130. // loop
  131. int target_ttl = -1;
  132. int sig_ttl = -1;
  133. int rows = 0;
  134. RRsetPtr rrset;
  135. bool any = (rdtype == RRType::ANY());
  136. rc = sqlite3_step(query);
  137. while (rc == SQLITE_ROW) {
  138. const char *type = (const char *)sqlite3_column_text(query, 0);
  139. int ttl = sqlite3_column_int(query, 1);
  140. const char *sigtype = (const char *)sqlite3_column_text(query, 2);
  141. const char *rdata = (const char *)sqlite3_column_text(query, 3);
  142. RRType rt(sigtype ? sigtype : type);
  143. // looking for something else but found NS; we need to inform
  144. // the caller that this is a referral, but we do not return the
  145. // NS RRset to the caller.
  146. if (rdtype != RRType::NS() && !any && rt == RRType::NS()) {
  147. flags |= REFERRAL;
  148. rc = sqlite3_step(query);
  149. continue;
  150. }
  151. rows++;
  152. // Looking for something else but found CNAME
  153. if (rt == RRType::CNAME() && rdtype != RRType::CNAME()) {
  154. if (rdtype == RRType::NSEC()) {
  155. // NSEC query, just skip the CNAME
  156. rc = sqlite3_step(query);
  157. continue;
  158. } else if (!any) {
  159. // include the CNAME, but don't flag it for chasing if
  160. // this is an ANY query
  161. flags |= CNAME_FOUND;
  162. }
  163. }
  164. if (!target[rt]) {
  165. rrset = RRsetPtr(new RRset(name, RRClass::IN(), rt, RRTTL(3600)));
  166. target.addRRset(rrset);
  167. }
  168. if (!sigtype && RRType(type) == rrset->getType()) {
  169. RdataPtr item = createRdata(RRType(type), RRClass("IN"), rdata);
  170. rrset->addRdata(item);
  171. if (target_ttl == -1 || target_ttl > ttl) {
  172. target_ttl = ttl;
  173. }
  174. rrset->setTTL(RRTTL(target_ttl));
  175. } else if (sigtype && RRType(sigtype) == rrset->getType()) {
  176. RdataPtr rrsig = createRdata(RRType::RRSIG(), RRClass::IN(), rdata);
  177. if (rrset->getRRsig()) {
  178. rrset->getRRsig()->addRdata(rrsig);
  179. } else {
  180. RRsetPtr sigs = RRsetPtr(new RRset(name, RRClass::IN(),
  181. RRType::RRSIG(),
  182. RRTTL(3600)));
  183. sigs->addRdata(rrsig);
  184. rrset->addRRsig(sigs);
  185. }
  186. if (sig_ttl == -1 || sig_ttl > ttl) {
  187. sig_ttl = ttl;
  188. }
  189. rrset->getRRsig()->setTTL(RRTTL(sig_ttl));
  190. }
  191. rc = sqlite3_step(query);
  192. }
  193. sqlite3_reset(query);
  194. if (rows > 0) {
  195. return (rows);
  196. }
  197. //
  198. // No rows were found. We need to find out whether there are
  199. // any RRs with that name to determine whether this is NXDOMAIN or
  200. // NXRRSET
  201. //
  202. sqlite3_reset(q_count);
  203. sqlite3_clear_bindings(q_count);
  204. rc = sqlite3_bind_int(q_count, 1, zone_id);
  205. if (rc != SQLITE_OK) {
  206. throw("Could not bind 1 (count)");
  207. }
  208. rc = sqlite3_bind_text(q_count, 2, c_name, -1, SQLITE_STATIC);
  209. if (rc != SQLITE_OK) {
  210. throw("Could not bind 2 (count)");
  211. }
  212. rc = sqlite3_step(q_count);
  213. if(rc == SQLITE_ROW) {
  214. int count = sqlite3_column_int(q_count, 0);
  215. if (count != 0) {
  216. flags |= TYPE_NOT_FOUND;
  217. sqlite3_reset(q_count);
  218. return (0);
  219. }
  220. }
  221. flags |= NAME_NOT_FOUND;
  222. sqlite3_reset(q_count);
  223. return (0);
  224. }
  225. //
  226. // Search for the closest enclosing zone. Will return -1 if not found,
  227. // >= 0 if found. If position is not NULL, it will be filled in with the
  228. // longest match found.
  229. //
  230. int Sqlite3DataSrc::findClosest(const char *name, const char **position) const {
  231. int rc;
  232. const char *current = name;
  233. while (*current != 0) {
  234. rc = hasExactZone(current);
  235. if (rc >= 0) {
  236. if (position != NULL) {
  237. *position = current;
  238. }
  239. return (rc);
  240. }
  241. while (*current != '.' && *current != 0) {
  242. current++;
  243. }
  244. if (*current == '.') {
  245. current++;
  246. }
  247. }
  248. return (-1);
  249. }
  250. void Sqlite3DataSrc::loadVersion(void) {
  251. int rc;
  252. const char *q = "SELECT version FROM schema_version";
  253. sqlite3_stmt *prepared = prepare(q);
  254. rc = sqlite3_step(prepared);
  255. if (rc != SQLITE_ROW) {
  256. throw("failed to find a row in schema_version table");
  257. }
  258. database_version = sqlite3_column_int(prepared, 0);
  259. release(prepared);
  260. }
  261. void Sqlite3DataSrc::setupPreparedStatements(void) {
  262. const char *q_zone_str = "SELECT id FROM zones WHERE name=?1";
  263. try {
  264. q_zone = prepare(q_zone_str);
  265. } catch (const char *e) {
  266. cout << e << endl << q_zone_str << endl;
  267. cout << sqlite3_errmsg(db) << endl;
  268. throw(e);
  269. }
  270. const char *q_record_str = "SELECT rdtype, ttl, sigtype, rdata "
  271. "FROM records WHERE zone_id=?1 AND name=?2 AND "
  272. "((rdtype=?3 OR sigtype=?3) OR "
  273. "(rdtype='CNAME' OR sigtype='CNAME') OR "
  274. "(rdtype='NS' OR sigtype='NS'))";
  275. try {
  276. q_record = prepare(q_record_str);
  277. } catch (const char *e) {
  278. cout << e << endl << q_record_str << endl;
  279. cout << sqlite3_errmsg(db) << endl;
  280. throw(e);
  281. }
  282. const char *q_addrs_str = "SELECT rdtype, ttl, sigtype, rdata "
  283. "FROM records WHERE zone_id=?1 AND name=?2 AND "
  284. "(rdtype='A' OR sigtype='A' OR "
  285. "rdtype='AAAA' OR sigtype='AAAA')";
  286. try {
  287. q_addrs = prepare(q_addrs_str);
  288. } catch (const char *e) {
  289. cout << e << endl << q_addrs_str << endl;
  290. cout << sqlite3_errmsg(db) << endl;
  291. throw(e);
  292. }
  293. const char *q_referral_str = "SELECT rdtype, ttl, sigtype, rdata FROM "
  294. "records WHERE zone_id=?1 AND name=?2 AND"
  295. "(rdtype='NS' OR sigtype='NS' OR "
  296. "rdtype='DS' OR sigtype='DS' OR "
  297. "rdtype='DNAME' OR sigtype='DNAME')";
  298. try {
  299. q_referral = prepare(q_referral_str);
  300. } catch (const char *e) {
  301. cout << e << endl << q_referral_str << endl;
  302. cout << sqlite3_errmsg(db) << endl;
  303. throw(e);
  304. }
  305. const char *q_any_str = "SELECT rdtype, ttl, sigtype, rdata "
  306. "FROM records WHERE zone_id=?1 AND name=?2";
  307. try {
  308. q_any = prepare(q_any_str);
  309. } catch (const char *e) {
  310. cout << e << endl << q_any_str << endl;
  311. cout << sqlite3_errmsg(db) << endl;
  312. throw(e);
  313. }
  314. const char *q_count_str = "SELECT COUNT(*) FROM records "
  315. "WHERE zone_id=?1 AND (name=?2 OR "
  316. "name LIKE '%.' || ?2);";
  317. try {
  318. q_count = prepare(q_count_str);
  319. } catch (const char *e) {
  320. cout << e << endl << q_count_str << endl;
  321. cout << sqlite3_errmsg(db) << endl;
  322. throw(e);
  323. }
  324. const char *q_previous_str = "SELECT name FROM records "
  325. "WHERE zone_id=?1 AND rdtype = 'NSEC' AND "
  326. "rname < $2 ORDER BY rname DESC LIMIT 1";
  327. try {
  328. q_previous = prepare(q_previous_str);
  329. } catch (const char *e) {
  330. cout << e << endl << q_previous_str << endl;
  331. cout << sqlite3_errmsg(db) << endl;
  332. throw(e);
  333. }
  334. }
  335. void Sqlite3DataSrc::execSetupQuery(const char *query) {
  336. int rc;
  337. rc = sqlite3_exec(db, query, NULL, NULL, NULL);
  338. if (rc != SQLITE_OK) {
  339. throw(query);
  340. }
  341. }
  342. void Sqlite3DataSrc::checkAndSetupSchema(void) {
  343. try {
  344. loadVersion();
  345. setupPreparedStatements();
  346. cout << "Loaded existing schema" << endl;
  347. } catch(...) {
  348. execSetupQuery("CREATE TABLE schema_version ("
  349. "version INTEGER NOT NULL)");
  350. execSetupQuery("INSERT INTO schema_version VALUES (1)");
  351. execSetupQuery("CREATE TABLE zones ("
  352. "id INTEGER PRIMARY KEY, "
  353. "name STRING NOT NULL, "
  354. "rdclass STRING NOT NULL DEFAULT 'IN', "
  355. "dnssec BOOLEAN NOT NULL DEFAULT 0)");
  356. execSetupQuery("CREATE TABLE records ("
  357. "id INTEGER PRIMARY KEY, "
  358. "zone_id INTEGER NOT NULL, "
  359. "name STRING NOT NULL, "
  360. "rname STRING NOT NULL, "
  361. "ttl INTEGER NOT NULL, "
  362. "rdtype STRING NOT NULL, "
  363. "sigtype STRING, "
  364. "rdata STRING NOT NULL)");
  365. execSetupQuery("CREATE INDEX records_byname ON records (name)");
  366. execSetupQuery("CREATE INDEX records_byrname ON records (rname)");
  367. execSetupQuery("CREATE INDEX zones_byname ON zones (name)");
  368. setupPreparedStatements();
  369. cout << "Created new file and schema" << endl;
  370. }
  371. }
  372. Sqlite3DataSrc::Sqlite3DataSrc()
  373. {
  374. db = NULL;
  375. database_version = -1;
  376. q_zone = NULL;
  377. q_record = NULL;
  378. q_addrs = NULL;
  379. q_referral = NULL;
  380. q_any = NULL;
  381. q_count = NULL;
  382. q_previous = NULL;
  383. }
  384. Sqlite3DataSrc::~Sqlite3DataSrc()
  385. {
  386. close();
  387. }
  388. DataSrc::Result
  389. Sqlite3DataSrc::init()
  390. {
  391. try {
  392. open("/tmp/zone.sqlite3");
  393. cout << "Schema version: " << getVersion() << endl;
  394. } catch (const char *e) {
  395. cout << e << endl;
  396. }
  397. return (SUCCESS);
  398. }
  399. void
  400. Sqlite3DataSrc::findClosestEnclosure(NameMatch& match) const {
  401. const Name& qname = match.qname();
  402. const string target_string = qname.toText();
  403. const char *position = NULL;
  404. int ret = findClosest(target_string.c_str(), &position);
  405. if (ret == -1) {
  406. return;
  407. }
  408. match.update(*this, Name(position));
  409. }
  410. DataSrc::Result
  411. Sqlite3DataSrc::findPreviousName(const Query& q,
  412. const Name& qname,
  413. Name& target,
  414. Name* zone) const
  415. {
  416. const char *c_rname = qname.reverse().toText().c_str();
  417. int zone_id;
  418. if (zone == NULL) {
  419. const char *c_name = qname.toText().c_str();
  420. zone_id = findClosest(c_name, NULL);
  421. } else {
  422. const char *c_zone = zone->toText().c_str();
  423. zone_id = findClosest(c_zone, NULL);
  424. }
  425. if (zone_id < 0) {
  426. return (ERROR);
  427. }
  428. sqlite3_reset(q_previous);
  429. sqlite3_clear_bindings(q_previous);
  430. int rc = sqlite3_bind_int(q_previous, 1, zone_id);
  431. if (rc != SQLITE_OK) {
  432. throw ("Could not bind 1 (record)");
  433. }
  434. rc = sqlite3_bind_text(q_previous, 2, c_rname, -1, SQLITE_STATIC);
  435. if (rc != SQLITE_OK) {
  436. throw ("Could not bind 2 (record)");
  437. }
  438. rc = sqlite3_step(q_previous);
  439. if (rc != SQLITE_ROW) {
  440. sqlite3_reset(q_previous);
  441. return (ERROR);
  442. }
  443. const char *prev = (const char *) sqlite3_column_text(q_previous, 0);
  444. target = Name(prev);
  445. sqlite3_reset(q_previous);
  446. return (SUCCESS);
  447. }
  448. DataSrc::Result
  449. Sqlite3DataSrc::findRRset(const Query& q,
  450. const Name& qname,
  451. const RRClass& qclass,
  452. const RRType& qtype,
  453. RRsetList& target,
  454. uint32_t& flags,
  455. Name* zone) const
  456. {
  457. findRecords(qname, qtype, target, zone, NORMAL, flags);
  458. return (SUCCESS);
  459. }
  460. DataSrc::Result
  461. Sqlite3DataSrc::findExactRRset(const Query& q,
  462. const Name& qname,
  463. const RRClass& qclass,
  464. const RRType& qtype,
  465. RRsetList& target,
  466. uint32_t& flags,
  467. Name* zone) const
  468. {
  469. findRecords(qname, qtype, target, zone, NORMAL, flags);
  470. // Ignore referrals in this case
  471. flags &= ~REFERRAL;
  472. // CNAMEs don't count in this case
  473. if (flags & CNAME_FOUND) {
  474. flags &= ~CNAME_FOUND;
  475. flags |= TYPE_NOT_FOUND;
  476. }
  477. return (SUCCESS);
  478. }
  479. DataSrc::Result
  480. Sqlite3DataSrc::findAddrs(const Query& q,
  481. const Name& qname,
  482. const RRClass& qclass,
  483. RRsetList& target,
  484. uint32_t& flags,
  485. Name* zone) const {
  486. findRecords(qname, RRType::ANY(), target, zone, ADDRESS, flags);
  487. return (SUCCESS);
  488. }
  489. DataSrc::Result
  490. Sqlite3DataSrc::findReferral(const Query& q,
  491. const Name& qname,
  492. const RRClass& qclass,
  493. RRsetList& target,
  494. uint32_t& flags,
  495. Name* zone) const {
  496. findRecords(qname, RRType::ANY(), target, zone, DELEGATION, flags);
  497. return (SUCCESS);
  498. }
  499. //
  500. // Open the database.
  501. //
  502. void
  503. Sqlite3DataSrc::open(const string& name)
  504. {
  505. int rc;
  506. database_name = name;
  507. rc = sqlite3_open(database_name.c_str(), &db);
  508. if (rc) {
  509. cerr << "open database: " << sqlite3_errmsg(db) << "\n";
  510. sqlite3_close(db);
  511. throw("Cannot open database");
  512. }
  513. checkAndSetupSchema();
  514. }
  515. DataSrc::Result
  516. Sqlite3DataSrc::close(void)
  517. {
  518. if (db == NULL) {
  519. return (SUCCESS);
  520. }
  521. if (q_zone != NULL) {
  522. release(q_zone);
  523. q_zone = NULL;
  524. }
  525. if (q_record) {
  526. release(q_record);
  527. q_record = NULL;
  528. }
  529. if (q_addrs) {
  530. release(q_addrs);
  531. q_addrs = NULL;
  532. }
  533. if (q_referral) {
  534. release(q_referral);
  535. q_referral = NULL;
  536. }
  537. if (q_any) {
  538. release(q_any);
  539. q_any = NULL;
  540. }
  541. if (q_count) {
  542. release(q_count);
  543. q_count = NULL;
  544. }
  545. if (q_previous) {
  546. release(q_previous);
  547. q_previous = NULL;
  548. }
  549. sqlite3_close(db);
  550. db = NULL;
  551. return (SUCCESS);
  552. }
  553. }
  554. }