/contrib/bind9/lib/dns/ecdb.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 818 lines · 606 code · 156 blank · 56 comment · 83 complexity · 4ceb55637500030ff4a8824465e62291 MD5 · raw file

  1. /*
  2. * Copyright (C) 2009-2012 Internet Systems Consortium, Inc. ("ISC")
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  9. * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  10. * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  11. * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  12. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  13. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  14. * PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. /* $Id$ */
  17. #include "config.h"
  18. #include <isc/result.h>
  19. #include <isc/util.h>
  20. #include <isc/mutex.h>
  21. #include <isc/mem.h>
  22. #include <dns/db.h>
  23. #include <dns/ecdb.h>
  24. #include <dns/rdata.h>
  25. #include <dns/rdataset.h>
  26. #include <dns/rdatasetiter.h>
  27. #include <dns/rdataslab.h>
  28. #define ECDB_MAGIC ISC_MAGIC('E', 'C', 'D', 'B')
  29. #define VALID_ECDB(db) ((db) != NULL && \
  30. (db)->common.impmagic == ECDB_MAGIC)
  31. #define ECDBNODE_MAGIC ISC_MAGIC('E', 'C', 'D', 'N')
  32. #define VALID_ECDBNODE(ecdbn) ISC_MAGIC_VALID(ecdbn, ECDBNODE_MAGIC)
  33. /*%
  34. * The 'ephemeral' cache DB (ecdb) implementation. An ecdb just provides
  35. * temporary storage for ongoing name resolution with the common DB interfaces.
  36. * It actually doesn't cache anything. The implementation expects any stored
  37. * data is released within a short period, and does not care about the
  38. * scalability in terms of the number of nodes.
  39. */
  40. typedef struct dns_ecdb {
  41. /* Unlocked */
  42. dns_db_t common;
  43. isc_mutex_t lock;
  44. /* Locked */
  45. unsigned int references;
  46. ISC_LIST(struct dns_ecdbnode) nodes;
  47. } dns_ecdb_t;
  48. typedef struct dns_ecdbnode {
  49. /* Unlocked */
  50. unsigned int magic;
  51. isc_mutex_t lock;
  52. dns_ecdb_t *ecdb;
  53. dns_name_t name;
  54. ISC_LINK(struct dns_ecdbnode) link;
  55. /* Locked */
  56. ISC_LIST(struct rdatasetheader) rdatasets;
  57. unsigned int references;
  58. } dns_ecdbnode_t;
  59. typedef struct rdatasetheader {
  60. dns_rdatatype_t type;
  61. dns_ttl_t ttl;
  62. dns_trust_t trust;
  63. dns_rdatatype_t covers;
  64. unsigned int attributes;
  65. ISC_LINK(struct rdatasetheader) link;
  66. } rdatasetheader_t;
  67. /* Copied from rbtdb.c */
  68. #define RDATASET_ATTR_NXDOMAIN 0x0010
  69. #define NXDOMAIN(header) \
  70. (((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0)
  71. static isc_result_t dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin,
  72. dns_dbtype_t type,
  73. dns_rdataclass_t rdclass,
  74. unsigned int argc, char *argv[],
  75. void *driverarg, dns_db_t **dbp);
  76. static void rdataset_disassociate(dns_rdataset_t *rdataset);
  77. static isc_result_t rdataset_first(dns_rdataset_t *rdataset);
  78. static isc_result_t rdataset_next(dns_rdataset_t *rdataset);
  79. static void rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
  80. static void rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target);
  81. static unsigned int rdataset_count(dns_rdataset_t *rdataset);
  82. static void rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust);
  83. static dns_rdatasetmethods_t rdataset_methods = {
  84. rdataset_disassociate,
  85. rdataset_first,
  86. rdataset_next,
  87. rdataset_current,
  88. rdataset_clone,
  89. rdataset_count,
  90. NULL, /* addnoqname */
  91. NULL, /* getnoqname */
  92. NULL, /* addclosest */
  93. NULL, /* getclosest */
  94. NULL, /* getadditional */
  95. NULL, /* setadditional */
  96. NULL, /* putadditional */
  97. rdataset_settrust, /* settrust */
  98. NULL /* expire */
  99. };
  100. typedef struct ecdb_rdatasetiter {
  101. dns_rdatasetiter_t common;
  102. rdatasetheader_t *current;
  103. } ecdb_rdatasetiter_t;
  104. static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
  105. static isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator);
  106. static isc_result_t rdatasetiter_next(dns_rdatasetiter_t *iterator);
  107. static void rdatasetiter_current(dns_rdatasetiter_t *iterator,
  108. dns_rdataset_t *rdataset);
  109. static dns_rdatasetitermethods_t rdatasetiter_methods = {
  110. rdatasetiter_destroy,
  111. rdatasetiter_first,
  112. rdatasetiter_next,
  113. rdatasetiter_current
  114. };
  115. isc_result_t
  116. dns_ecdb_register(isc_mem_t *mctx, dns_dbimplementation_t **dbimp) {
  117. REQUIRE(mctx != NULL);
  118. REQUIRE(dbimp != NULL && *dbimp == NULL);
  119. return (dns_db_register("ecdb", dns_ecdb_create, NULL, mctx, dbimp));
  120. }
  121. void
  122. dns_ecdb_unregister(dns_dbimplementation_t **dbimp) {
  123. REQUIRE(dbimp != NULL && *dbimp != NULL);
  124. dns_db_unregister(dbimp);
  125. }
  126. /*%
  127. * DB routines
  128. */
  129. static void
  130. attach(dns_db_t *source, dns_db_t **targetp) {
  131. dns_ecdb_t *ecdb = (dns_ecdb_t *)source;
  132. REQUIRE(VALID_ECDB(ecdb));
  133. REQUIRE(targetp != NULL && *targetp == NULL);
  134. LOCK(&ecdb->lock);
  135. ecdb->references++;
  136. UNLOCK(&ecdb->lock);
  137. *targetp = source;
  138. }
  139. static void
  140. destroy_ecdb(dns_ecdb_t **ecdbp) {
  141. dns_ecdb_t *ecdb = *ecdbp;
  142. isc_mem_t *mctx = ecdb->common.mctx;
  143. if (dns_name_dynamic(&ecdb->common.origin))
  144. dns_name_free(&ecdb->common.origin, mctx);
  145. DESTROYLOCK(&ecdb->lock);
  146. ecdb->common.impmagic = 0;
  147. ecdb->common.magic = 0;
  148. isc_mem_putanddetach(&mctx, ecdb, sizeof(*ecdb));
  149. *ecdbp = NULL;
  150. }
  151. static void
  152. detach(dns_db_t **dbp) {
  153. dns_ecdb_t *ecdb;
  154. isc_boolean_t need_destroy = ISC_FALSE;
  155. REQUIRE(dbp != NULL);
  156. ecdb = (dns_ecdb_t *)*dbp;
  157. REQUIRE(VALID_ECDB(ecdb));
  158. LOCK(&ecdb->lock);
  159. ecdb->references--;
  160. if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes))
  161. need_destroy = ISC_TRUE;
  162. UNLOCK(&ecdb->lock);
  163. if (need_destroy)
  164. destroy_ecdb(&ecdb);
  165. *dbp = NULL;
  166. }
  167. static void
  168. attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
  169. dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
  170. dns_ecdbnode_t *node = (dns_ecdbnode_t *)source;
  171. REQUIRE(VALID_ECDB(ecdb));
  172. REQUIRE(VALID_ECDBNODE(node));
  173. REQUIRE(targetp != NULL && *targetp == NULL);
  174. LOCK(&node->lock);
  175. INSIST(node->references > 0);
  176. node->references++;
  177. INSIST(node->references != 0); /* Catch overflow. */
  178. UNLOCK(&node->lock);
  179. *targetp = node;
  180. }
  181. static void
  182. destroynode(dns_ecdbnode_t *node) {
  183. isc_mem_t *mctx;
  184. dns_ecdb_t *ecdb = node->ecdb;
  185. isc_boolean_t need_destroydb = ISC_FALSE;
  186. rdatasetheader_t *header;
  187. mctx = ecdb->common.mctx;
  188. LOCK(&ecdb->lock);
  189. ISC_LIST_UNLINK(ecdb->nodes, node, link);
  190. if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes))
  191. need_destroydb = ISC_TRUE;
  192. UNLOCK(&ecdb->lock);
  193. dns_name_free(&node->name, mctx);
  194. while ((header = ISC_LIST_HEAD(node->rdatasets)) != NULL) {
  195. unsigned int headersize;
  196. ISC_LIST_UNLINK(node->rdatasets, header, link);
  197. headersize =
  198. dns_rdataslab_size((unsigned char *)header,
  199. sizeof(*header));
  200. isc_mem_put(mctx, header, headersize);
  201. }
  202. DESTROYLOCK(&node->lock);
  203. node->magic = 0;
  204. isc_mem_put(mctx, node, sizeof(*node));
  205. if (need_destroydb)
  206. destroy_ecdb(&ecdb);
  207. }
  208. static void
  209. detachnode(dns_db_t *db, dns_dbnode_t **nodep) {
  210. dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
  211. dns_ecdbnode_t *node;
  212. isc_boolean_t need_destroy = ISC_FALSE;
  213. REQUIRE(VALID_ECDB(ecdb));
  214. REQUIRE(nodep != NULL);
  215. node = (dns_ecdbnode_t *)*nodep;
  216. REQUIRE(VALID_ECDBNODE(node));
  217. UNUSED(ecdb); /* in case REQUIRE() is empty */
  218. LOCK(&node->lock);
  219. INSIST(node->references > 0);
  220. node->references--;
  221. if (node->references == 0)
  222. need_destroy = ISC_TRUE;
  223. UNLOCK(&node->lock);
  224. if (need_destroy)
  225. destroynode(node);
  226. *nodep = NULL;
  227. }
  228. static isc_result_t
  229. find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
  230. dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
  231. dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset,
  232. dns_rdataset_t *sigrdataset)
  233. {
  234. dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
  235. REQUIRE(VALID_ECDB(ecdb));
  236. UNUSED(name);
  237. UNUSED(version);
  238. UNUSED(type);
  239. UNUSED(options);
  240. UNUSED(now);
  241. UNUSED(nodep);
  242. UNUSED(foundname);
  243. UNUSED(rdataset);
  244. UNUSED(sigrdataset);
  245. return (ISC_R_NOTFOUND);
  246. }
  247. static isc_result_t
  248. findzonecut(dns_db_t *db, dns_name_t *name,
  249. unsigned int options, isc_stdtime_t now,
  250. dns_dbnode_t **nodep, dns_name_t *foundname,
  251. dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
  252. {
  253. dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
  254. REQUIRE(VALID_ECDB(ecdb));
  255. UNUSED(name);
  256. UNUSED(options);
  257. UNUSED(now);
  258. UNUSED(nodep);
  259. UNUSED(foundname);
  260. UNUSED(rdataset);
  261. UNUSED(sigrdataset);
  262. return (ISC_R_NOTFOUND);
  263. }
  264. static isc_result_t
  265. findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
  266. dns_dbnode_t **nodep)
  267. {
  268. dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
  269. isc_mem_t *mctx;
  270. dns_ecdbnode_t *node;
  271. isc_result_t result;
  272. REQUIRE(VALID_ECDB(ecdb));
  273. REQUIRE(nodep != NULL && *nodep == NULL);
  274. UNUSED(name);
  275. if (create != ISC_TRUE) {
  276. /* an 'ephemeral' node is never reused. */
  277. return (ISC_R_NOTFOUND);
  278. }
  279. mctx = ecdb->common.mctx;
  280. node = isc_mem_get(mctx, sizeof(*node));
  281. if (node == NULL)
  282. return (ISC_R_NOMEMORY);
  283. result = isc_mutex_init(&node->lock);
  284. if (result != ISC_R_SUCCESS) {
  285. UNEXPECTED_ERROR(__FILE__, __LINE__,
  286. "isc_mutex_init() failed: %s",
  287. isc_result_totext(result));
  288. isc_mem_put(mctx, node, sizeof(*node));
  289. return (ISC_R_UNEXPECTED);
  290. }
  291. dns_name_init(&node->name, NULL);
  292. result = dns_name_dup(name, mctx, &node->name);
  293. if (result != ISC_R_SUCCESS) {
  294. DESTROYLOCK(&node->lock);
  295. isc_mem_put(mctx, node, sizeof(*node));
  296. return (result);
  297. }
  298. node->ecdb= ecdb;
  299. node->references = 1;
  300. ISC_LIST_INIT(node->rdatasets);
  301. ISC_LINK_INIT(node, link);
  302. LOCK(&ecdb->lock);
  303. ISC_LIST_APPEND(ecdb->nodes, node, link);
  304. UNLOCK(&ecdb->lock);
  305. node->magic = ECDBNODE_MAGIC;
  306. *nodep = node;
  307. return (ISC_R_SUCCESS);
  308. }
  309. static void
  310. bind_rdataset(dns_ecdb_t *ecdb, dns_ecdbnode_t *node,
  311. rdatasetheader_t *header, dns_rdataset_t *rdataset)
  312. {
  313. unsigned char *raw;
  314. /*
  315. * Caller must be holding the node lock.
  316. */
  317. REQUIRE(!dns_rdataset_isassociated(rdataset));
  318. rdataset->methods = &rdataset_methods;
  319. rdataset->rdclass = ecdb->common.rdclass;
  320. rdataset->type = header->type;
  321. rdataset->covers = header->covers;
  322. rdataset->ttl = header->ttl;
  323. rdataset->trust = header->trust;
  324. if (NXDOMAIN(header))
  325. rdataset->attributes |= DNS_RDATASETATTR_NXDOMAIN;
  326. rdataset->private1 = ecdb;
  327. rdataset->private2 = node;
  328. raw = (unsigned char *)header + sizeof(*header);
  329. rdataset->private3 = raw;
  330. rdataset->count = 0;
  331. /*
  332. * Reset iterator state.
  333. */
  334. rdataset->privateuint4 = 0;
  335. rdataset->private5 = NULL;
  336. INSIST(node->references > 0);
  337. node->references++;
  338. }
  339. static isc_result_t
  340. addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
  341. isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
  342. dns_rdataset_t *addedrdataset)
  343. {
  344. dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
  345. isc_region_t r;
  346. isc_result_t result = ISC_R_SUCCESS;
  347. isc_mem_t *mctx;
  348. dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node;
  349. rdatasetheader_t *header;
  350. REQUIRE(VALID_ECDB(ecdb));
  351. REQUIRE(VALID_ECDBNODE(ecdbnode));
  352. UNUSED(version);
  353. UNUSED(now);
  354. UNUSED(options);
  355. mctx = ecdb->common.mctx;
  356. LOCK(&ecdbnode->lock);
  357. /*
  358. * Sanity check: this implementation does not allow overriding an
  359. * existing rdataset of the same type.
  360. */
  361. for (header = ISC_LIST_HEAD(ecdbnode->rdatasets); header != NULL;
  362. header = ISC_LIST_NEXT(header, link)) {
  363. INSIST(header->type != rdataset->type ||
  364. header->covers != rdataset->covers);
  365. }
  366. result = dns_rdataslab_fromrdataset(rdataset, mctx,
  367. &r, sizeof(rdatasetheader_t));
  368. if (result != ISC_R_SUCCESS)
  369. goto unlock;
  370. header = (rdatasetheader_t *)r.base;
  371. header->type = rdataset->type;
  372. header->ttl = rdataset->ttl;
  373. header->trust = rdataset->trust;
  374. header->covers = rdataset->covers;
  375. header->attributes = 0;
  376. if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
  377. header->attributes |= RDATASET_ATTR_NXDOMAIN;
  378. ISC_LINK_INIT(header, link);
  379. ISC_LIST_APPEND(ecdbnode->rdatasets, header, link);
  380. if (addedrdataset == NULL)
  381. goto unlock;
  382. bind_rdataset(ecdb, ecdbnode, header, addedrdataset);
  383. unlock:
  384. UNLOCK(&ecdbnode->lock);
  385. return (result);
  386. }
  387. static isc_result_t
  388. deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
  389. dns_rdatatype_t type, dns_rdatatype_t covers)
  390. {
  391. UNUSED(db);
  392. UNUSED(node);
  393. UNUSED(version);
  394. UNUSED(type);
  395. UNUSED(covers);
  396. return (ISC_R_NOTIMPLEMENTED);
  397. }
  398. static isc_result_t
  399. createiterator(dns_db_t *db, unsigned int options,
  400. dns_dbiterator_t **iteratorp)
  401. {
  402. UNUSED(db);
  403. UNUSED(options);
  404. UNUSED(iteratorp);
  405. return (ISC_R_NOTIMPLEMENTED);
  406. }
  407. static isc_result_t
  408. allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
  409. isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
  410. {
  411. dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
  412. dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)node;
  413. isc_mem_t *mctx;
  414. ecdb_rdatasetiter_t *iterator;
  415. REQUIRE(VALID_ECDB(ecdb));
  416. REQUIRE(VALID_ECDBNODE(ecdbnode));
  417. mctx = ecdb->common.mctx;
  418. iterator = isc_mem_get(mctx, sizeof(ecdb_rdatasetiter_t));
  419. if (iterator == NULL)
  420. return (ISC_R_NOMEMORY);
  421. iterator->common.magic = DNS_RDATASETITER_MAGIC;
  422. iterator->common.methods = &rdatasetiter_methods;
  423. iterator->common.db = db;
  424. iterator->common.node = NULL;
  425. attachnode(db, node, &iterator->common.node);
  426. iterator->common.version = version;
  427. iterator->common.now = now;
  428. *iteratorp = (dns_rdatasetiter_t *)iterator;
  429. return (ISC_R_SUCCESS);
  430. }
  431. static dns_dbmethods_t ecdb_methods = {
  432. attach,
  433. detach,
  434. NULL, /* beginload */
  435. NULL, /* endload */
  436. NULL, /* dump */
  437. NULL, /* currentversion */
  438. NULL, /* newversion */
  439. NULL, /* attachversion */
  440. NULL, /* closeversion */
  441. findnode,
  442. find,
  443. findzonecut,
  444. attachnode,
  445. detachnode,
  446. NULL, /* expirenode */
  447. NULL, /* printnode */
  448. createiterator, /* createiterator */
  449. NULL, /* findrdataset */
  450. allrdatasets,
  451. addrdataset,
  452. NULL, /* subtractrdataset */
  453. deleterdataset,
  454. NULL, /* issecure */
  455. NULL, /* nodecount */
  456. NULL, /* ispersistent */
  457. NULL, /* overmem */
  458. NULL, /* settask */
  459. NULL, /* getoriginnode */
  460. NULL, /* transfernode */
  461. NULL, /* getnsec3parameters */
  462. NULL, /* findnsec3node */
  463. NULL, /* setsigningtime */
  464. NULL, /* getsigningtime */
  465. NULL, /* resigned */
  466. NULL, /* isdnssec */
  467. NULL, /* getrrsetstats */
  468. NULL, /* rpz_enabled */
  469. NULL /* rpz_findips */
  470. };
  471. static isc_result_t
  472. dns_ecdb_create(isc_mem_t *mctx, dns_name_t *origin, dns_dbtype_t type,
  473. dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
  474. void *driverarg, dns_db_t **dbp)
  475. {
  476. dns_ecdb_t *ecdb;
  477. isc_result_t result;
  478. REQUIRE(mctx != NULL);
  479. REQUIRE(origin == dns_rootname);
  480. REQUIRE(type == dns_dbtype_cache);
  481. REQUIRE(dbp != NULL && *dbp == NULL);
  482. UNUSED(argc);
  483. UNUSED(argv);
  484. UNUSED(driverarg);
  485. ecdb = isc_mem_get(mctx, sizeof(*ecdb));
  486. if (ecdb == NULL)
  487. return (ISC_R_NOMEMORY);
  488. ecdb->common.attributes = DNS_DBATTR_CACHE;
  489. ecdb->common.rdclass = rdclass;
  490. ecdb->common.methods = &ecdb_methods;
  491. dns_name_init(&ecdb->common.origin, NULL);
  492. result = dns_name_dupwithoffsets(origin, mctx, &ecdb->common.origin);
  493. if (result != ISC_R_SUCCESS) {
  494. isc_mem_put(mctx, ecdb, sizeof(*ecdb));
  495. return (result);
  496. }
  497. result = isc_mutex_init(&ecdb->lock);
  498. if (result != ISC_R_SUCCESS) {
  499. UNEXPECTED_ERROR(__FILE__, __LINE__,
  500. "isc_mutex_init() failed: %s",
  501. isc_result_totext(result));
  502. if (dns_name_dynamic(&ecdb->common.origin))
  503. dns_name_free(&ecdb->common.origin, mctx);
  504. isc_mem_put(mctx, ecdb, sizeof(*ecdb));
  505. return (ISC_R_UNEXPECTED);
  506. }
  507. ecdb->references = 1;
  508. ISC_LIST_INIT(ecdb->nodes);
  509. ecdb->common.mctx = NULL;
  510. isc_mem_attach(mctx, &ecdb->common.mctx);
  511. ecdb->common.impmagic = ECDB_MAGIC;
  512. ecdb->common.magic = DNS_DB_MAGIC;
  513. *dbp = (dns_db_t *)ecdb;
  514. return (ISC_R_SUCCESS);
  515. }
  516. /*%
  517. * Rdataset Methods
  518. */
  519. static void
  520. rdataset_disassociate(dns_rdataset_t *rdataset) {
  521. dns_db_t *db = rdataset->private1;
  522. dns_dbnode_t *node = rdataset->private2;
  523. dns_db_detachnode(db, &node);
  524. }
  525. static isc_result_t
  526. rdataset_first(dns_rdataset_t *rdataset) {
  527. unsigned char *raw = rdataset->private3;
  528. unsigned int count;
  529. count = raw[0] * 256 + raw[1];
  530. if (count == 0) {
  531. rdataset->private5 = NULL;
  532. return (ISC_R_NOMORE);
  533. }
  534. #if DNS_RDATASET_FIXED
  535. raw += 2 + (4 * count);
  536. #else
  537. raw += 2;
  538. #endif
  539. /*
  540. * The privateuint4 field is the number of rdata beyond the cursor
  541. * position, so we decrement the total count by one before storing
  542. * it.
  543. */
  544. count--;
  545. rdataset->privateuint4 = count;
  546. rdataset->private5 = raw;
  547. return (ISC_R_SUCCESS);
  548. }
  549. static isc_result_t
  550. rdataset_next(dns_rdataset_t *rdataset) {
  551. unsigned int count;
  552. unsigned int length;
  553. unsigned char *raw;
  554. count = rdataset->privateuint4;
  555. if (count == 0)
  556. return (ISC_R_NOMORE);
  557. count--;
  558. rdataset->privateuint4 = count;
  559. raw = rdataset->private5;
  560. length = raw[0] * 256 + raw[1];
  561. #if DNS_RDATASET_FIXED
  562. raw += length + 4;
  563. #else
  564. raw += length + 2;
  565. #endif
  566. rdataset->private5 = raw;
  567. return (ISC_R_SUCCESS);
  568. }
  569. static void
  570. rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
  571. unsigned char *raw = rdataset->private5;
  572. isc_region_t r;
  573. unsigned int length;
  574. unsigned int flags = 0;
  575. REQUIRE(raw != NULL);
  576. length = raw[0] * 256 + raw[1];
  577. #if DNS_RDATASET_FIXED
  578. raw += 4;
  579. #else
  580. raw += 2;
  581. #endif
  582. if (rdataset->type == dns_rdatatype_rrsig) {
  583. if (*raw & DNS_RDATASLAB_OFFLINE)
  584. flags |= DNS_RDATA_OFFLINE;
  585. length--;
  586. raw++;
  587. }
  588. r.length = length;
  589. r.base = raw;
  590. dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
  591. rdata->flags |= flags;
  592. }
  593. static void
  594. rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
  595. dns_db_t *db = source->private1;
  596. dns_dbnode_t *node = source->private2;
  597. dns_dbnode_t *cloned_node = NULL;
  598. attachnode(db, node, &cloned_node);
  599. *target = *source;
  600. /*
  601. * Reset iterator state.
  602. */
  603. target->privateuint4 = 0;
  604. target->private5 = NULL;
  605. }
  606. static unsigned int
  607. rdataset_count(dns_rdataset_t *rdataset) {
  608. unsigned char *raw = rdataset->private3;
  609. unsigned int count;
  610. count = raw[0] * 256 + raw[1];
  611. return (count);
  612. }
  613. static void
  614. rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
  615. rdatasetheader_t *header = rdataset->private3;
  616. header--;
  617. header->trust = rdataset->trust = trust;
  618. }
  619. /*
  620. * Rdataset Iterator Methods
  621. */
  622. static void
  623. rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
  624. ecdb_rdatasetiter_t *ecdbiterator;
  625. isc_mem_t *mctx;
  626. REQUIRE(iteratorp != NULL);
  627. ecdbiterator = (ecdb_rdatasetiter_t *)*iteratorp;
  628. REQUIRE(DNS_RDATASETITER_VALID(&ecdbiterator->common));
  629. mctx = ecdbiterator->common.db->mctx;
  630. ecdbiterator->common.magic = 0;
  631. dns_db_detachnode(ecdbiterator->common.db, &ecdbiterator->common.node);
  632. isc_mem_put(mctx, ecdbiterator, sizeof(ecdb_rdatasetiter_t));
  633. *iteratorp = NULL;
  634. }
  635. static isc_result_t
  636. rdatasetiter_first(dns_rdatasetiter_t *iterator) {
  637. ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator;
  638. dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)iterator->node;
  639. REQUIRE(DNS_RDATASETITER_VALID(iterator));
  640. if (ISC_LIST_EMPTY(ecdbnode->rdatasets))
  641. return (ISC_R_NOMORE);
  642. ecdbiterator->current = ISC_LIST_HEAD(ecdbnode->rdatasets);
  643. return (ISC_R_SUCCESS);
  644. }
  645. static isc_result_t
  646. rdatasetiter_next(dns_rdatasetiter_t *iterator) {
  647. ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator;
  648. REQUIRE(DNS_RDATASETITER_VALID(iterator));
  649. ecdbiterator->current = ISC_LIST_NEXT(ecdbiterator->current, link);
  650. if (ecdbiterator->current == NULL)
  651. return (ISC_R_NOMORE);
  652. else
  653. return (ISC_R_SUCCESS);
  654. }
  655. static void
  656. rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
  657. ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator;
  658. dns_ecdb_t *ecdb;
  659. ecdb = (dns_ecdb_t *)iterator->db;
  660. REQUIRE(VALID_ECDB(ecdb));
  661. bind_rdataset(ecdb, iterator->node, ecdbiterator->current, rdataset);
  662. }