PageRenderTime 55ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/contrib/bind9/lib/dns/sdlz.c

https://bitbucket.org/freebsd/freebsd-head/
C | 2079 lines | 1488 code | 356 blank | 235 comment | 337 complexity | 81e919fc777422fc86ee4d607b95574e MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, BSD-3-Clause, LGPL-2.0, LGPL-2.1, BSD-2-Clause, 0BSD, JSON, AGPL-1.0, GPL-2.0
  1. /*
  2. * Portions Copyright (C) 2005-2012 Internet Systems Consortium, Inc. ("ISC")
  3. * Portions Copyright (C) 1999-2001 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. /*
  18. * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
  19. *
  20. * Permission to use, copy, modify, and distribute this software for any
  21. * purpose with or without fee is hereby granted, provided that the
  22. * above copyright notice and this permission notice appear in all
  23. * copies.
  24. *
  25. * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
  26. * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
  27. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
  28. * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
  29. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  30. * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  31. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
  32. * USE OR PERFORMANCE OF THIS SOFTWARE.
  33. *
  34. * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
  35. * conceived and contributed by Rob Butler.
  36. *
  37. * Permission to use, copy, modify, and distribute this software for any
  38. * purpose with or without fee is hereby granted, provided that the
  39. * above copyright notice and this permission notice appear in all
  40. * copies.
  41. *
  42. * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
  43. * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
  44. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
  45. * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
  46. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  47. * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  48. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
  49. * USE OR PERFORMANCE OF THIS SOFTWARE.
  50. */
  51. /* $Id$ */
  52. /*! \file */
  53. #include <config.h>
  54. #include <string.h>
  55. #include <isc/buffer.h>
  56. #include <isc/lex.h>
  57. #include <isc/log.h>
  58. #include <isc/rwlock.h>
  59. #include <isc/string.h>
  60. #include <isc/util.h>
  61. #include <isc/magic.h>
  62. #include <isc/mem.h>
  63. #include <isc/once.h>
  64. #include <isc/print.h>
  65. #include <isc/region.h>
  66. #include <dns/callbacks.h>
  67. #include <dns/db.h>
  68. #include <dns/dbiterator.h>
  69. #include <dns/dlz.h>
  70. #include <dns/fixedname.h>
  71. #include <dns/log.h>
  72. #include <dns/rdata.h>
  73. #include <dns/rdatalist.h>
  74. #include <dns/rdataset.h>
  75. #include <dns/rdatasetiter.h>
  76. #include <dns/rdatatype.h>
  77. #include <dns/result.h>
  78. #include <dns/master.h>
  79. #include <dns/sdlz.h>
  80. #include <dns/types.h>
  81. #include "rdatalist_p.h"
  82. /*
  83. * Private Types
  84. */
  85. struct dns_sdlzimplementation {
  86. const dns_sdlzmethods_t *methods;
  87. isc_mem_t *mctx;
  88. void *driverarg;
  89. unsigned int flags;
  90. isc_mutex_t driverlock;
  91. dns_dlzimplementation_t *dlz_imp;
  92. };
  93. struct dns_sdlz_db {
  94. /* Unlocked */
  95. dns_db_t common;
  96. void *dbdata;
  97. dns_sdlzimplementation_t *dlzimp;
  98. isc_mutex_t refcnt_lock;
  99. /* Locked */
  100. unsigned int references;
  101. dns_dbversion_t *future_version;
  102. int dummy_version;
  103. };
  104. struct dns_sdlzlookup {
  105. /* Unlocked */
  106. unsigned int magic;
  107. dns_sdlz_db_t *sdlz;
  108. ISC_LIST(dns_rdatalist_t) lists;
  109. ISC_LIST(isc_buffer_t) buffers;
  110. dns_name_t *name;
  111. ISC_LINK(dns_sdlzlookup_t) link;
  112. isc_mutex_t lock;
  113. dns_rdatacallbacks_t callbacks;
  114. /* Locked */
  115. unsigned int references;
  116. };
  117. typedef struct dns_sdlzlookup dns_sdlznode_t;
  118. struct dns_sdlzallnodes {
  119. dns_dbiterator_t common;
  120. ISC_LIST(dns_sdlznode_t) nodelist;
  121. dns_sdlznode_t *current;
  122. dns_sdlznode_t *origin;
  123. };
  124. typedef dns_sdlzallnodes_t sdlz_dbiterator_t;
  125. typedef struct sdlz_rdatasetiter {
  126. dns_rdatasetiter_t common;
  127. dns_rdatalist_t *current;
  128. } sdlz_rdatasetiter_t;
  129. #define SDLZDB_MAGIC ISC_MAGIC('D', 'L', 'Z', 'S')
  130. /*
  131. * Note that "impmagic" is not the first four bytes of the struct, so
  132. * ISC_MAGIC_VALID cannot be used.
  133. */
  134. #define VALID_SDLZDB(sdlzdb) ((sdlzdb) != NULL && \
  135. (sdlzdb)->common.impmagic == SDLZDB_MAGIC)
  136. #define SDLZLOOKUP_MAGIC ISC_MAGIC('D','L','Z','L')
  137. #define VALID_SDLZLOOKUP(sdlzl) ISC_MAGIC_VALID(sdlzl, SDLZLOOKUP_MAGIC)
  138. #define VALID_SDLZNODE(sdlzn) VALID_SDLZLOOKUP(sdlzn)
  139. /* These values are taken from RFC 1537 */
  140. #define SDLZ_DEFAULT_REFRESH (60 * 60 * 8)
  141. #define SDLZ_DEFAULT_RETRY (60 * 60 * 2)
  142. #define SDLZ_DEFAULT_EXPIRE (60 * 60 * 24 * 7)
  143. #define SDLZ_DEFAULT_MINIMUM (60 * 60 * 24)
  144. /* This is a reasonable value */
  145. #define SDLZ_DEFAULT_TTL (60 * 60 * 24)
  146. #ifdef __COVERITY__
  147. #define MAYBE_LOCK(imp) LOCK(&imp->driverlock)
  148. #define MAYBE_UNLOCK(imp) UNLOCK(&imp->driverlock)
  149. #else
  150. #define MAYBE_LOCK(imp) \
  151. do { \
  152. unsigned int flags = imp->flags; \
  153. if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
  154. LOCK(&imp->driverlock); \
  155. } while (0)
  156. #define MAYBE_UNLOCK(imp) \
  157. do { \
  158. unsigned int flags = imp->flags; \
  159. if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
  160. UNLOCK(&imp->driverlock); \
  161. } while (0)
  162. #endif
  163. /*
  164. * Forward references. Try to keep these to a minimum.
  165. */
  166. static void list_tordataset(dns_rdatalist_t *rdatalist,
  167. dns_db_t *db, dns_dbnode_t *node,
  168. dns_rdataset_t *rdataset);
  169. static void detachnode(dns_db_t *db, dns_dbnode_t **targetp);
  170. static void dbiterator_destroy(dns_dbiterator_t **iteratorp);
  171. static isc_result_t dbiterator_first(dns_dbiterator_t *iterator);
  172. static isc_result_t dbiterator_last(dns_dbiterator_t *iterator);
  173. static isc_result_t dbiterator_seek(dns_dbiterator_t *iterator,
  174. dns_name_t *name);
  175. static isc_result_t dbiterator_prev(dns_dbiterator_t *iterator);
  176. static isc_result_t dbiterator_next(dns_dbiterator_t *iterator);
  177. static isc_result_t dbiterator_current(dns_dbiterator_t *iterator,
  178. dns_dbnode_t **nodep,
  179. dns_name_t *name);
  180. static isc_result_t dbiterator_pause(dns_dbiterator_t *iterator);
  181. static isc_result_t dbiterator_origin(dns_dbiterator_t *iterator,
  182. dns_name_t *name);
  183. static dns_dbiteratormethods_t dbiterator_methods = {
  184. dbiterator_destroy,
  185. dbiterator_first,
  186. dbiterator_last,
  187. dbiterator_seek,
  188. dbiterator_prev,
  189. dbiterator_next,
  190. dbiterator_current,
  191. dbiterator_pause,
  192. dbiterator_origin
  193. };
  194. /*
  195. * Utility functions
  196. */
  197. /*
  198. * Log a message at the given level
  199. */
  200. static void
  201. sdlz_log(int level, const char *fmt, ...) {
  202. va_list ap;
  203. va_start(ap, fmt);
  204. isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE,
  205. DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(level),
  206. fmt, ap);
  207. va_end(ap);
  208. }
  209. /*% Converts the input string to lowercase, in place. */
  210. static void
  211. dns_sdlz_tolower(char *str) {
  212. unsigned int len = strlen(str);
  213. unsigned int i;
  214. for (i = 0; i < len; i++) {
  215. if (str[i] >= 'A' && str[i] <= 'Z')
  216. str[i] += 32;
  217. }
  218. }
  219. static inline unsigned int
  220. initial_size(const char *data) {
  221. unsigned int len = (strlen(data) / 64) + 1;
  222. return (len * 64 + 64);
  223. }
  224. /*
  225. * Rdataset Iterator Methods. These methods were "borrowed" from the SDB
  226. * driver interface. See the SDB driver interface documentation for more info.
  227. */
  228. static void
  229. rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
  230. sdlz_rdatasetiter_t *sdlziterator =
  231. (sdlz_rdatasetiter_t *)(*iteratorp);
  232. detachnode(sdlziterator->common.db, &sdlziterator->common.node);
  233. isc_mem_put(sdlziterator->common.db->mctx, sdlziterator,
  234. sizeof(sdlz_rdatasetiter_t));
  235. *iteratorp = NULL;
  236. }
  237. static isc_result_t
  238. rdatasetiter_first(dns_rdatasetiter_t *iterator) {
  239. sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
  240. dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)iterator->node;
  241. if (ISC_LIST_EMPTY(sdlznode->lists))
  242. return (ISC_R_NOMORE);
  243. sdlziterator->current = ISC_LIST_HEAD(sdlznode->lists);
  244. return (ISC_R_SUCCESS);
  245. }
  246. static isc_result_t
  247. rdatasetiter_next(dns_rdatasetiter_t *iterator) {
  248. sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
  249. sdlziterator->current = ISC_LIST_NEXT(sdlziterator->current, link);
  250. if (sdlziterator->current == NULL)
  251. return (ISC_R_NOMORE);
  252. else
  253. return (ISC_R_SUCCESS);
  254. }
  255. static void
  256. rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
  257. sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
  258. list_tordataset(sdlziterator->current, iterator->db, iterator->node,
  259. rdataset);
  260. }
  261. static dns_rdatasetitermethods_t rdatasetiter_methods = {
  262. rdatasetiter_destroy,
  263. rdatasetiter_first,
  264. rdatasetiter_next,
  265. rdatasetiter_current
  266. };
  267. /*
  268. * DB routines. These methods were "borrowed" from the SDB driver interface.
  269. * See the SDB driver interface documentation for more info.
  270. */
  271. static void
  272. attach(dns_db_t *source, dns_db_t **targetp) {
  273. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) source;
  274. REQUIRE(VALID_SDLZDB(sdlz));
  275. LOCK(&sdlz->refcnt_lock);
  276. REQUIRE(sdlz->references > 0);
  277. sdlz->references++;
  278. UNLOCK(&sdlz->refcnt_lock);
  279. *targetp = source;
  280. }
  281. static void
  282. destroy(dns_sdlz_db_t *sdlz) {
  283. isc_mem_t *mctx;
  284. mctx = sdlz->common.mctx;
  285. sdlz->common.magic = 0;
  286. sdlz->common.impmagic = 0;
  287. (void)isc_mutex_destroy(&sdlz->refcnt_lock);
  288. dns_name_free(&sdlz->common.origin, mctx);
  289. isc_mem_put(mctx, sdlz, sizeof(dns_sdlz_db_t));
  290. isc_mem_detach(&mctx);
  291. }
  292. static void
  293. detach(dns_db_t **dbp) {
  294. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)(*dbp);
  295. isc_boolean_t need_destroy = ISC_FALSE;
  296. REQUIRE(VALID_SDLZDB(sdlz));
  297. LOCK(&sdlz->refcnt_lock);
  298. REQUIRE(sdlz->references > 0);
  299. sdlz->references--;
  300. if (sdlz->references == 0)
  301. need_destroy = ISC_TRUE;
  302. UNLOCK(&sdlz->refcnt_lock);
  303. if (need_destroy)
  304. destroy(sdlz);
  305. *dbp = NULL;
  306. }
  307. static isc_result_t
  308. beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) {
  309. UNUSED(db);
  310. UNUSED(addp);
  311. UNUSED(dbloadp);
  312. return (ISC_R_NOTIMPLEMENTED);
  313. }
  314. static isc_result_t
  315. endload(dns_db_t *db, dns_dbload_t **dbloadp) {
  316. UNUSED(db);
  317. UNUSED(dbloadp);
  318. return (ISC_R_NOTIMPLEMENTED);
  319. }
  320. static isc_result_t
  321. dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
  322. dns_masterformat_t masterformat)
  323. {
  324. UNUSED(db);
  325. UNUSED(version);
  326. UNUSED(filename);
  327. UNUSED(masterformat);
  328. return (ISC_R_NOTIMPLEMENTED);
  329. }
  330. static void
  331. currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
  332. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  333. REQUIRE(VALID_SDLZDB(sdlz));
  334. REQUIRE(versionp != NULL && *versionp == NULL);
  335. *versionp = (void *) &sdlz->dummy_version;
  336. return;
  337. }
  338. static isc_result_t
  339. newversion(dns_db_t *db, dns_dbversion_t **versionp) {
  340. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  341. char origin[DNS_NAME_MAXTEXT + 1];
  342. isc_result_t result;
  343. REQUIRE(VALID_SDLZDB(sdlz));
  344. if (sdlz->dlzimp->methods->newversion == NULL)
  345. return (ISC_R_NOTIMPLEMENTED);
  346. dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
  347. result = sdlz->dlzimp->methods->newversion(origin,
  348. sdlz->dlzimp->driverarg,
  349. sdlz->dbdata, versionp);
  350. if (result != ISC_R_SUCCESS) {
  351. sdlz_log(ISC_LOG_ERROR,
  352. "sdlz newversion on origin %s failed : %s",
  353. origin, isc_result_totext(result));
  354. return (result);
  355. }
  356. sdlz->future_version = *versionp;
  357. return (ISC_R_SUCCESS);
  358. }
  359. static void
  360. attachversion(dns_db_t *db, dns_dbversion_t *source,
  361. dns_dbversion_t **targetp)
  362. {
  363. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  364. REQUIRE(VALID_SDLZDB(sdlz));
  365. REQUIRE(source != NULL && source == (void *)&sdlz->dummy_version);
  366. *targetp = source;
  367. }
  368. static void
  369. closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
  370. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  371. char origin[DNS_NAME_MAXTEXT + 1];
  372. REQUIRE(VALID_SDLZDB(sdlz));
  373. REQUIRE(versionp != NULL);
  374. if (*versionp == (void *)&sdlz->dummy_version) {
  375. *versionp = NULL;
  376. return;
  377. }
  378. REQUIRE(*versionp == sdlz->future_version);
  379. REQUIRE(sdlz->dlzimp->methods->closeversion != NULL);
  380. dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
  381. sdlz->dlzimp->methods->closeversion(origin, commit,
  382. sdlz->dlzimp->driverarg,
  383. sdlz->dbdata, versionp);
  384. if (*versionp != NULL)
  385. sdlz_log(ISC_LOG_ERROR,
  386. "sdlz closeversion on origin %s failed", origin);
  387. sdlz->future_version = NULL;
  388. }
  389. static isc_result_t
  390. createnode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) {
  391. dns_sdlznode_t *node;
  392. isc_result_t result;
  393. node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t));
  394. if (node == NULL)
  395. return (ISC_R_NOMEMORY);
  396. node->sdlz = NULL;
  397. attach((dns_db_t *)sdlz, (dns_db_t **)&node->sdlz);
  398. ISC_LIST_INIT(node->lists);
  399. ISC_LIST_INIT(node->buffers);
  400. ISC_LINK_INIT(node, link);
  401. node->name = NULL;
  402. result = isc_mutex_init(&node->lock);
  403. if (result != ISC_R_SUCCESS) {
  404. UNEXPECTED_ERROR(__FILE__, __LINE__,
  405. "isc_mutex_init() failed: %s",
  406. isc_result_totext(result));
  407. isc_mem_put(sdlz->common.mctx, node, sizeof(dns_sdlznode_t));
  408. return (ISC_R_UNEXPECTED);
  409. }
  410. dns_rdatacallbacks_init(&node->callbacks);
  411. node->references = 1;
  412. node->magic = SDLZLOOKUP_MAGIC;
  413. *nodep = node;
  414. return (ISC_R_SUCCESS);
  415. }
  416. static void
  417. destroynode(dns_sdlznode_t *node) {
  418. dns_rdatalist_t *list;
  419. dns_rdata_t *rdata;
  420. isc_buffer_t *b;
  421. dns_sdlz_db_t *sdlz;
  422. dns_db_t *db;
  423. isc_mem_t *mctx;
  424. sdlz = node->sdlz;
  425. mctx = sdlz->common.mctx;
  426. while (!ISC_LIST_EMPTY(node->lists)) {
  427. list = ISC_LIST_HEAD(node->lists);
  428. while (!ISC_LIST_EMPTY(list->rdata)) {
  429. rdata = ISC_LIST_HEAD(list->rdata);
  430. ISC_LIST_UNLINK(list->rdata, rdata, link);
  431. isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
  432. }
  433. ISC_LIST_UNLINK(node->lists, list, link);
  434. isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
  435. }
  436. while (!ISC_LIST_EMPTY(node->buffers)) {
  437. b = ISC_LIST_HEAD(node->buffers);
  438. ISC_LIST_UNLINK(node->buffers, b, link);
  439. isc_buffer_free(&b);
  440. }
  441. if (node->name != NULL) {
  442. dns_name_free(node->name, mctx);
  443. isc_mem_put(mctx, node->name, sizeof(dns_name_t));
  444. }
  445. DESTROYLOCK(&node->lock);
  446. node->magic = 0;
  447. isc_mem_put(mctx, node, sizeof(dns_sdlznode_t));
  448. db = &sdlz->common;
  449. detach(&db);
  450. }
  451. static isc_result_t
  452. findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
  453. dns_dbnode_t **nodep)
  454. {
  455. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  456. dns_sdlznode_t *node = NULL;
  457. isc_result_t result;
  458. isc_buffer_t b;
  459. char namestr[DNS_NAME_MAXTEXT + 1];
  460. isc_buffer_t b2;
  461. char zonestr[DNS_NAME_MAXTEXT + 1];
  462. isc_boolean_t isorigin;
  463. dns_sdlzauthorityfunc_t authority;
  464. REQUIRE(VALID_SDLZDB(sdlz));
  465. REQUIRE(nodep != NULL && *nodep == NULL);
  466. if (sdlz->dlzimp->methods->newversion == NULL) {
  467. REQUIRE(create == ISC_FALSE);
  468. }
  469. isc_buffer_init(&b, namestr, sizeof(namestr));
  470. if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) {
  471. dns_name_t relname;
  472. unsigned int labels;
  473. labels = dns_name_countlabels(name) -
  474. dns_name_countlabels(&db->origin);
  475. dns_name_init(&relname, NULL);
  476. dns_name_getlabelsequence(name, 0, labels, &relname);
  477. result = dns_name_totext(&relname, ISC_TRUE, &b);
  478. if (result != ISC_R_SUCCESS)
  479. return (result);
  480. } else {
  481. result = dns_name_totext(name, ISC_TRUE, &b);
  482. if (result != ISC_R_SUCCESS)
  483. return (result);
  484. }
  485. isc_buffer_putuint8(&b, 0);
  486. isc_buffer_init(&b2, zonestr, sizeof(zonestr));
  487. result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b2);
  488. if (result != ISC_R_SUCCESS)
  489. return (result);
  490. isc_buffer_putuint8(&b2, 0);
  491. result = createnode(sdlz, &node);
  492. if (result != ISC_R_SUCCESS)
  493. return (result);
  494. isorigin = dns_name_equal(name, &sdlz->common.origin);
  495. /* make sure strings are always lowercase */
  496. dns_sdlz_tolower(zonestr);
  497. dns_sdlz_tolower(namestr);
  498. MAYBE_LOCK(sdlz->dlzimp);
  499. /* try to lookup the host (namestr) */
  500. result = sdlz->dlzimp->methods->lookup(zonestr, namestr,
  501. sdlz->dlzimp->driverarg,
  502. sdlz->dbdata, node);
  503. /*
  504. * if the host (namestr) was not found, try to lookup a
  505. * "wildcard" host.
  506. */
  507. if (result != ISC_R_SUCCESS && !create) {
  508. result = sdlz->dlzimp->methods->lookup(zonestr, "*",
  509. sdlz->dlzimp->driverarg,
  510. sdlz->dbdata, node);
  511. }
  512. MAYBE_UNLOCK(sdlz->dlzimp);
  513. if (result != ISC_R_SUCCESS && !isorigin && !create) {
  514. destroynode(node);
  515. return (result);
  516. }
  517. if (isorigin && sdlz->dlzimp->methods->authority != NULL) {
  518. MAYBE_LOCK(sdlz->dlzimp);
  519. authority = sdlz->dlzimp->methods->authority;
  520. result = (*authority)(zonestr, sdlz->dlzimp->driverarg,
  521. sdlz->dbdata, node);
  522. MAYBE_UNLOCK(sdlz->dlzimp);
  523. if (result != ISC_R_SUCCESS &&
  524. result != ISC_R_NOTIMPLEMENTED) {
  525. destroynode(node);
  526. return (result);
  527. }
  528. }
  529. if (node->name == NULL) {
  530. node->name = isc_mem_get(sdlz->common.mctx,
  531. sizeof(dns_name_t));
  532. if (node->name == NULL) {
  533. destroynode(node);
  534. return (ISC_R_NOMEMORY);
  535. }
  536. dns_name_init(node->name, NULL);
  537. result = dns_name_dup(name, sdlz->common.mctx, node->name);
  538. if (result != ISC_R_SUCCESS) {
  539. isc_mem_put(sdlz->common.mctx, node->name,
  540. sizeof(dns_name_t));
  541. destroynode(node);
  542. return (result);
  543. }
  544. }
  545. *nodep = node;
  546. return (ISC_R_SUCCESS);
  547. }
  548. static isc_result_t
  549. findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
  550. isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
  551. dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
  552. {
  553. UNUSED(db);
  554. UNUSED(name);
  555. UNUSED(options);
  556. UNUSED(now);
  557. UNUSED(nodep);
  558. UNUSED(foundname);
  559. UNUSED(rdataset);
  560. UNUSED(sigrdataset);
  561. return (ISC_R_NOTIMPLEMENTED);
  562. }
  563. static void
  564. attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
  565. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  566. dns_sdlznode_t *node = (dns_sdlznode_t *)source;
  567. REQUIRE(VALID_SDLZDB(sdlz));
  568. UNUSED(sdlz);
  569. LOCK(&node->lock);
  570. INSIST(node->references > 0);
  571. node->references++;
  572. INSIST(node->references != 0); /* Catch overflow. */
  573. UNLOCK(&node->lock);
  574. *targetp = source;
  575. }
  576. static void
  577. detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
  578. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  579. dns_sdlznode_t *node;
  580. isc_boolean_t need_destroy = ISC_FALSE;
  581. REQUIRE(VALID_SDLZDB(sdlz));
  582. REQUIRE(targetp != NULL && *targetp != NULL);
  583. UNUSED(sdlz);
  584. node = (dns_sdlznode_t *)(*targetp);
  585. LOCK(&node->lock);
  586. INSIST(node->references > 0);
  587. node->references--;
  588. if (node->references == 0)
  589. need_destroy = ISC_TRUE;
  590. UNLOCK(&node->lock);
  591. if (need_destroy)
  592. destroynode(node);
  593. *targetp = NULL;
  594. }
  595. static isc_result_t
  596. expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
  597. UNUSED(db);
  598. UNUSED(node);
  599. UNUSED(now);
  600. INSIST(0);
  601. return (ISC_R_UNEXPECTED);
  602. }
  603. static void
  604. printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
  605. UNUSED(db);
  606. UNUSED(node);
  607. UNUSED(out);
  608. return;
  609. }
  610. static isc_result_t
  611. createiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp)
  612. {
  613. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  614. sdlz_dbiterator_t *sdlziter;
  615. isc_result_t result;
  616. isc_buffer_t b;
  617. char zonestr[DNS_NAME_MAXTEXT + 1];
  618. REQUIRE(VALID_SDLZDB(sdlz));
  619. if (sdlz->dlzimp->methods->allnodes == NULL)
  620. return (ISC_R_NOTIMPLEMENTED);
  621. if ((options & DNS_DB_NSEC3ONLY) != 0 ||
  622. (options & DNS_DB_NONSEC3) != 0)
  623. return (ISC_R_NOTIMPLEMENTED);
  624. isc_buffer_init(&b, zonestr, sizeof(zonestr));
  625. result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b);
  626. if (result != ISC_R_SUCCESS)
  627. return (result);
  628. isc_buffer_putuint8(&b, 0);
  629. sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t));
  630. if (sdlziter == NULL)
  631. return (ISC_R_NOMEMORY);
  632. sdlziter->common.methods = &dbiterator_methods;
  633. sdlziter->common.db = NULL;
  634. dns_db_attach(db, &sdlziter->common.db);
  635. sdlziter->common.relative_names = ISC_TF(options & DNS_DB_RELATIVENAMES);
  636. sdlziter->common.magic = DNS_DBITERATOR_MAGIC;
  637. ISC_LIST_INIT(sdlziter->nodelist);
  638. sdlziter->current = NULL;
  639. sdlziter->origin = NULL;
  640. /* make sure strings are always lowercase */
  641. dns_sdlz_tolower(zonestr);
  642. MAYBE_LOCK(sdlz->dlzimp);
  643. result = sdlz->dlzimp->methods->allnodes(zonestr,
  644. sdlz->dlzimp->driverarg,
  645. sdlz->dbdata, sdlziter);
  646. MAYBE_UNLOCK(sdlz->dlzimp);
  647. if (result != ISC_R_SUCCESS) {
  648. dns_dbiterator_t *iter = &sdlziter->common;
  649. dbiterator_destroy(&iter);
  650. return (result);
  651. }
  652. if (sdlziter->origin != NULL) {
  653. ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link);
  654. ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link);
  655. }
  656. *iteratorp = (dns_dbiterator_t *)sdlziter;
  657. return (ISC_R_SUCCESS);
  658. }
  659. static isc_result_t
  660. findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
  661. dns_rdatatype_t type, dns_rdatatype_t covers,
  662. isc_stdtime_t now, dns_rdataset_t *rdataset,
  663. dns_rdataset_t *sigrdataset)
  664. {
  665. dns_rdatalist_t *list;
  666. dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
  667. REQUIRE(VALID_SDLZNODE(node));
  668. UNUSED(db);
  669. UNUSED(version);
  670. UNUSED(covers);
  671. UNUSED(now);
  672. UNUSED(sigrdataset);
  673. if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig)
  674. return (ISC_R_NOTIMPLEMENTED);
  675. list = ISC_LIST_HEAD(sdlznode->lists);
  676. while (list != NULL) {
  677. if (list->type == type)
  678. break;
  679. list = ISC_LIST_NEXT(list, link);
  680. }
  681. if (list == NULL)
  682. return (ISC_R_NOTFOUND);
  683. list_tordataset(list, db, node, rdataset);
  684. return (ISC_R_SUCCESS);
  685. }
  686. static isc_result_t
  687. find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
  688. dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
  689. dns_dbnode_t **nodep, dns_name_t *foundname,
  690. dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
  691. {
  692. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  693. dns_dbnode_t *node = NULL;
  694. dns_fixedname_t fname;
  695. dns_rdataset_t xrdataset;
  696. dns_name_t *xname;
  697. unsigned int nlabels, olabels;
  698. isc_result_t result;
  699. unsigned int i;
  700. REQUIRE(VALID_SDLZDB(sdlz));
  701. REQUIRE(nodep == NULL || *nodep == NULL);
  702. REQUIRE(version == NULL || version == (void*)&sdlz->dummy_version);
  703. UNUSED(options);
  704. UNUSED(sdlz);
  705. if (!dns_name_issubdomain(name, &db->origin))
  706. return (DNS_R_NXDOMAIN);
  707. olabels = dns_name_countlabels(&db->origin);
  708. nlabels = dns_name_countlabels(name);
  709. dns_fixedname_init(&fname);
  710. xname = dns_fixedname_name(&fname);
  711. if (rdataset == NULL) {
  712. dns_rdataset_init(&xrdataset);
  713. rdataset = &xrdataset;
  714. }
  715. result = DNS_R_NXDOMAIN;
  716. for (i = olabels; i <= nlabels; i++) {
  717. /*
  718. * Look up the next label.
  719. */
  720. dns_name_getlabelsequence(name, nlabels - i, i, xname);
  721. result = findnode(db, xname, ISC_FALSE, &node);
  722. if (result != ISC_R_SUCCESS) {
  723. result = DNS_R_NXDOMAIN;
  724. continue;
  725. }
  726. /*
  727. * Look for a DNAME at the current label, unless this is
  728. * the qname.
  729. */
  730. if (i < nlabels) {
  731. result = findrdataset(db, node, version,
  732. dns_rdatatype_dname,
  733. 0, now, rdataset, sigrdataset);
  734. if (result == ISC_R_SUCCESS) {
  735. result = DNS_R_DNAME;
  736. break;
  737. }
  738. }
  739. /*
  740. * Look for an NS at the current label, unless this is the
  741. * origin or glue is ok.
  742. */
  743. if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
  744. result = findrdataset(db, node, version,
  745. dns_rdatatype_ns,
  746. 0, now, rdataset, sigrdataset);
  747. if (result == ISC_R_SUCCESS) {
  748. if (i == nlabels && type == dns_rdatatype_any)
  749. {
  750. result = DNS_R_ZONECUT;
  751. dns_rdataset_disassociate(rdataset);
  752. if (sigrdataset != NULL &&
  753. dns_rdataset_isassociated
  754. (sigrdataset)) {
  755. dns_rdataset_disassociate
  756. (sigrdataset);
  757. }
  758. } else
  759. result = DNS_R_DELEGATION;
  760. break;
  761. }
  762. }
  763. /*
  764. * If the current name is not the qname, add another label
  765. * and try again.
  766. */
  767. if (i < nlabels) {
  768. destroynode(node);
  769. node = NULL;
  770. continue;
  771. }
  772. /*
  773. * If we're looking for ANY, we're done.
  774. */
  775. if (type == dns_rdatatype_any) {
  776. result = ISC_R_SUCCESS;
  777. break;
  778. }
  779. /*
  780. * Look for the qtype.
  781. */
  782. result = findrdataset(db, node, version, type,
  783. 0, now, rdataset, sigrdataset);
  784. if (result == ISC_R_SUCCESS)
  785. break;
  786. /*
  787. * Look for a CNAME
  788. */
  789. if (type != dns_rdatatype_cname) {
  790. result = findrdataset(db, node, version,
  791. dns_rdatatype_cname,
  792. 0, now, rdataset, sigrdataset);
  793. if (result == ISC_R_SUCCESS) {
  794. result = DNS_R_CNAME;
  795. break;
  796. }
  797. }
  798. result = DNS_R_NXRRSET;
  799. break;
  800. }
  801. if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset))
  802. dns_rdataset_disassociate(rdataset);
  803. if (foundname != NULL) {
  804. isc_result_t xresult;
  805. xresult = dns_name_copy(xname, foundname, NULL);
  806. if (xresult != ISC_R_SUCCESS) {
  807. if (node != NULL)
  808. destroynode(node);
  809. if (dns_rdataset_isassociated(rdataset))
  810. dns_rdataset_disassociate(rdataset);
  811. return (DNS_R_BADDB);
  812. }
  813. }
  814. if (nodep != NULL)
  815. *nodep = node;
  816. else if (node != NULL)
  817. detachnode(db, &node);
  818. return (result);
  819. }
  820. static isc_result_t
  821. allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
  822. isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
  823. {
  824. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) db;
  825. sdlz_rdatasetiter_t *iterator;
  826. REQUIRE(VALID_SDLZDB(sdlz));
  827. REQUIRE(version == NULL ||
  828. version == (void*)&sdlz->dummy_version ||
  829. version == sdlz->future_version);
  830. UNUSED(version);
  831. UNUSED(now);
  832. iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t));
  833. if (iterator == NULL)
  834. return (ISC_R_NOMEMORY);
  835. iterator->common.magic = DNS_RDATASETITER_MAGIC;
  836. iterator->common.methods = &rdatasetiter_methods;
  837. iterator->common.db = db;
  838. iterator->common.node = NULL;
  839. attachnode(db, node, &iterator->common.node);
  840. iterator->common.version = version;
  841. iterator->common.now = now;
  842. *iteratorp = (dns_rdatasetiter_t *)iterator;
  843. return (ISC_R_SUCCESS);
  844. }
  845. static isc_result_t
  846. modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
  847. dns_rdataset_t *rdataset, unsigned int options,
  848. dns_sdlzmodrdataset_t mod_function)
  849. {
  850. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  851. dns_master_style_t *style = NULL;
  852. isc_result_t result;
  853. isc_buffer_t *buffer = NULL;
  854. isc_mem_t *mctx;
  855. dns_sdlznode_t *sdlznode;
  856. char *rdatastr = NULL;
  857. char name[DNS_NAME_MAXTEXT + 1];
  858. REQUIRE(VALID_SDLZDB(sdlz));
  859. if (mod_function == NULL)
  860. return (ISC_R_NOTIMPLEMENTED);
  861. sdlznode = (dns_sdlznode_t *)node;
  862. UNUSED(options);
  863. dns_name_format(sdlznode->name, name, sizeof(name));
  864. mctx = sdlz->common.mctx;
  865. result = isc_buffer_allocate(mctx, &buffer, 1024);
  866. if (result != ISC_R_SUCCESS)
  867. return (result);
  868. result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1, mctx);
  869. if (result != ISC_R_SUCCESS)
  870. goto cleanup;
  871. result = dns_master_rdatasettotext(sdlznode->name, rdataset,
  872. style, buffer);
  873. if (result != ISC_R_SUCCESS)
  874. goto cleanup;
  875. if (isc_buffer_usedlength(buffer) < 1) {
  876. result = ISC_R_BADADDRESSFORM;
  877. goto cleanup;
  878. }
  879. rdatastr = isc_buffer_base(buffer);
  880. if (rdatastr == NULL) {
  881. result = ISC_R_NOMEMORY;
  882. goto cleanup;
  883. }
  884. rdatastr[isc_buffer_usedlength(buffer) - 1] = 0;
  885. MAYBE_LOCK(sdlz->dlzimp);
  886. result = mod_function(name, rdatastr, sdlz->dlzimp->driverarg,
  887. sdlz->dbdata, version);
  888. MAYBE_UNLOCK(sdlz->dlzimp);
  889. cleanup:
  890. isc_buffer_free(&buffer);
  891. if (style != NULL)
  892. dns_master_styledestroy(&style, mctx);
  893. return (result);
  894. }
  895. static isc_result_t
  896. addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
  897. isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
  898. dns_rdataset_t *addedrdataset)
  899. {
  900. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  901. isc_result_t result;
  902. UNUSED(now);
  903. UNUSED(addedrdataset);
  904. REQUIRE(VALID_SDLZDB(sdlz));
  905. if (sdlz->dlzimp->methods->addrdataset == NULL)
  906. return (ISC_R_NOTIMPLEMENTED);
  907. result = modrdataset(db, node, version, rdataset, options,
  908. sdlz->dlzimp->methods->addrdataset);
  909. return (result);
  910. }
  911. static isc_result_t
  912. subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
  913. dns_rdataset_t *rdataset, unsigned int options,
  914. dns_rdataset_t *newrdataset)
  915. {
  916. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  917. isc_result_t result;
  918. UNUSED(newrdataset);
  919. REQUIRE(VALID_SDLZDB(sdlz));
  920. if (sdlz->dlzimp->methods->subtractrdataset == NULL) {
  921. return (ISC_R_NOTIMPLEMENTED);
  922. }
  923. result = modrdataset(db, node, version, rdataset, options,
  924. sdlz->dlzimp->methods->subtractrdataset);
  925. return (result);
  926. }
  927. static isc_result_t
  928. deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
  929. dns_rdatatype_t type, dns_rdatatype_t covers)
  930. {
  931. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  932. char name[DNS_NAME_MAXTEXT + 1];
  933. char b_type[DNS_RDATATYPE_FORMATSIZE];
  934. dns_sdlznode_t *sdlznode;
  935. isc_result_t result;
  936. UNUSED(covers);
  937. REQUIRE(VALID_SDLZDB(sdlz));
  938. if (sdlz->dlzimp->methods->delrdataset == NULL)
  939. return (ISC_R_NOTIMPLEMENTED);
  940. sdlznode = (dns_sdlznode_t *)node;
  941. dns_name_format(sdlznode->name, name, sizeof(name));
  942. dns_rdatatype_format(type, b_type, sizeof(b_type));
  943. MAYBE_LOCK(sdlz->dlzimp);
  944. result = sdlz->dlzimp->methods->delrdataset(name, b_type,
  945. sdlz->dlzimp->driverarg,
  946. sdlz->dbdata, version);
  947. MAYBE_UNLOCK(sdlz->dlzimp);
  948. return (result);
  949. }
  950. static isc_boolean_t
  951. issecure(dns_db_t *db) {
  952. UNUSED(db);
  953. return (ISC_FALSE);
  954. }
  955. static unsigned int
  956. nodecount(dns_db_t *db) {
  957. UNUSED(db);
  958. return (0);
  959. }
  960. static isc_boolean_t
  961. ispersistent(dns_db_t *db) {
  962. UNUSED(db);
  963. return (ISC_TRUE);
  964. }
  965. static void
  966. overmem(dns_db_t *db, isc_boolean_t overmem) {
  967. UNUSED(db);
  968. UNUSED(overmem);
  969. }
  970. static void
  971. settask(dns_db_t *db, isc_task_t *task) {
  972. UNUSED(db);
  973. UNUSED(task);
  974. }
  975. /*
  976. * getoriginnode() is used by the update code to find the
  977. * dns_rdatatype_dnskey record for a zone
  978. */
  979. static isc_result_t
  980. getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
  981. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
  982. isc_result_t result;
  983. REQUIRE(VALID_SDLZDB(sdlz));
  984. if (sdlz->dlzimp->methods->newversion == NULL)
  985. return (ISC_R_NOTIMPLEMENTED);
  986. result = findnode(db, &sdlz->common.origin, ISC_FALSE, nodep);
  987. if (result != ISC_R_SUCCESS)
  988. sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed : %s",
  989. isc_result_totext(result));
  990. return (result);
  991. }
  992. static dns_dbmethods_t sdlzdb_methods = {
  993. attach,
  994. detach,
  995. beginload,
  996. endload,
  997. dump,
  998. currentversion,
  999. newversion,
  1000. attachversion,
  1001. closeversion,
  1002. findnode,
  1003. find,
  1004. findzonecut,
  1005. attachnode,
  1006. detachnode,
  1007. expirenode,
  1008. printnode,
  1009. createiterator,
  1010. findrdataset,
  1011. allrdatasets,
  1012. addrdataset,
  1013. subtractrdataset,
  1014. deleterdataset,
  1015. issecure,
  1016. nodecount,
  1017. ispersistent,
  1018. overmem,
  1019. settask,
  1020. getoriginnode,
  1021. NULL,
  1022. NULL,
  1023. NULL,
  1024. NULL,
  1025. NULL,
  1026. NULL,
  1027. NULL,
  1028. NULL,
  1029. NULL,
  1030. NULL
  1031. };
  1032. /*
  1033. * Database Iterator Methods. These methods were "borrowed" from the SDB
  1034. * driver interface. See the SDB driver interface documentation for more info.
  1035. */
  1036. static void
  1037. dbiterator_destroy(dns_dbiterator_t **iteratorp) {
  1038. sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp);
  1039. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db;
  1040. while (!ISC_LIST_EMPTY(sdlziter->nodelist)) {
  1041. dns_sdlznode_t *node;
  1042. node = ISC_LIST_HEAD(sdlziter->nodelist);
  1043. ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
  1044. destroynode(node);
  1045. }
  1046. dns_db_detach(&sdlziter->common.db);
  1047. isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t));
  1048. *iteratorp = NULL;
  1049. }
  1050. static isc_result_t
  1051. dbiterator_first(dns_dbiterator_t *iterator) {
  1052. sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
  1053. sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
  1054. if (sdlziter->current == NULL)
  1055. return (ISC_R_NOMORE);
  1056. else
  1057. return (ISC_R_SUCCESS);
  1058. }
  1059. static isc_result_t
  1060. dbiterator_last(dns_dbiterator_t *iterator) {
  1061. sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
  1062. sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist);
  1063. if (sdlziter->current == NULL)
  1064. return (ISC_R_NOMORE);
  1065. else
  1066. return (ISC_R_SUCCESS);
  1067. }
  1068. static isc_result_t
  1069. dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
  1070. sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
  1071. sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
  1072. while (sdlziter->current != NULL) {
  1073. if (dns_name_equal(sdlziter->current->name, name))
  1074. return (ISC_R_SUCCESS);
  1075. sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
  1076. }
  1077. return (ISC_R_NOTFOUND);
  1078. }
  1079. static isc_result_t
  1080. dbiterator_prev(dns_dbiterator_t *iterator) {
  1081. sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
  1082. sdlziter->current = ISC_LIST_PREV(sdlziter->current, link);
  1083. if (sdlziter->current == NULL)
  1084. return (ISC_R_NOMORE);
  1085. else
  1086. return (ISC_R_SUCCESS);
  1087. }
  1088. static isc_result_t
  1089. dbiterator_next(dns_dbiterator_t *iterator) {
  1090. sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
  1091. sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
  1092. if (sdlziter->current == NULL)
  1093. return (ISC_R_NOMORE);
  1094. else
  1095. return (ISC_R_SUCCESS);
  1096. }
  1097. static isc_result_t
  1098. dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
  1099. dns_name_t *name)
  1100. {
  1101. sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
  1102. attachnode(iterator->db, sdlziter->current, nodep);
  1103. if (name != NULL)
  1104. return (dns_name_copy(sdlziter->current->name, name, NULL));
  1105. return (ISC_R_SUCCESS);
  1106. }
  1107. static isc_result_t
  1108. dbiterator_pause(dns_dbiterator_t *iterator) {
  1109. UNUSED(iterator);
  1110. return (ISC_R_SUCCESS);
  1111. }
  1112. static isc_result_t
  1113. dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
  1114. UNUSED(iterator);
  1115. return (dns_name_copy(dns_rootname, name, NULL));
  1116. }
  1117. /*
  1118. * Rdataset Methods. These methods were "borrowed" from the SDB driver
  1119. * interface. See the SDB driver interface documentation for more info.
  1120. */
  1121. static void
  1122. disassociate(dns_rdataset_t *rdataset) {
  1123. dns_dbnode_t *node = rdataset->private5;
  1124. dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
  1125. dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
  1126. detachnode(db, &node);
  1127. isc__rdatalist_disassociate(rdataset);
  1128. }
  1129. static void
  1130. rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
  1131. dns_dbnode_t *node = source->private5;
  1132. dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
  1133. dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
  1134. dns_dbnode_t *tempdb = NULL;
  1135. isc__rdatalist_clone(source, target);
  1136. attachnode(db, node, &tempdb);
  1137. source->private5 = tempdb;
  1138. }
  1139. static dns_rdatasetmethods_t rdataset_methods = {
  1140. disassociate,
  1141. isc__rdatalist_first,
  1142. isc__rdatalist_next,
  1143. isc__rdatalist_current,
  1144. rdataset_clone,
  1145. isc__rdatalist_count,
  1146. isc__rdatalist_addnoqname,
  1147. isc__rdatalist_getnoqname,
  1148. NULL,
  1149. NULL,
  1150. NULL,
  1151. NULL,
  1152. NULL,
  1153. NULL,
  1154. NULL
  1155. };
  1156. static void
  1157. list_tordataset(dns_rdatalist_t *rdatalist,
  1158. dns_db_t *db, dns_dbnode_t *node,
  1159. dns_rdataset_t *rdataset)
  1160. {
  1161. /*
  1162. * The sdlz rdataset is an rdatalist with some additions.
  1163. * - private1 & private2 are used by the rdatalist.
  1164. * - private3 & private 4 are unused.
  1165. * - private5 is the node.
  1166. */
  1167. /* This should never fail. */
  1168. RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
  1169. ISC_R_SUCCESS);
  1170. rdataset->methods = &rdataset_methods;
  1171. dns_db_attachnode(db, node, &rdataset->private5);
  1172. }
  1173. /*
  1174. * SDLZ core methods. This is the core of the new DLZ functionality.
  1175. */
  1176. /*%
  1177. * Build a 'bind' database driver structure to be returned by
  1178. * either the find zone or the allow zone transfer method.
  1179. * This method is only available in this source file, it is
  1180. * not made available anywhere else.
  1181. */
  1182. static isc_result_t
  1183. dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
  1184. dns_name_t *name, dns_rdataclass_t rdclass, dns_db_t **dbp)
  1185. {
  1186. isc_result_t result;
  1187. dns_sdlz_db_t *sdlzdb;
  1188. dns_sdlzimplementation_t *imp;
  1189. /* check that things are as we expect */
  1190. REQUIRE(dbp != NULL && *dbp == NULL);
  1191. REQUIRE(name != NULL);
  1192. imp = (dns_sdlzimplementation_t *) driverarg;
  1193. /* allocate and zero memory for driver structure */
  1194. sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
  1195. if (sdlzdb == NULL)
  1196. return (ISC_R_NOMEMORY);
  1197. memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
  1198. /* initialize and set origin */
  1199. dns_name_init(&sdlzdb->common.origin, NULL);
  1200. result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
  1201. if (result != ISC_R_SUCCESS)
  1202. goto mem_cleanup;
  1203. /* initialize the reference count mutex */
  1204. result = isc_mutex_init(&sdlzdb->refcnt_lock);
  1205. if (result != ISC_R_SUCCESS)
  1206. goto name_cleanup;
  1207. /* set the rest of the database structure attributes */
  1208. sdlzdb->dlzimp = imp;
  1209. sdlzdb->common.methods = &sdlzdb_methods;
  1210. sdlzdb->common.attributes = 0;
  1211. sdlzdb->common.rdclass = rdclass;
  1212. sdlzdb->common.mctx = NULL;
  1213. sdlzdb->dbdata = dbdata;
  1214. sdlzdb->references = 1;
  1215. /* attach to the memory context */
  1216. isc_mem_attach(mctx, &sdlzdb->common.mctx);
  1217. /* mark structure as valid */
  1218. sdlzdb->common.magic = DNS_DB_MAGIC;
  1219. sdlzdb->common.impmagic = SDLZDB_MAGIC;
  1220. *dbp = (dns_db_t *) sdlzdb;
  1221. return (result);
  1222. /*
  1223. * reference count mutex could not be initialized, clean up
  1224. * name memory
  1225. */
  1226. name_cleanup:
  1227. dns_name_free(&sdlzdb->common.origin, mctx);
  1228. mem_cleanup:
  1229. isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
  1230. return (result);
  1231. }
  1232. static isc_result_t
  1233. dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
  1234. dns_rdataclass_t rdclass, dns_name_t *name,
  1235. isc_sockaddr_t *clientaddr, dns_db_t **dbp)
  1236. {
  1237. isc_buffer_t b;
  1238. isc_buffer_t b2;
  1239. char namestr[DNS_NAME_MAXTEXT + 1];
  1240. char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")
  1241. + 1];
  1242. isc_netaddr_t netaddr;
  1243. isc_result_t result;
  1244. dns_sdlzimplementation_t *imp;
  1245. /*
  1246. * Perform checks to make sure data is as we expect it to be.
  1247. */
  1248. REQUIRE(driverarg != NULL);
  1249. REQUIRE(name != NULL);
  1250. REQUIRE(clientaddr != NULL);
  1251. REQUIRE(dbp != NULL && *dbp == NULL);
  1252. imp = (dns_sdlzimplementation_t *) driverarg;
  1253. /* Convert DNS name to ascii text */
  1254. isc_buffer_init(&b, namestr, sizeof(namestr));
  1255. result = dns_name_totext(name, ISC_TRUE, &b);
  1256. if (result != ISC_R_SUCCESS)
  1257. return (result);
  1258. isc_buffer_putuint8(&b, 0);
  1259. /* convert client address to ascii text */
  1260. isc_buffer_init(&b2, clientstr, sizeof(clientstr));
  1261. isc_netaddr_fromsockaddr(&netaddr, clientaddr);
  1262. result = isc_netaddr_totext(&netaddr, &b2);
  1263. if (result != ISC_R_SUCCESS)
  1264. return (result);
  1265. isc_buffer_putuint8(&b2, 0);
  1266. /* make sure strings are always lowercase */
  1267. dns_sdlz_tolower(namestr);
  1268. dns_sdlz_tolower(clientstr);
  1269. /* Call SDLZ driver's find zone method */
  1270. if (imp->methods->allowzonexfr != NULL) {
  1271. MAYBE_LOCK(imp);
  1272. result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
  1273. namestr, clientstr);
  1274. MAYBE_UNLOCK(imp);
  1275. /*
  1276. * if zone is supported and transfers allowed build a 'bind'
  1277. * database driver
  1278. */
  1279. if (result == ISC_R_SUCCESS)
  1280. result = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
  1281. name, rdclass, dbp);
  1282. return (result);
  1283. }
  1284. return (ISC_R_NOTIMPLEMENTED);
  1285. }
  1286. static isc_result_t
  1287. dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
  1288. char *argv[], void *driverarg, void **dbdata)
  1289. {
  1290. dns_sdlzimplementation_t *imp;
  1291. isc_result_t result = ISC_R_NOTFOUND;
  1292. /* Write debugging message to log */
  1293. sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver.");
  1294. /*
  1295. * Performs checks to make sure data is as we expect it to be.
  1296. */
  1297. REQUIRE(driverarg != NULL);
  1298. REQUIRE(dlzname != NULL);
  1299. REQUIRE(dbdata != NULL);
  1300. UNUSED(mctx);
  1301. imp = driverarg;
  1302. /* If the create method exists, call it. */
  1303. if (imp->methods->create != NULL) {
  1304. MAYBE_LOCK(imp);
  1305. result = imp->methods->create(dlzname, argc, argv,
  1306. imp->driverarg, dbdata);
  1307. MAYBE_UNLOCK(imp);
  1308. }
  1309. /* Write debugging message to log */
  1310. if (result == ISC_R_SUCCESS) {
  1311. sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully.");
  1312. } else {
  1313. sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load.");
  1314. }
  1315. return (result);
  1316. }
  1317. static void
  1318. dns_sdlzdestroy(void *driverdata, void **dbdata)
  1319. {
  1320. dns_sdlzimplementation_t *imp;
  1321. /* Write debugging message to log */
  1322. sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver.");
  1323. imp = driverdata;
  1324. /* If the destroy method exists, call it. */
  1325. if (imp->methods->destroy != NULL) {
  1326. MAYBE_LOCK(imp);
  1327. imp->methods->destroy(imp->driverarg, dbdata);
  1328. MAYBE_UNLOCK(imp);
  1329. }
  1330. }
  1331. static isc_result_t
  1332. dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
  1333. dns_rdataclass_t rdclass, dns_name_t *name, dns_db_t **dbp)
  1334. {
  1335. isc_buffer_t b;
  1336. char namestr[DNS_NAME_MAXTEXT + 1];
  1337. isc_result_t result;
  1338. dns_sdlzimplementation_t *imp;
  1339. /*
  1340. * Perform checks to make sure data is as we expect it to be.
  1341. */
  1342. REQUIRE(driverarg != NULL);
  1343. REQUIRE(name != NULL);
  1344. REQUIRE(dbp != NULL && *dbp == NULL);
  1345. imp = (dns_sdlzimplementation_t *) driverarg;
  1346. /* Convert DNS name to ascii text */
  1347. isc_buffer_init(&b, namestr, sizeof(namestr));
  1348. result = dns_name_totext(name, ISC_TRUE, &b);
  1349. if (result != ISC_R_SUCCESS)
  1350. return (result);
  1351. isc_buffer_putuint8(&b, 0);
  1352. /* make sure strings are always lowercase */
  1353. dns_sdlz_tolower(namestr);
  1354. /* Call SDLZ driver's find zone method */
  1355. MAYBE_LOCK(imp);
  1356. result = imp->methods->findzone(imp->driverarg, dbdata, namestr);
  1357. MAYBE_UNLOCK(imp);
  1358. /*
  1359. * if zone is supported build a 'bind' database driver
  1360. * structure to return
  1361. */
  1362. if (result == ISC_R_SUCCESS)
  1363. result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
  1364. rdclass, dbp);
  1365. return (result);
  1366. }
  1367. static isc_result_t
  1368. dns_sdlzconfigure(void *driverarg, void *dbdata, dns_view_t *view)
  1369. {
  1370. isc_result_t result;
  1371. dns_sdlzimplementation_t *imp;
  1372. REQUIRE(driverarg != NULL);
  1373. imp = (dns_sdlzimplementation_t *) driverarg;
  1374. /* Call SDLZ driver's configure method */
  1375. if (imp->methods->configure != NULL) {
  1376. MAYBE_LOCK(imp);
  1377. result = imp->methods->configure(view, imp->driverarg, dbdata);
  1378. MAYBE_UNLOCK(imp);
  1379. } else {
  1380. result = ISC_R_SUCCESS;
  1381. }
  1382. return (result);
  1383. }
  1384. static isc_boolean_t
  1385. dns_sdlzssumatch(dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr,
  1386. dns_rdatatype_t type, const dst_key_t *key, void *driverarg,
  1387. void *dbdata)
  1388. {
  1389. dns_sdlzimplementation_t *imp;
  1390. char b_signer[DNS_NAME_FORMATSIZE];
  1391. char b_name[DNS_NAME_FORMATSIZE];
  1392. char b_addr[ISC_NETADDR_FORMATSIZE];
  1393. char b_type[DNS_RDATATYPE_FORMATSIZE];
  1394. char b_key[DST_KEY_FORMATSIZE];
  1395. isc_buffer_t *tkey_token = NULL;
  1396. isc_region_t token_region;
  1397. isc_uint32_t token_len = 0;
  1398. isc_boolean_t ret;
  1399. REQUIRE(driverarg != NULL);
  1400. imp = (dns_sdlzimplementation_t *) driverarg;
  1401. if (imp->methods->ssumatch == NULL)
  1402. return (ISC_FALSE);
  1403. /*
  1404. * Format the request elements. sdlz operates on strings, not
  1405. * structures
  1406. */
  1407. if (signer != NULL)
  1408. dns_name_format(signer, b_signer, sizeof(b_signer));
  1409. else
  1410. b_signer[0] = 0;
  1411. dns_name_format(name, b_name, sizeof(b_name));
  1412. if (tcpaddr != NULL)
  1413. isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
  1414. else
  1415. b_addr[0] = 0;
  1416. dns_rdatatype_format(type, b_type, sizeof(b_type));
  1417. if (key != NULL) {
  1418. dst_key_format(key, b_key, sizeof(b_key));
  1419. tkey_token = dst_key_tkeytoken(key);
  1420. } else
  1421. b_key[0] = 0;
  1422. if (tkey_token != NULL) {
  1423. isc_buffer_region(tkey_token, &token_region);
  1424. token_len = token_region.length;
  1425. }
  1426. MAYBE_LOCK(imp);
  1427. ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key,
  1428. token_len,
  1429. token_len != 0 ? token_region.base : NULL,
  1430. imp->driverarg, dbdata);
  1431. MAYBE_UNLOCK(imp);
  1432. return (ret);
  1433. }
  1434. static dns_dlzmethods_t sdlzmethods = {
  1435. dns_sdlzcreate,
  1436. dns_sdlzdestroy,
  1437. dns_sdlzfindzone,
  1438. dns_sdlzallowzonexfr,
  1439. dns_sdlzconfigure,
  1440. dns_sdlzssumatch
  1441. };
  1442. /*
  1443. * Public functions.
  1444. */
  1445. isc_result_t
  1446. dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
  1447. const char *data)
  1448. {
  1449. dns_rdatalist_t *rdatalist;
  1450. dns_rdata_t *rdata;
  1451. dns_rdatatype_t typeval;
  1452. isc_consttextregion_t r;
  1453. isc_buffer_t b;
  1454. isc_buffer_t *rdatabuf = NULL;
  1455. isc_lex_t *lex;
  1456. isc_result_t result;
  1457. unsigned int size;
  1458. isc_mem_t *mctx;
  1459. dns_name_t *origin;
  1460. REQUIRE(VALID_SDLZLOOKUP(lookup));
  1461. REQUIRE(type != NULL);
  1462. REQUIRE(data != NULL);
  1463. mctx = lookup->sdlz->common.mctx;
  1464. r.base = type;
  1465. r.length = strlen(type);
  1466. result = dns_rdatatype_fromtext(&typeval, (void *) &r);
  1467. if (result != ISC_R_SUCCESS)
  1468. return (result);
  1469. rdatalist = ISC_LIST_HEAD(lookup->lists);
  1470. while (rdatalist != NULL) {
  1471. if (rdatalist->type == typeval)
  1472. break;
  1473. rdatalist = ISC_LIST_NEXT(rdatalist, link);
  1474. }
  1475. if (rdatalist == NULL) {
  1476. rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
  1477. if (rdatalist == NULL)
  1478. return (ISC_R_NOMEMORY);
  1479. rdatalist->rdclass = lookup->sdlz->common.rdclass;
  1480. rdatalist->type = typeval;
  1481. rdatalist->covers = 0;
  1482. rdatalist->ttl = ttl;
  1483. ISC_LIST_INIT(rdatalist->rdata);
  1484. ISC_LINK_INIT(rdatalist, link);
  1485. ISC_LIST_APPEND(lookup->lists, rdatalist, link);
  1486. } else
  1487. if (rdatalist->ttl > ttl) {
  1488. /*
  1489. * BIND9 doesn't enforce all RRs in an RRset
  1490. * having the same TTL, as per RFC 2136,
  1491. * section 7.12. If a DLZ backend has
  1492. * different TTLs, then the best
  1493. * we can do is return the lowest.
  1494. */
  1495. rdatalist->ttl = ttl;
  1496. }
  1497. rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
  1498. if (rdata == NULL)
  1499. return (ISC_R_NOMEMORY);
  1500. dns_rdata_init(rdata);
  1501. if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
  1502. origin = &lookup->sdlz->common.origin;
  1503. else
  1504. origin = dns_rootname;
  1505. lex = NULL;
  1506. result = isc_lex_create(mctx, 64, &lex);
  1507. if (result != ISC_R_SUCCESS)
  1508. goto failure;
  1509. size = initial_size(data);
  1510. do {
  1511. isc_buffer_init(&b, data, strlen(data));
  1512. isc_buffer_add(&b, strlen(data));
  1513. result = isc_lex_openbuffer(lex, &b);
  1514. if (result != ISC_R_SUCCESS)
  1515. goto failure;
  1516. rdatabuf = NULL;
  1517. result = isc_buffer_allocate(mctx, &rdatabuf, size);
  1518. if (result != ISC_R_SUCCESS)
  1519. goto failure;
  1520. result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
  1521. rdatalist->type, lex,
  1522. origin, ISC_FALSE,
  1523. mctx, rdatabuf,
  1524. &lookup->callbacks);
  1525. if (result != ISC_R_SUCCESS)
  1526. isc_buffer_free(&rdatabuf);
  1527. if (size >= 65535)
  1528. break;
  1529. size *= 2;
  1530. if (size >= 65535)
  1531. size = 65535;
  1532. } while (result == ISC_R_NOSPACE);
  1533. if (result != ISC_R_SUCCESS)
  1534. goto failure;
  1535. ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
  1536. ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
  1537. if (lex != NULL)
  1538. isc_lex_destroy(&lex);
  1539. return (ISC_R_SUCCESS);
  1540. failure:
  1541. if (rdatabuf != NULL)
  1542. isc_buffer_free(&rdatabuf);
  1543. if (lex != NULL)
  1544. isc_lex_destroy(&lex);
  1545. isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
  1546. return (result);
  1547. }
  1548. isc_result_t
  1549. dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
  1550. const char *type, dns_ttl_t ttl, const char *data)
  1551. {
  1552. dns_name_t *newname, *origin;
  1553. dns_fixedname_t fnewname;
  1554. dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
  1555. dns_sdlznode_t *sdlznode;
  1556. isc_mem_t *mctx = sdlz->common.mctx;
  1557. isc_buffer_t b;
  1558. isc_result_t result;
  1559. dns_fixedname_init(&fnewname);
  1560. newname = dns_fixedname_name(&fnewname);
  1561. if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
  1562. origin = &sdlz->common.origin;
  1563. else
  1564. origin = dns_rootname;
  1565. isc_buffer_init(&b, name, strlen(name));
  1566. isc_buffer_add(&b, strlen(name));
  1567. result = dns_name_fromtext(newname, &b, origin, 0, NULL);
  1568. if (result != ISC_R_SUCCESS)
  1569. return (result);
  1570. if (allnodes->common.relative_names) {
  1571. /* All names are relative to the root */
  1572. unsigned int nlabels = dns_name_countlabels(newname);
  1573. dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
  1574. }
  1575. sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
  1576. if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
  1577. sdlznode = NULL;
  1578. result = createnode(sdlz, &sdlznode);
  1579. if (result != ISC_R_SUCCESS)
  1580. return (result);
  1581. sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
  1582. if (sdlznode->name == NULL) {
  1583. destroynode(sdlznode);
  1584. return (ISC_R_NOMEMORY);
  1585. }
  1586. dns_name_init(sdlznode->name, NULL);
  1587. result = dns_name_dup(newname, mctx, sdlznode->name);
  1588. if (result != ISC_R_SUCCESS) {
  1589. isc_mem_put(mctx, sdlznode->name, sizeof(dns_name_t));
  1590. destroynode(sdlznode);
  1591. return (result);
  1592. }
  1593. ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
  1594. if (allnodes->origin == NULL &&
  1595. dns_name_equal(newname, &sdlz->common.origin))
  1596. allnodes->origin = sdlznode;
  1597. }
  1598. return (dns_sdlz_putrr(sdlznode, type, ttl, data));
  1599. }
  1600. isc_result_t
  1601. dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
  1602. isc_uint32_t serial)
  1603. {
  1604. char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
  1605. int n;
  1606. REQUIRE(mname != NULL);
  1607. REQUIRE(rname != NULL);
  1608. n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u",
  1609. mname, rname, serial,
  1610. SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
  1611. SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
  1612. if (n >= (int)sizeof(str) || n < 0)
  1613. return (ISC_R_NOSPACE);
  1614. return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
  1615. }
  1616. isc_result_t
  1617. dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
  1618. void *driverarg, unsigned int flags, isc_mem_t *mctx,
  1619. dns_sdlzimplementation_t **sdlzimp)
  1620. {
  1621. dns_sdlzimplementation_t *imp;
  1622. isc_result_t result;
  1623. /*
  1624. * Performs checks to make sure data is as we expect it to be.
  1625. */
  1626. REQUIRE(drivername != NULL);
  1627. REQUIRE(methods != NULL);
  1628. REQUIRE(methods->findzone != NULL);
  1629. REQUIRE(methods->lookup != NULL);
  1630. REQUIRE(mctx != NULL);
  1631. REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
  1632. REQUIRE((flags & ~(DNS_SDLZFLAG_RELATIVEOWNER |
  1633. DNS_SDLZFLAG_RELATIVERDATA |
  1634. DNS_SDLZFLAG_THREADSAFE)) == 0);
  1635. /* Write debugging message to log */
  1636. sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername);
  1637. /*
  1638. * Allocate memory for a sdlz_implementation object. Error if
  1639. * we cannot.
  1640. */
  1641. imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
  1642. if (imp == NULL)
  1643. return (ISC_R_NOMEMORY);
  1644. /* Make sure memory region is set to all 0's */
  1645. memset(imp, 0, sizeof(dns_sdlzimplementation_t));
  1646. /* Store the data passed into this method */
  1647. imp->methods = methods;
  1648. imp->driverarg = driverarg;
  1649. imp->flags = flags;
  1650. imp->mctx = NULL;
  1651. /* attach the new sdlz_implementation object to a memory context */
  1652. isc_mem_attach(mctx, &imp->mctx);
  1653. /*
  1654. * initialize the driver lock, error if we cannot
  1655. * (used if a driver does not support multiple threads)
  1656. */
  1657. result = isc_mutex_init(&imp->driverlock);
  1658. if (result != ISC_R_SUCCESS) {
  1659. UNEXPECTED_ERROR(__FILE__, __LINE__,
  1660. "isc_mutex_init() failed: %s",
  1661. isc_result_totext(result));
  1662. goto cleanup_mctx;
  1663. }
  1664. imp->dlz_imp = NULL;
  1665. /*
  1666. * register the DLZ driver. Pass in our "extra" sdlz information as
  1667. * a driverarg. (that's why we stored the passed in driver arg in our
  1668. * sdlz_implementation structure) Also, store the dlz_implementation
  1669. * structure in our sdlz_implementation.
  1670. */
  1671. result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
  1672. &imp->dlz_imp);
  1673. /* if registration fails, cleanup and get outta here. */
  1674. if (result != ISC_R_SUCCESS)
  1675. goto cleanup_mutex;
  1676. *sdlzimp = imp;
  1677. return (ISC_R_SUCCESS);
  1678. cleanup_mutex:
  1679. /* destroy the driver lock, we don't need it anymore */
  1680. DESTROYLOCK(&imp->driverlock);
  1681. cleanup_mctx:
  1682. /*
  1683. * return the memory back to the available memory pool and
  1684. * remove it from the memory context.
  1685. */
  1686. isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
  1687. isc_mem_detach(&mctx);
  1688. return (result);
  1689. }
  1690. void
  1691. dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
  1692. dns_sdlzimplementation_t *imp;
  1693. isc_mem_t *mctx;
  1694. /* Write debugging message to log */
  1695. sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver.");
  1696. /*
  1697. * Performs checks to make sure data is as we expect it to be.
  1698. */
  1699. REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
  1700. imp = *sdlzimp;
  1701. /* Unregister the DLZ driver implementation */
  1702. dns_dlzunregister(&imp->dlz_imp);
  1703. /* destroy the driver lock, we don't need it anymore */
  1704. DESTROYLOCK(&imp->driverlock);
  1705. mctx = imp->mctx;
  1706. /*
  1707. * return the memory back to the available memory pool and
  1708. * remove it from the memory context.
  1709. */
  1710. isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
  1711. isc_mem_detach(&mctx);
  1712. *sdlzimp = NULL;
  1713. }
  1714. isc_result_t
  1715. dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
  1716. dns_name_t *name, dns_db_t **dbp)
  1717. {
  1718. isc_result_t result;
  1719. result = dns_sdlzcreateDBP(dlzdatabase->mctx,
  1720. dlzdatabase->implementation->driverarg,
  1721. dlzdatabase->dbdata, name, rdclass, dbp);
  1722. return (result);
  1723. }