/contrib/bind9/lib/dns/sdb.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1590 lines · 1247 code · 256 blank · 87 comment · 276 complexity · b7051583d80eca22437965b1317cc7da MD5 · raw file

  1. /*
  2. * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  10. * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  11. * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  12. * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  13. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  14. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15. * PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /* $Id$ */
  18. /*! \file */
  19. #include <config.h>
  20. #include <string.h>
  21. #include <isc/buffer.h>
  22. #include <isc/lex.h>
  23. #include <isc/log.h>
  24. #include <isc/magic.h>
  25. #include <isc/mem.h>
  26. #include <isc/once.h>
  27. #include <isc/print.h>
  28. #include <isc/region.h>
  29. #include <isc/util.h>
  30. #include <dns/callbacks.h>
  31. #include <dns/db.h>
  32. #include <dns/dbiterator.h>
  33. #include <dns/fixedname.h>
  34. #include <dns/log.h>
  35. #include <dns/rdata.h>
  36. #include <dns/rdatalist.h>
  37. #include <dns/rdataset.h>
  38. #include <dns/rdatasetiter.h>
  39. #include <dns/rdatatype.h>
  40. #include <dns/result.h>
  41. #include <dns/sdb.h>
  42. #include <dns/types.h>
  43. #include "rdatalist_p.h"
  44. struct dns_sdbimplementation {
  45. const dns_sdbmethods_t *methods;
  46. void *driverdata;
  47. unsigned int flags;
  48. isc_mem_t *mctx;
  49. isc_mutex_t driverlock;
  50. dns_dbimplementation_t *dbimp;
  51. };
  52. struct dns_sdb {
  53. /* Unlocked */
  54. dns_db_t common;
  55. char *zone;
  56. dns_sdbimplementation_t *implementation;
  57. void *dbdata;
  58. isc_mutex_t lock;
  59. /* Locked */
  60. unsigned int references;
  61. };
  62. struct dns_sdblookup {
  63. /* Unlocked */
  64. unsigned int magic;
  65. dns_sdb_t *sdb;
  66. ISC_LIST(dns_rdatalist_t) lists;
  67. ISC_LIST(isc_buffer_t) buffers;
  68. dns_name_t *name;
  69. ISC_LINK(dns_sdblookup_t) link;
  70. isc_mutex_t lock;
  71. dns_rdatacallbacks_t callbacks;
  72. /* Locked */
  73. unsigned int references;
  74. };
  75. typedef struct dns_sdblookup dns_sdbnode_t;
  76. struct dns_sdballnodes {
  77. dns_dbiterator_t common;
  78. ISC_LIST(dns_sdbnode_t) nodelist;
  79. dns_sdbnode_t *current;
  80. dns_sdbnode_t *origin;
  81. };
  82. typedef dns_sdballnodes_t sdb_dbiterator_t;
  83. typedef struct sdb_rdatasetiter {
  84. dns_rdatasetiter_t common;
  85. dns_rdatalist_t *current;
  86. } sdb_rdatasetiter_t;
  87. #define SDB_MAGIC ISC_MAGIC('S', 'D', 'B', '-')
  88. /*%
  89. * Note that "impmagic" is not the first four bytes of the struct, so
  90. * ISC_MAGIC_VALID cannot be used.
  91. */
  92. #define VALID_SDB(sdb) ((sdb) != NULL && \
  93. (sdb)->common.impmagic == SDB_MAGIC)
  94. #define SDBLOOKUP_MAGIC ISC_MAGIC('S','D','B','L')
  95. #define VALID_SDBLOOKUP(sdbl) ISC_MAGIC_VALID(sdbl, SDBLOOKUP_MAGIC)
  96. #define VALID_SDBNODE(sdbn) VALID_SDBLOOKUP(sdbn)
  97. /* These values are taken from RFC1537 */
  98. #define SDB_DEFAULT_REFRESH (60 * 60 * 8)
  99. #define SDB_DEFAULT_RETRY (60 * 60 * 2)
  100. #define SDB_DEFAULT_EXPIRE (60 * 60 * 24 * 7)
  101. #define SDB_DEFAULT_MINIMUM (60 * 60 * 24)
  102. /* This is a reasonable value */
  103. #define SDB_DEFAULT_TTL (60 * 60 * 24)
  104. #ifdef __COVERITY__
  105. #define MAYBE_LOCK(sdb) LOCK(&sdb->implementation->driverlock)
  106. #define MAYBE_UNLOCK(sdb) UNLOCK(&sdb->implementation->driverlock)
  107. #else
  108. #define MAYBE_LOCK(sdb) \
  109. do { \
  110. unsigned int flags = sdb->implementation->flags; \
  111. if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \
  112. LOCK(&sdb->implementation->driverlock); \
  113. } while (0)
  114. #define MAYBE_UNLOCK(sdb) \
  115. do { \
  116. unsigned int flags = sdb->implementation->flags; \
  117. if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \
  118. UNLOCK(&sdb->implementation->driverlock); \
  119. } while (0)
  120. #endif
  121. static int dummy;
  122. static isc_result_t dns_sdb_create(isc_mem_t *mctx, dns_name_t *origin,
  123. dns_dbtype_t type, dns_rdataclass_t rdclass,
  124. unsigned int argc, char *argv[],
  125. void *driverarg, dns_db_t **dbp);
  126. static isc_result_t findrdataset(dns_db_t *db, dns_dbnode_t *node,
  127. dns_dbversion_t *version,
  128. dns_rdatatype_t type, dns_rdatatype_t covers,
  129. isc_stdtime_t now, dns_rdataset_t *rdataset,
  130. dns_rdataset_t *sigrdataset);
  131. static isc_result_t createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep);
  132. static void destroynode(dns_sdbnode_t *node);
  133. static void detachnode(dns_db_t *db, dns_dbnode_t **targetp);
  134. static void list_tordataset(dns_rdatalist_t *rdatalist,
  135. dns_db_t *db, dns_dbnode_t *node,
  136. dns_rdataset_t *rdataset);
  137. static void dbiterator_destroy(dns_dbiterator_t **iteratorp);
  138. static isc_result_t dbiterator_first(dns_dbiterator_t *iterator);
  139. static isc_result_t dbiterator_last(dns_dbiterator_t *iterator);
  140. static isc_result_t dbiterator_seek(dns_dbiterator_t *iterator,
  141. dns_name_t *name);
  142. static isc_result_t dbiterator_prev(dns_dbiterator_t *iterator);
  143. static isc_result_t dbiterator_next(dns_dbiterator_t *iterator);
  144. static isc_result_t dbiterator_current(dns_dbiterator_t *iterator,
  145. dns_dbnode_t **nodep,
  146. dns_name_t *name);
  147. static isc_result_t dbiterator_pause(dns_dbiterator_t *iterator);
  148. static isc_result_t dbiterator_origin(dns_dbiterator_t *iterator,
  149. dns_name_t *name);
  150. static dns_dbiteratormethods_t dbiterator_methods = {
  151. dbiterator_destroy,
  152. dbiterator_first,
  153. dbiterator_last,
  154. dbiterator_seek,
  155. dbiterator_prev,
  156. dbiterator_next,
  157. dbiterator_current,
  158. dbiterator_pause,
  159. dbiterator_origin
  160. };
  161. static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
  162. static isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator);
  163. static isc_result_t rdatasetiter_next(dns_rdatasetiter_t *iterator);
  164. static void rdatasetiter_current(dns_rdatasetiter_t *iterator,
  165. dns_rdataset_t *rdataset);
  166. static dns_rdatasetitermethods_t rdatasetiter_methods = {
  167. rdatasetiter_destroy,
  168. rdatasetiter_first,
  169. rdatasetiter_next,
  170. rdatasetiter_current
  171. };
  172. /*
  173. * Functions used by implementors of simple databases
  174. */
  175. isc_result_t
  176. dns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods,
  177. void *driverdata, unsigned int flags, isc_mem_t *mctx,
  178. dns_sdbimplementation_t **sdbimp)
  179. {
  180. dns_sdbimplementation_t *imp;
  181. isc_result_t result;
  182. REQUIRE(drivername != NULL);
  183. REQUIRE(methods != NULL);
  184. REQUIRE(methods->lookup != NULL || methods->lookup2 != NULL);
  185. REQUIRE(mctx != NULL);
  186. REQUIRE(sdbimp != NULL && *sdbimp == NULL);
  187. REQUIRE((flags & ~(DNS_SDBFLAG_RELATIVEOWNER |
  188. DNS_SDBFLAG_RELATIVERDATA |
  189. DNS_SDBFLAG_THREADSAFE|
  190. DNS_SDBFLAG_DNS64)) == 0);
  191. imp = isc_mem_get(mctx, sizeof(dns_sdbimplementation_t));
  192. if (imp == NULL)
  193. return (ISC_R_NOMEMORY);
  194. imp->methods = methods;
  195. imp->driverdata = driverdata;
  196. imp->flags = flags;
  197. imp->mctx = NULL;
  198. isc_mem_attach(mctx, &imp->mctx);
  199. result = isc_mutex_init(&imp->driverlock);
  200. if (result != ISC_R_SUCCESS)
  201. goto cleanup_mctx;
  202. imp->dbimp = NULL;
  203. result = dns_db_register(drivername, dns_sdb_create, imp, mctx,
  204. &imp->dbimp);
  205. if (result != ISC_R_SUCCESS)
  206. goto cleanup_mutex;
  207. *sdbimp = imp;
  208. return (ISC_R_SUCCESS);
  209. cleanup_mutex:
  210. DESTROYLOCK(&imp->driverlock);
  211. cleanup_mctx:
  212. isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
  213. return (result);
  214. }
  215. void
  216. dns_sdb_unregister(dns_sdbimplementation_t **sdbimp) {
  217. dns_sdbimplementation_t *imp;
  218. isc_mem_t *mctx;
  219. REQUIRE(sdbimp != NULL && *sdbimp != NULL);
  220. imp = *sdbimp;
  221. dns_db_unregister(&imp->dbimp);
  222. DESTROYLOCK(&imp->driverlock);
  223. mctx = imp->mctx;
  224. isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
  225. isc_mem_detach(&mctx);
  226. *sdbimp = NULL;
  227. }
  228. static inline unsigned int
  229. initial_size(unsigned int len) {
  230. unsigned int size;
  231. for (size = 1024; size < (64 * 1024); size *= 2)
  232. if (len < size)
  233. return (size);
  234. return (65535);
  235. }
  236. isc_result_t
  237. dns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t typeval,
  238. dns_ttl_t ttl, const unsigned char *rdatap,
  239. unsigned int rdlen)
  240. {
  241. dns_rdatalist_t *rdatalist;
  242. dns_rdata_t *rdata;
  243. isc_buffer_t *rdatabuf = NULL;
  244. isc_result_t result;
  245. isc_mem_t *mctx;
  246. isc_region_t region;
  247. mctx = lookup->sdb->common.mctx;
  248. rdatalist = ISC_LIST_HEAD(lookup->lists);
  249. while (rdatalist != NULL) {
  250. if (rdatalist->type == typeval)
  251. break;
  252. rdatalist = ISC_LIST_NEXT(rdatalist, link);
  253. }
  254. if (rdatalist == NULL) {
  255. rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
  256. if (rdatalist == NULL)
  257. return (ISC_R_NOMEMORY);
  258. rdatalist->rdclass = lookup->sdb->common.rdclass;
  259. rdatalist->type = typeval;
  260. rdatalist->covers = 0;
  261. rdatalist->ttl = ttl;
  262. ISC_LIST_INIT(rdatalist->rdata);
  263. ISC_LINK_INIT(rdatalist, link);
  264. ISC_LIST_APPEND(lookup->lists, rdatalist, link);
  265. } else
  266. if (rdatalist->ttl != ttl)
  267. return (DNS_R_BADTTL);
  268. rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
  269. if (rdata == NULL)
  270. return (ISC_R_NOMEMORY);
  271. result = isc_buffer_allocate(mctx, &rdatabuf, rdlen);
  272. if (result != ISC_R_SUCCESS)
  273. goto failure;
  274. DE_CONST(rdatap, region.base);
  275. region.length = rdlen;
  276. isc_buffer_copyregion(rdatabuf, &region);
  277. isc_buffer_usedregion(rdatabuf, &region);
  278. dns_rdata_init(rdata);
  279. dns_rdata_fromregion(rdata, rdatalist->rdclass, rdatalist->type,
  280. &region);
  281. ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
  282. ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
  283. rdata = NULL;
  284. failure:
  285. if (rdata != NULL)
  286. isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
  287. return (result);
  288. }
  289. isc_result_t
  290. dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
  291. const char *data)
  292. {
  293. unsigned int datalen;
  294. dns_rdatatype_t typeval;
  295. isc_textregion_t r;
  296. isc_lex_t *lex = NULL;
  297. isc_result_t result;
  298. unsigned char *p = NULL;
  299. unsigned int size = 0; /* Init to suppress compiler warning */
  300. isc_mem_t *mctx;
  301. dns_sdbimplementation_t *imp;
  302. dns_name_t *origin;
  303. isc_buffer_t b;
  304. isc_buffer_t rb;
  305. REQUIRE(VALID_SDBLOOKUP(lookup));
  306. REQUIRE(type != NULL);
  307. REQUIRE(data != NULL);
  308. mctx = lookup->sdb->common.mctx;
  309. DE_CONST(type, r.base);
  310. r.length = strlen(type);
  311. result = dns_rdatatype_fromtext(&typeval, &r);
  312. if (result != ISC_R_SUCCESS)
  313. return (result);
  314. imp = lookup->sdb->implementation;
  315. if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0)
  316. origin = &lookup->sdb->common.origin;
  317. else
  318. origin = dns_rootname;
  319. result = isc_lex_create(mctx, 64, &lex);
  320. if (result != ISC_R_SUCCESS)
  321. goto failure;
  322. datalen = strlen(data);
  323. size = initial_size(datalen);
  324. do {
  325. isc_buffer_init(&b, data, datalen);
  326. isc_buffer_add(&b, datalen);
  327. result = isc_lex_openbuffer(lex, &b);
  328. if (result != ISC_R_SUCCESS)
  329. goto failure;
  330. if (size >= 65535)
  331. size = 65535;
  332. p = isc_mem_get(mctx, size);
  333. if (p == NULL) {
  334. result = ISC_R_NOMEMORY;
  335. goto failure;
  336. }
  337. isc_buffer_init(&rb, p, size);
  338. result = dns_rdata_fromtext(NULL,
  339. lookup->sdb->common.rdclass,
  340. typeval, lex,
  341. origin, 0,
  342. mctx, &rb,
  343. &lookup->callbacks);
  344. if (result != ISC_R_NOSPACE)
  345. break;
  346. /*
  347. * Is the RR too big?
  348. */
  349. if (size >= 65535)
  350. break;
  351. isc_mem_put(mctx, p, size);
  352. p = NULL;
  353. size *= 2;
  354. } while (result == ISC_R_NOSPACE);
  355. if (result != ISC_R_SUCCESS)
  356. goto failure;
  357. result = dns_sdb_putrdata(lookup, typeval, ttl,
  358. isc_buffer_base(&rb),
  359. isc_buffer_usedlength(&rb));
  360. failure:
  361. if (p != NULL)
  362. isc_mem_put(mctx, p, size);
  363. if (lex != NULL)
  364. isc_lex_destroy(&lex);
  365. return (result);
  366. }
  367. static isc_result_t
  368. getnode(dns_sdballnodes_t *allnodes, const char *name, dns_sdbnode_t **nodep) {
  369. dns_name_t *newname, *origin;
  370. dns_fixedname_t fnewname;
  371. dns_sdb_t *sdb = (dns_sdb_t *)allnodes->common.db;
  372. dns_sdbimplementation_t *imp = sdb->implementation;
  373. dns_sdbnode_t *sdbnode;
  374. isc_mem_t *mctx = sdb->common.mctx;
  375. isc_buffer_t b;
  376. isc_result_t result;
  377. dns_fixedname_init(&fnewname);
  378. newname = dns_fixedname_name(&fnewname);
  379. if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0)
  380. origin = &sdb->common.origin;
  381. else
  382. origin = dns_rootname;
  383. isc_buffer_init(&b, name, strlen(name));
  384. isc_buffer_add(&b, strlen(name));
  385. result = dns_name_fromtext(newname, &b, origin, 0, NULL);
  386. if (result != ISC_R_SUCCESS)
  387. return (result);
  388. if (allnodes->common.relative_names) {
  389. /* All names are relative to the root */
  390. unsigned int nlabels = dns_name_countlabels(newname);
  391. dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
  392. }
  393. sdbnode = ISC_LIST_HEAD(allnodes->nodelist);
  394. if (sdbnode == NULL || !dns_name_equal(sdbnode->name, newname)) {
  395. sdbnode = NULL;
  396. result = createnode(sdb, &sdbnode);
  397. if (result != ISC_R_SUCCESS)
  398. return (result);
  399. sdbnode->name = isc_mem_get(mctx, sizeof(dns_name_t));
  400. if (sdbnode->name == NULL) {
  401. destroynode(sdbnode);
  402. return (ISC_R_NOMEMORY);
  403. }
  404. dns_name_init(sdbnode->name, NULL);
  405. result = dns_name_dup(newname, mctx, sdbnode->name);
  406. if (result != ISC_R_SUCCESS) {
  407. isc_mem_put(mctx, sdbnode->name, sizeof(dns_name_t));
  408. destroynode(sdbnode);
  409. return (result);
  410. }
  411. ISC_LIST_PREPEND(allnodes->nodelist, sdbnode, link);
  412. if (allnodes->origin == NULL &&
  413. dns_name_equal(newname, &sdb->common.origin))
  414. allnodes->origin = sdbnode;
  415. }
  416. *nodep = sdbnode;
  417. return (ISC_R_SUCCESS);
  418. }
  419. isc_result_t
  420. dns_sdb_putnamedrr(dns_sdballnodes_t *allnodes, const char *name,
  421. const char *type, dns_ttl_t ttl, const char *data)
  422. {
  423. isc_result_t result;
  424. dns_sdbnode_t *sdbnode = NULL;
  425. result = getnode(allnodes, name, &sdbnode);
  426. if (result != ISC_R_SUCCESS)
  427. return (result);
  428. return (dns_sdb_putrr(sdbnode, type, ttl, data));
  429. }
  430. isc_result_t
  431. dns_sdb_putnamedrdata(dns_sdballnodes_t *allnodes, const char *name,
  432. dns_rdatatype_t type, dns_ttl_t ttl,
  433. const void *rdata, unsigned int rdlen)
  434. {
  435. isc_result_t result;
  436. dns_sdbnode_t *sdbnode = NULL;
  437. result = getnode(allnodes, name, &sdbnode);
  438. if (result != ISC_R_SUCCESS)
  439. return (result);
  440. return (dns_sdb_putrdata(sdbnode, type, ttl, rdata, rdlen));
  441. }
  442. isc_result_t
  443. dns_sdb_putsoa(dns_sdblookup_t *lookup, const char *mname, const char *rname,
  444. isc_uint32_t serial)
  445. {
  446. char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
  447. int n;
  448. REQUIRE(mname != NULL);
  449. REQUIRE(rname != NULL);
  450. n = snprintf(str, sizeof(str), "%s %s %u %u %u %u %u",
  451. mname, rname, serial,
  452. SDB_DEFAULT_REFRESH, SDB_DEFAULT_RETRY,
  453. SDB_DEFAULT_EXPIRE, SDB_DEFAULT_MINIMUM);
  454. if (n >= (int)sizeof(str) || n < 0)
  455. return (ISC_R_NOSPACE);
  456. return (dns_sdb_putrr(lookup, "SOA", SDB_DEFAULT_TTL, str));
  457. }
  458. /*
  459. * DB routines
  460. */
  461. static void
  462. attach(dns_db_t *source, dns_db_t **targetp) {
  463. dns_sdb_t *sdb = (dns_sdb_t *) source;
  464. REQUIRE(VALID_SDB(sdb));
  465. LOCK(&sdb->lock);
  466. REQUIRE(sdb->references > 0);
  467. sdb->references++;
  468. UNLOCK(&sdb->lock);
  469. *targetp = source;
  470. }
  471. static void
  472. destroy(dns_sdb_t *sdb) {
  473. isc_mem_t *mctx;
  474. dns_sdbimplementation_t *imp = sdb->implementation;
  475. mctx = sdb->common.mctx;
  476. if (imp->methods->destroy != NULL) {
  477. MAYBE_LOCK(sdb);
  478. imp->methods->destroy(sdb->zone, imp->driverdata,
  479. &sdb->dbdata);
  480. MAYBE_UNLOCK(sdb);
  481. }
  482. isc_mem_free(mctx, sdb->zone);
  483. DESTROYLOCK(&sdb->lock);
  484. sdb->common.magic = 0;
  485. sdb->common.impmagic = 0;
  486. dns_name_free(&sdb->common.origin, mctx);
  487. isc_mem_put(mctx, sdb, sizeof(dns_sdb_t));
  488. isc_mem_detach(&mctx);
  489. }
  490. static void
  491. detach(dns_db_t **dbp) {
  492. dns_sdb_t *sdb = (dns_sdb_t *)(*dbp);
  493. isc_boolean_t need_destroy = ISC_FALSE;
  494. REQUIRE(VALID_SDB(sdb));
  495. LOCK(&sdb->lock);
  496. REQUIRE(sdb->references > 0);
  497. sdb->references--;
  498. if (sdb->references == 0)
  499. need_destroy = ISC_TRUE;
  500. UNLOCK(&sdb->lock);
  501. if (need_destroy)
  502. destroy(sdb);
  503. *dbp = NULL;
  504. }
  505. static isc_result_t
  506. beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) {
  507. UNUSED(db);
  508. UNUSED(addp);
  509. UNUSED(dbloadp);
  510. return (ISC_R_NOTIMPLEMENTED);
  511. }
  512. static isc_result_t
  513. endload(dns_db_t *db, dns_dbload_t **dbloadp) {
  514. UNUSED(db);
  515. UNUSED(dbloadp);
  516. return (ISC_R_NOTIMPLEMENTED);
  517. }
  518. static isc_result_t
  519. dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
  520. dns_masterformat_t masterformat) {
  521. UNUSED(db);
  522. UNUSED(version);
  523. UNUSED(filename);
  524. UNUSED(masterformat);
  525. return (ISC_R_NOTIMPLEMENTED);
  526. }
  527. static void
  528. currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
  529. REQUIRE(versionp != NULL && *versionp == NULL);
  530. UNUSED(db);
  531. *versionp = (void *) &dummy;
  532. return;
  533. }
  534. static isc_result_t
  535. newversion(dns_db_t *db, dns_dbversion_t **versionp) {
  536. UNUSED(db);
  537. UNUSED(versionp);
  538. return (ISC_R_NOTIMPLEMENTED);
  539. }
  540. static void
  541. attachversion(dns_db_t *db, dns_dbversion_t *source,
  542. dns_dbversion_t **targetp)
  543. {
  544. REQUIRE(source != NULL && source == (void *) &dummy);
  545. REQUIRE(targetp != NULL && *targetp == NULL);
  546. UNUSED(db);
  547. *targetp = source;
  548. return;
  549. }
  550. static void
  551. closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
  552. REQUIRE(versionp != NULL && *versionp == (void *) &dummy);
  553. REQUIRE(commit == ISC_FALSE);
  554. UNUSED(db);
  555. UNUSED(commit);
  556. *versionp = NULL;
  557. }
  558. static isc_result_t
  559. createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep) {
  560. dns_sdbnode_t *node;
  561. isc_result_t result;
  562. node = isc_mem_get(sdb->common.mctx, sizeof(dns_sdbnode_t));
  563. if (node == NULL)
  564. return (ISC_R_NOMEMORY);
  565. node->sdb = NULL;
  566. attach((dns_db_t *)sdb, (dns_db_t **)&node->sdb);
  567. ISC_LIST_INIT(node->lists);
  568. ISC_LIST_INIT(node->buffers);
  569. ISC_LINK_INIT(node, link);
  570. node->name = NULL;
  571. result = isc_mutex_init(&node->lock);
  572. if (result != ISC_R_SUCCESS) {
  573. isc_mem_put(sdb->common.mctx, node, sizeof(dns_sdbnode_t));
  574. return (result);
  575. }
  576. dns_rdatacallbacks_init(&node->callbacks);
  577. node->references = 1;
  578. node->magic = SDBLOOKUP_MAGIC;
  579. *nodep = node;
  580. return (ISC_R_SUCCESS);
  581. }
  582. static void
  583. destroynode(dns_sdbnode_t *node) {
  584. dns_rdatalist_t *list;
  585. dns_rdata_t *rdata;
  586. isc_buffer_t *b;
  587. dns_sdb_t *sdb;
  588. isc_mem_t *mctx;
  589. sdb = node->sdb;
  590. mctx = sdb->common.mctx;
  591. while (!ISC_LIST_EMPTY(node->lists)) {
  592. list = ISC_LIST_HEAD(node->lists);
  593. while (!ISC_LIST_EMPTY(list->rdata)) {
  594. rdata = ISC_LIST_HEAD(list->rdata);
  595. ISC_LIST_UNLINK(list->rdata, rdata, link);
  596. isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
  597. }
  598. ISC_LIST_UNLINK(node->lists, list, link);
  599. isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
  600. }
  601. while (!ISC_LIST_EMPTY(node->buffers)) {
  602. b = ISC_LIST_HEAD(node->buffers);
  603. ISC_LIST_UNLINK(node->buffers, b, link);
  604. isc_buffer_free(&b);
  605. }
  606. if (node->name != NULL) {
  607. dns_name_free(node->name, mctx);
  608. isc_mem_put(mctx, node->name, sizeof(dns_name_t));
  609. }
  610. DESTROYLOCK(&node->lock);
  611. node->magic = 0;
  612. isc_mem_put(mctx, node, sizeof(dns_sdbnode_t));
  613. detach((dns_db_t **) (void *)&sdb);
  614. }
  615. static isc_result_t
  616. findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
  617. dns_dbnode_t **nodep)
  618. {
  619. dns_sdb_t *sdb = (dns_sdb_t *)db;
  620. dns_sdbnode_t *node = NULL;
  621. isc_result_t result;
  622. isc_buffer_t b;
  623. char namestr[DNS_NAME_MAXTEXT + 1];
  624. isc_boolean_t isorigin;
  625. dns_sdbimplementation_t *imp;
  626. dns_name_t relname;
  627. unsigned int labels;
  628. REQUIRE(VALID_SDB(sdb));
  629. REQUIRE(create == ISC_FALSE);
  630. REQUIRE(nodep != NULL && *nodep == NULL);
  631. UNUSED(name);
  632. UNUSED(create);
  633. imp = sdb->implementation;
  634. isorigin = dns_name_equal(name, &sdb->common.origin);
  635. if (imp->methods->lookup2 != NULL) {
  636. if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
  637. labels = dns_name_countlabels(name) -
  638. dns_name_countlabels(&db->origin);
  639. dns_name_init(&relname, NULL);
  640. dns_name_getlabelsequence(name, 0, labels, &relname);
  641. name = &relname;
  642. }
  643. } else {
  644. isc_buffer_init(&b, namestr, sizeof(namestr));
  645. if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
  646. labels = dns_name_countlabels(name) -
  647. dns_name_countlabels(&db->origin);
  648. dns_name_init(&relname, NULL);
  649. dns_name_getlabelsequence(name, 0, labels, &relname);
  650. result = dns_name_totext(&relname, ISC_TRUE, &b);
  651. if (result != ISC_R_SUCCESS)
  652. return (result);
  653. } else {
  654. result = dns_name_totext(name, ISC_TRUE, &b);
  655. if (result != ISC_R_SUCCESS)
  656. return (result);
  657. }
  658. isc_buffer_putuint8(&b, 0);
  659. }
  660. result = createnode(sdb, &node);
  661. if (result != ISC_R_SUCCESS)
  662. return (result);
  663. MAYBE_LOCK(sdb);
  664. if (imp->methods->lookup2 != NULL)
  665. result = imp->methods->lookup2(&sdb->common.origin, name,
  666. sdb->dbdata, node);
  667. else
  668. result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata,
  669. node);
  670. MAYBE_UNLOCK(sdb);
  671. if (result != ISC_R_SUCCESS &&
  672. !(result == ISC_R_NOTFOUND &&
  673. isorigin && imp->methods->authority != NULL))
  674. {
  675. destroynode(node);
  676. return (result);
  677. }
  678. if (isorigin && imp->methods->authority != NULL) {
  679. MAYBE_LOCK(sdb);
  680. result = imp->methods->authority(sdb->zone, sdb->dbdata, node);
  681. MAYBE_UNLOCK(sdb);
  682. if (result != ISC_R_SUCCESS) {
  683. destroynode(node);
  684. return (result);
  685. }
  686. }
  687. *nodep = node;
  688. return (ISC_R_SUCCESS);
  689. }
  690. static isc_result_t
  691. find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
  692. dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
  693. dns_dbnode_t **nodep, dns_name_t *foundname,
  694. dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
  695. {
  696. dns_sdb_t *sdb = (dns_sdb_t *)db;
  697. dns_dbnode_t *node = NULL;
  698. dns_fixedname_t fname;
  699. dns_rdataset_t xrdataset;
  700. dns_name_t *xname;
  701. unsigned int nlabels, olabels;
  702. isc_result_t result;
  703. unsigned int i;
  704. unsigned int flags;
  705. REQUIRE(VALID_SDB(sdb));
  706. REQUIRE(nodep == NULL || *nodep == NULL);
  707. REQUIRE(version == NULL || version == (void *) &dummy);
  708. UNUSED(options);
  709. if (!dns_name_issubdomain(name, &db->origin))
  710. return (DNS_R_NXDOMAIN);
  711. olabels = dns_name_countlabels(&db->origin);
  712. nlabels = dns_name_countlabels(name);
  713. dns_fixedname_init(&fname);
  714. xname = dns_fixedname_name(&fname);
  715. if (rdataset == NULL) {
  716. dns_rdataset_init(&xrdataset);
  717. rdataset = &xrdataset;
  718. }
  719. result = DNS_R_NXDOMAIN;
  720. flags = sdb->implementation->flags;
  721. i = (flags & DNS_SDBFLAG_DNS64) != 0 ? nlabels : olabels;
  722. for (; i <= nlabels; i++) {
  723. /*
  724. * Look up the next label.
  725. */
  726. dns_name_getlabelsequence(name, nlabels - i, i, xname);
  727. result = findnode(db, xname, ISC_FALSE, &node);
  728. if (result == ISC_R_NOTFOUND) {
  729. /*
  730. * No data at zone apex?
  731. */
  732. if (i == olabels)
  733. return (DNS_R_BADDB);
  734. result = DNS_R_NXDOMAIN;
  735. continue;
  736. }
  737. if (result != ISC_R_SUCCESS)
  738. return (result);
  739. /*
  740. * DNS64 zone's don't have DNAME or NS records.
  741. */
  742. if ((flags & DNS_SDBFLAG_DNS64) != 0)
  743. goto skip;
  744. /*
  745. * DNS64 zone's don't have DNAME or NS records.
  746. */
  747. if ((flags & DNS_SDBFLAG_DNS64) != 0)
  748. goto skip;
  749. /*
  750. * Look for a DNAME at the current label, unless this is
  751. * the qname.
  752. */
  753. if (i < nlabels) {
  754. result = findrdataset(db, node, version,
  755. dns_rdatatype_dname,
  756. 0, now, rdataset, sigrdataset);
  757. if (result == ISC_R_SUCCESS) {
  758. result = DNS_R_DNAME;
  759. break;
  760. }
  761. }
  762. /*
  763. * Look for an NS at the current label, unless this is the
  764. * origin or glue is ok.
  765. */
  766. if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
  767. result = findrdataset(db, node, version,
  768. dns_rdatatype_ns,
  769. 0, now, rdataset, sigrdataset);
  770. if (result == ISC_R_SUCCESS) {
  771. if (i == nlabels && type == dns_rdatatype_any)
  772. {
  773. result = DNS_R_ZONECUT;
  774. dns_rdataset_disassociate(rdataset);
  775. if (sigrdataset != NULL &&
  776. dns_rdataset_isassociated
  777. (sigrdataset)) {
  778. dns_rdataset_disassociate
  779. (sigrdataset);
  780. }
  781. } else
  782. result = DNS_R_DELEGATION;
  783. break;
  784. }
  785. }
  786. /*
  787. * If the current name is not the qname, add another label
  788. * and try again.
  789. */
  790. if (i < nlabels) {
  791. destroynode(node);
  792. node = NULL;
  793. continue;
  794. }
  795. skip:
  796. /*
  797. * If we're looking for ANY, we're done.
  798. */
  799. if (type == dns_rdatatype_any) {
  800. result = ISC_R_SUCCESS;
  801. break;
  802. }
  803. /*
  804. * Look for the qtype.
  805. */
  806. result = findrdataset(db, node, version, type,
  807. 0, now, rdataset, sigrdataset);
  808. if (result == ISC_R_SUCCESS)
  809. break;
  810. /*
  811. * Look for a CNAME
  812. */
  813. if (type != dns_rdatatype_cname) {
  814. result = findrdataset(db, node, version,
  815. dns_rdatatype_cname,
  816. 0, now, rdataset, sigrdataset);
  817. if (result == ISC_R_SUCCESS) {
  818. result = DNS_R_CNAME;
  819. break;
  820. }
  821. }
  822. result = DNS_R_NXRRSET;
  823. break;
  824. }
  825. if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset))
  826. dns_rdataset_disassociate(rdataset);
  827. if (foundname != NULL) {
  828. isc_result_t xresult;
  829. xresult = dns_name_copy(xname, foundname, NULL);
  830. if (xresult != ISC_R_SUCCESS) {
  831. if (node != NULL)
  832. destroynode(node);
  833. if (dns_rdataset_isassociated(rdataset))
  834. dns_rdataset_disassociate(rdataset);
  835. return (DNS_R_BADDB);
  836. }
  837. }
  838. if (nodep != NULL)
  839. *nodep = node;
  840. else if (node != NULL)
  841. detachnode(db, &node);
  842. return (result);
  843. }
  844. static isc_result_t
  845. findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
  846. isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
  847. dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
  848. {
  849. UNUSED(db);
  850. UNUSED(name);
  851. UNUSED(options);
  852. UNUSED(now);
  853. UNUSED(nodep);
  854. UNUSED(foundname);
  855. UNUSED(rdataset);
  856. UNUSED(sigrdataset);
  857. return (ISC_R_NOTIMPLEMENTED);
  858. }
  859. static void
  860. attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
  861. dns_sdb_t *sdb = (dns_sdb_t *)db;
  862. dns_sdbnode_t *node = (dns_sdbnode_t *)source;
  863. REQUIRE(VALID_SDB(sdb));
  864. UNUSED(sdb);
  865. LOCK(&node->lock);
  866. INSIST(node->references > 0);
  867. node->references++;
  868. INSIST(node->references != 0); /* Catch overflow. */
  869. UNLOCK(&node->lock);
  870. *targetp = source;
  871. }
  872. static void
  873. detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
  874. dns_sdb_t *sdb = (dns_sdb_t *)db;
  875. dns_sdbnode_t *node;
  876. isc_boolean_t need_destroy = ISC_FALSE;
  877. REQUIRE(VALID_SDB(sdb));
  878. REQUIRE(targetp != NULL && *targetp != NULL);
  879. UNUSED(sdb);
  880. node = (dns_sdbnode_t *)(*targetp);
  881. LOCK(&node->lock);
  882. INSIST(node->references > 0);
  883. node->references--;
  884. if (node->references == 0)
  885. need_destroy = ISC_TRUE;
  886. UNLOCK(&node->lock);
  887. if (need_destroy)
  888. destroynode(node);
  889. *targetp = NULL;
  890. }
  891. static isc_result_t
  892. expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
  893. UNUSED(db);
  894. UNUSED(node);
  895. UNUSED(now);
  896. INSIST(0);
  897. return (ISC_R_UNEXPECTED);
  898. }
  899. static void
  900. printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
  901. UNUSED(db);
  902. UNUSED(node);
  903. UNUSED(out);
  904. return;
  905. }
  906. static isc_result_t
  907. createiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp)
  908. {
  909. dns_sdb_t *sdb = (dns_sdb_t *)db;
  910. sdb_dbiterator_t *sdbiter;
  911. dns_sdbimplementation_t *imp = sdb->implementation;
  912. isc_result_t result;
  913. REQUIRE(VALID_SDB(sdb));
  914. if (imp->methods->allnodes == NULL)
  915. return (ISC_R_NOTIMPLEMENTED);
  916. if ((options & DNS_DB_NSEC3ONLY) != 0 ||
  917. (options & DNS_DB_NONSEC3) != 0)
  918. return (ISC_R_NOTIMPLEMENTED);
  919. sdbiter = isc_mem_get(sdb->common.mctx, sizeof(sdb_dbiterator_t));
  920. if (sdbiter == NULL)
  921. return (ISC_R_NOMEMORY);
  922. sdbiter->common.methods = &dbiterator_methods;
  923. sdbiter->common.db = NULL;
  924. dns_db_attach(db, &sdbiter->common.db);
  925. sdbiter->common.relative_names = ISC_TF(options & DNS_DB_RELATIVENAMES);
  926. sdbiter->common.magic = DNS_DBITERATOR_MAGIC;
  927. ISC_LIST_INIT(sdbiter->nodelist);
  928. sdbiter->current = NULL;
  929. sdbiter->origin = NULL;
  930. MAYBE_LOCK(sdb);
  931. result = imp->methods->allnodes(sdb->zone, sdb->dbdata, sdbiter);
  932. MAYBE_UNLOCK(sdb);
  933. if (result != ISC_R_SUCCESS) {
  934. dbiterator_destroy((dns_dbiterator_t **) (void *)&sdbiter);
  935. return (result);
  936. }
  937. if (sdbiter->origin != NULL) {
  938. ISC_LIST_UNLINK(sdbiter->nodelist, sdbiter->origin, link);
  939. ISC_LIST_PREPEND(sdbiter->nodelist, sdbiter->origin, link);
  940. }
  941. *iteratorp = (dns_dbiterator_t *)sdbiter;
  942. return (ISC_R_SUCCESS);
  943. }
  944. static isc_result_t
  945. findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
  946. dns_rdatatype_t type, dns_rdatatype_t covers,
  947. isc_stdtime_t now, dns_rdataset_t *rdataset,
  948. dns_rdataset_t *sigrdataset)
  949. {
  950. dns_rdatalist_t *list;
  951. dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node;
  952. REQUIRE(VALID_SDBNODE(node));
  953. UNUSED(db);
  954. UNUSED(version);
  955. UNUSED(covers);
  956. UNUSED(now);
  957. UNUSED(sigrdataset);
  958. if (type == dns_rdatatype_rrsig)
  959. return (ISC_R_NOTIMPLEMENTED);
  960. list = ISC_LIST_HEAD(sdbnode->lists);
  961. while (list != NULL) {
  962. if (list->type == type)
  963. break;
  964. list = ISC_LIST_NEXT(list, link);
  965. }
  966. if (list == NULL)
  967. return (ISC_R_NOTFOUND);
  968. list_tordataset(list, db, node, rdataset);
  969. return (ISC_R_SUCCESS);
  970. }
  971. static isc_result_t
  972. allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
  973. isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
  974. {
  975. sdb_rdatasetiter_t *iterator;
  976. REQUIRE(version == NULL || version == &dummy);
  977. UNUSED(version);
  978. UNUSED(now);
  979. iterator = isc_mem_get(db->mctx, sizeof(sdb_rdatasetiter_t));
  980. if (iterator == NULL)
  981. return (ISC_R_NOMEMORY);
  982. iterator->common.magic = DNS_RDATASETITER_MAGIC;
  983. iterator->common.methods = &rdatasetiter_methods;
  984. iterator->common.db = db;
  985. iterator->common.node = NULL;
  986. attachnode(db, node, &iterator->common.node);
  987. iterator->common.version = version;
  988. iterator->common.now = now;
  989. *iteratorp = (dns_rdatasetiter_t *)iterator;
  990. return (ISC_R_SUCCESS);
  991. }
  992. static isc_result_t
  993. addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
  994. isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
  995. dns_rdataset_t *addedrdataset)
  996. {
  997. UNUSED(db);
  998. UNUSED(node);
  999. UNUSED(version);
  1000. UNUSED(now);
  1001. UNUSED(rdataset);
  1002. UNUSED(options);
  1003. UNUSED(addedrdataset);
  1004. return (ISC_R_NOTIMPLEMENTED);
  1005. }
  1006. static isc_result_t
  1007. subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
  1008. dns_rdataset_t *rdataset, unsigned int options,
  1009. dns_rdataset_t *newrdataset)
  1010. {
  1011. UNUSED(db);
  1012. UNUSED(node);
  1013. UNUSED(version);
  1014. UNUSED(rdataset);
  1015. UNUSED(options);
  1016. UNUSED(newrdataset);
  1017. return (ISC_R_NOTIMPLEMENTED);
  1018. }
  1019. static isc_result_t
  1020. deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
  1021. dns_rdatatype_t type, dns_rdatatype_t covers)
  1022. {
  1023. UNUSED(db);
  1024. UNUSED(node);
  1025. UNUSED(version);
  1026. UNUSED(type);
  1027. UNUSED(covers);
  1028. return (ISC_R_NOTIMPLEMENTED);
  1029. }
  1030. static isc_boolean_t
  1031. issecure(dns_db_t *db) {
  1032. UNUSED(db);
  1033. return (ISC_FALSE);
  1034. }
  1035. static unsigned int
  1036. nodecount(dns_db_t *db) {
  1037. UNUSED(db);
  1038. return (0);
  1039. }
  1040. static isc_boolean_t
  1041. ispersistent(dns_db_t *db) {
  1042. UNUSED(db);
  1043. return (ISC_TRUE);
  1044. }
  1045. static void
  1046. overmem(dns_db_t *db, isc_boolean_t overmem) {
  1047. UNUSED(db);
  1048. UNUSED(overmem);
  1049. }
  1050. static void
  1051. settask(dns_db_t *db, isc_task_t *task) {
  1052. UNUSED(db);
  1053. UNUSED(task);
  1054. }
  1055. static dns_dbmethods_t sdb_methods = {
  1056. attach,
  1057. detach,
  1058. beginload,
  1059. endload,
  1060. dump,
  1061. currentversion,
  1062. newversion,
  1063. attachversion,
  1064. closeversion,
  1065. findnode,
  1066. find,
  1067. findzonecut,
  1068. attachnode,
  1069. detachnode,
  1070. expirenode,
  1071. printnode,
  1072. createiterator,
  1073. findrdataset,
  1074. allrdatasets,
  1075. addrdataset,
  1076. subtractrdataset,
  1077. deleterdataset,
  1078. issecure,
  1079. nodecount,
  1080. ispersistent,
  1081. overmem,
  1082. settask,
  1083. NULL,
  1084. NULL,
  1085. NULL,
  1086. NULL,
  1087. NULL,
  1088. NULL,
  1089. NULL,
  1090. NULL,
  1091. NULL,
  1092. NULL,
  1093. NULL
  1094. };
  1095. static isc_result_t
  1096. dns_sdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type,
  1097. dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
  1098. void *driverarg, dns_db_t **dbp)
  1099. {
  1100. dns_sdb_t *sdb;
  1101. isc_result_t result;
  1102. char zonestr[DNS_NAME_MAXTEXT + 1];
  1103. isc_buffer_t b;
  1104. dns_sdbimplementation_t *imp;
  1105. REQUIRE(driverarg != NULL);
  1106. imp = driverarg;
  1107. if (type != dns_dbtype_zone)
  1108. return (ISC_R_NOTIMPLEMENTED);
  1109. sdb = isc_mem_get(mctx, sizeof(dns_sdb_t));
  1110. if (sdb == NULL)
  1111. return (ISC_R_NOMEMORY);
  1112. memset(sdb, 0, sizeof(dns_sdb_t));
  1113. dns_name_init(&sdb->common.origin, NULL);
  1114. sdb->common.attributes = 0;
  1115. sdb->common.methods = &sdb_methods;
  1116. sdb->common.rdclass = rdclass;
  1117. sdb->common.mctx = NULL;
  1118. sdb->implementation = imp;
  1119. isc_mem_attach(mctx, &sdb->common.mctx);
  1120. result = isc_mutex_init(&sdb->lock);
  1121. if (result != ISC_R_SUCCESS)
  1122. goto cleanup_mctx;
  1123. result = dns_name_dupwithoffsets(origin, mctx, &sdb->common.origin);
  1124. if (result != ISC_R_SUCCESS)
  1125. goto cleanup_lock;
  1126. isc_buffer_init(&b, zonestr, sizeof(zonestr));
  1127. result = dns_name_totext(origin, ISC_TRUE, &b);
  1128. if (result != ISC_R_SUCCESS)
  1129. goto cleanup_origin;
  1130. isc_buffer_putuint8(&b, 0);
  1131. sdb->zone = isc_mem_strdup(mctx, zonestr);
  1132. if (sdb->zone == NULL) {
  1133. result = ISC_R_NOMEMORY;
  1134. goto cleanup_origin;
  1135. }
  1136. sdb->dbdata = NULL;
  1137. if (imp->methods->create != NULL) {
  1138. MAYBE_LOCK(sdb);
  1139. result = imp->methods->create(sdb->zone, argc, argv,
  1140. imp->driverdata, &sdb->dbdata);
  1141. MAYBE_UNLOCK(sdb);
  1142. if (result != ISC_R_SUCCESS)
  1143. goto cleanup_zonestr;
  1144. }
  1145. sdb->references = 1;
  1146. sdb->common.magic = DNS_DB_MAGIC;
  1147. sdb->common.impmagic = SDB_MAGIC;
  1148. *dbp = (dns_db_t *)sdb;
  1149. return (ISC_R_SUCCESS);
  1150. cleanup_zonestr:
  1151. isc_mem_free(mctx, sdb->zone);
  1152. cleanup_origin:
  1153. dns_name_free(&sdb->common.origin, mctx);
  1154. cleanup_lock:
  1155. (void)isc_mutex_destroy(&sdb->lock);
  1156. cleanup_mctx:
  1157. isc_mem_put(mctx, sdb, sizeof(dns_sdb_t));
  1158. isc_mem_detach(&mctx);
  1159. return (result);
  1160. }
  1161. /*
  1162. * Rdataset Methods
  1163. */
  1164. static void
  1165. disassociate(dns_rdataset_t *rdataset) {
  1166. dns_dbnode_t *node = rdataset->private5;
  1167. dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node;
  1168. dns_db_t *db = (dns_db_t *) sdbnode->sdb;
  1169. detachnode(db, &node);
  1170. isc__rdatalist_disassociate(rdataset);
  1171. }
  1172. static void
  1173. rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
  1174. dns_dbnode_t *node = source->private5;
  1175. dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node;
  1176. dns_db_t *db = (dns_db_t *) sdbnode->sdb;
  1177. dns_dbnode_t *tempdb = NULL;
  1178. isc__rdatalist_clone(source, target);
  1179. attachnode(db, node, &tempdb);
  1180. source->private5 = tempdb;
  1181. }
  1182. static dns_rdatasetmethods_t methods = {
  1183. disassociate,
  1184. isc__rdatalist_first,
  1185. isc__rdatalist_next,
  1186. isc__rdatalist_current,
  1187. rdataset_clone,
  1188. isc__rdatalist_count,
  1189. isc__rdatalist_addnoqname,
  1190. isc__rdatalist_getnoqname,
  1191. NULL,
  1192. NULL,
  1193. NULL,
  1194. NULL,
  1195. NULL,
  1196. NULL,
  1197. NULL
  1198. };
  1199. static void
  1200. list_tordataset(dns_rdatalist_t *rdatalist,
  1201. dns_db_t *db, dns_dbnode_t *node,
  1202. dns_rdataset_t *rdataset)
  1203. {
  1204. /*
  1205. * The sdb rdataset is an rdatalist with some additions.
  1206. * - private1 & private2 are used by the rdatalist.
  1207. * - private3 & private 4 are unused.
  1208. * - private5 is the node.
  1209. */
  1210. /* This should never fail. */
  1211. RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
  1212. ISC_R_SUCCESS);
  1213. rdataset->methods = &methods;
  1214. dns_db_attachnode(db, node, &rdataset->private5);
  1215. }
  1216. /*
  1217. * Database Iterator Methods
  1218. */
  1219. static void
  1220. dbiterator_destroy(dns_dbiterator_t **iteratorp) {
  1221. sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)(*iteratorp);
  1222. dns_sdb_t *sdb = (dns_sdb_t *)sdbiter->common.db;
  1223. while (!ISC_LIST_EMPTY(sdbiter->nodelist)) {
  1224. dns_sdbnode_t *node;
  1225. node = ISC_LIST_HEAD(sdbiter->nodelist);
  1226. ISC_LIST_UNLINK(sdbiter->nodelist, node, link);
  1227. destroynode(node);
  1228. }
  1229. dns_db_detach(&sdbiter->common.db);
  1230. isc_mem_put(sdb->common.mctx, sdbiter, sizeof(sdb_dbiterator_t));
  1231. *iteratorp = NULL;
  1232. }
  1233. static isc_result_t
  1234. dbiterator_first(dns_dbiterator_t *iterator) {
  1235. sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
  1236. sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
  1237. if (sdbiter->current == NULL)
  1238. return (ISC_R_NOMORE);
  1239. else
  1240. return (ISC_R_SUCCESS);
  1241. }
  1242. static isc_result_t
  1243. dbiterator_last(dns_dbiterator_t *iterator) {
  1244. sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
  1245. sdbiter->current = ISC_LIST_TAIL(sdbiter->nodelist);
  1246. if (sdbiter->current == NULL)
  1247. return (ISC_R_NOMORE);
  1248. else
  1249. return (ISC_R_SUCCESS);
  1250. }
  1251. static isc_result_t
  1252. dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
  1253. sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
  1254. sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
  1255. while (sdbiter->current != NULL) {
  1256. if (dns_name_equal(sdbiter->current->name, name))
  1257. return (ISC_R_SUCCESS);
  1258. sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link);
  1259. }
  1260. return (ISC_R_NOTFOUND);
  1261. }
  1262. static isc_result_t
  1263. dbiterator_prev(dns_dbiterator_t *iterator) {
  1264. sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
  1265. sdbiter->current = ISC_LIST_PREV(sdbiter->current, link);
  1266. if (sdbiter->current == NULL)
  1267. return (ISC_R_NOMORE);
  1268. else
  1269. return (ISC_R_SUCCESS);
  1270. }
  1271. static isc_result_t
  1272. dbiterator_next(dns_dbiterator_t *iterator) {
  1273. sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
  1274. sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link);
  1275. if (sdbiter->current == NULL)
  1276. return (ISC_R_NOMORE);
  1277. else
  1278. return (ISC_R_SUCCESS);
  1279. }
  1280. static isc_result_t
  1281. dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
  1282. dns_name_t *name)
  1283. {
  1284. sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
  1285. attachnode(iterator->db, sdbiter->current, nodep);
  1286. if (name != NULL)
  1287. return (dns_name_copy(sdbiter->current->name, name, NULL));
  1288. return (ISC_R_SUCCESS);
  1289. }
  1290. static isc_result_t
  1291. dbiterator_pause(dns_dbiterator_t *iterator) {
  1292. UNUSED(iterator);
  1293. return (ISC_R_SUCCESS);
  1294. }
  1295. static isc_result_t
  1296. dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
  1297. UNUSED(iterator);
  1298. return (dns_name_copy(dns_rootname, name, NULL));
  1299. }
  1300. /*
  1301. * Rdataset Iterator Methods
  1302. */
  1303. static void
  1304. rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
  1305. sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)(*iteratorp);
  1306. detachnode(sdbiterator->common.db, &sdbiterator->common.node);
  1307. isc_mem_put(sdbiterator->common.db->mctx, sdbiterator,
  1308. sizeof(sdb_rdatasetiter_t));
  1309. *iteratorp = NULL;
  1310. }
  1311. static isc_result_t
  1312. rdatasetiter_first(dns_rdatasetiter_t *iterator) {
  1313. sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
  1314. dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)iterator->node;
  1315. if (ISC_LIST_EMPTY(sdbnode->lists))
  1316. return (ISC_R_NOMORE);
  1317. sdbiterator->current = ISC_LIST_HEAD(sdbnode->lists);
  1318. return (ISC_R_SUCCESS);
  1319. }
  1320. static isc_result_t
  1321. rdatasetiter_next(dns_rdatasetiter_t *iterator) {
  1322. sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
  1323. sdbiterator->current = ISC_LIST_NEXT(sdbiterator->current, link);
  1324. if (sdbiterator->current == NULL)
  1325. return (ISC_R_NOMORE);
  1326. else
  1327. return (ISC_R_SUCCESS);
  1328. }
  1329. static void
  1330. rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
  1331. sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
  1332. list_tordataset(sdbiterator->current, iterator->db, iterator->node,
  1333. rdataset);
  1334. }