/contrib/bind9/lib/irs/context.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 396 lines · 291 code · 79 blank · 26 comment · 72 complexity · 9d261fe3413f853bcd57983d3c561391 MD5 · raw file

  1. /*
  2. * Copyright (C) 2009 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: context.c,v 1.3 2009/09/02 23:48:02 tbox Exp $ */
  17. #include <config.h>
  18. #include <isc/app.h>
  19. #include <isc/lib.h>
  20. #include <isc/magic.h>
  21. #include <isc/mem.h>
  22. #include <isc/once.h>
  23. #include <isc/socket.h>
  24. #include <isc/task.h>
  25. #include <isc/thread.h>
  26. #include <isc/timer.h>
  27. #include <isc/util.h>
  28. #include <dns/client.h>
  29. #include <dns/lib.h>
  30. #include <irs/context.h>
  31. #include <irs/dnsconf.h>
  32. #include <irs/resconf.h>
  33. #define IRS_CONTEXT_MAGIC ISC_MAGIC('I', 'R', 'S', 'c')
  34. #define IRS_CONTEXT_VALID(c) ISC_MAGIC_VALID(c, IRS_CONTEXT_MAGIC)
  35. #ifndef RESOLV_CONF
  36. /*% location of resolve.conf */
  37. #define RESOLV_CONF "/etc/resolv.conf"
  38. #endif
  39. #ifndef DNS_CONF
  40. /*% location of dns.conf */
  41. #define DNS_CONF "/etc/dns.conf"
  42. #endif
  43. #ifndef ISC_PLATFORM_USETHREADS
  44. irs_context_t *irs_g_context = NULL;
  45. #else
  46. static isc_boolean_t thread_key_initialized = ISC_FALSE;
  47. static isc_mutex_t thread_key_mutex;
  48. static isc_thread_key_t irs_context_key;
  49. static isc_once_t once = ISC_ONCE_INIT;
  50. #endif
  51. struct irs_context {
  52. /*
  53. * An IRS context is a thread-specific object, and does not need to
  54. * be locked.
  55. */
  56. unsigned int magic;
  57. isc_mem_t *mctx;
  58. isc_appctx_t *actx;
  59. isc_taskmgr_t *taskmgr;
  60. isc_task_t *task;
  61. isc_socketmgr_t *socketmgr;
  62. isc_timermgr_t *timermgr;
  63. dns_client_t *dnsclient;
  64. irs_resconf_t *resconf;
  65. irs_dnsconf_t *dnsconf;
  66. };
  67. static void
  68. ctxs_destroy(isc_mem_t **mctxp, isc_appctx_t **actxp,
  69. isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp,
  70. isc_timermgr_t **timermgrp)
  71. {
  72. if (taskmgrp != NULL)
  73. isc_taskmgr_destroy(taskmgrp);
  74. if (timermgrp != NULL)
  75. isc_timermgr_destroy(timermgrp);
  76. if (socketmgrp != NULL)
  77. isc_socketmgr_destroy(socketmgrp);
  78. if (actxp != NULL)
  79. isc_appctx_destroy(actxp);
  80. if (mctxp != NULL)
  81. isc_mem_destroy(mctxp);
  82. }
  83. static isc_result_t
  84. ctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp,
  85. isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp,
  86. isc_timermgr_t **timermgrp)
  87. {
  88. isc_result_t result;
  89. result = isc_mem_create(0, 0, mctxp);
  90. if (result != ISC_R_SUCCESS)
  91. goto fail;
  92. result = isc_appctx_create(*mctxp, actxp);
  93. if (result != ISC_R_SUCCESS)
  94. goto fail;
  95. result = isc_taskmgr_createinctx(*mctxp, *actxp, 1, 0, taskmgrp);
  96. if (result != ISC_R_SUCCESS)
  97. goto fail;
  98. result = isc_socketmgr_createinctx(*mctxp, *actxp, socketmgrp);
  99. if (result != ISC_R_SUCCESS)
  100. goto fail;
  101. result = isc_timermgr_createinctx(*mctxp, *actxp, timermgrp);
  102. if (result != ISC_R_SUCCESS)
  103. goto fail;
  104. return (ISC_R_SUCCESS);
  105. fail:
  106. ctxs_destroy(mctxp, actxp, taskmgrp, socketmgrp, timermgrp);
  107. return (result);
  108. }
  109. #ifdef ISC_PLATFORM_USETHREADS
  110. static void
  111. free_specific_context(void *arg) {
  112. irs_context_t *context = arg;
  113. irs_context_destroy(&context);
  114. isc_thread_key_setspecific(irs_context_key, NULL);
  115. }
  116. static void
  117. thread_key_mutex_init(void) {
  118. RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
  119. }
  120. static isc_result_t
  121. thread_key_init() {
  122. isc_result_t result;
  123. result = isc_once_do(&once, thread_key_mutex_init);
  124. if (result != ISC_R_SUCCESS)
  125. return (result);
  126. if (!thread_key_initialized) {
  127. LOCK(&thread_key_mutex);
  128. if (!thread_key_initialized &&
  129. isc_thread_key_create(&irs_context_key,
  130. free_specific_context) != 0) {
  131. result = ISC_R_FAILURE;
  132. } else
  133. thread_key_initialized = ISC_TRUE;
  134. UNLOCK(&thread_key_mutex);
  135. }
  136. return (result);
  137. }
  138. #endif /* ISC_PLATFORM_USETHREADS */
  139. isc_result_t
  140. irs_context_get(irs_context_t **contextp) {
  141. irs_context_t *context;
  142. isc_result_t result;
  143. REQUIRE(contextp != NULL && *contextp == NULL);
  144. #ifndef ISC_PLATFORM_USETHREADS
  145. if (irs_g_context == NULL) {
  146. result = irs_context_create(&irs_g_context);
  147. if (result != ISC_R_SUCCESS)
  148. return (result);
  149. }
  150. context = irs_g_context;
  151. #else
  152. result = thread_key_init();
  153. if (result != ISC_R_SUCCESS)
  154. return (result);
  155. context = isc_thread_key_getspecific(irs_context_key);
  156. if (context == NULL) {
  157. result = irs_context_create(&context);
  158. if (result != ISC_R_SUCCESS)
  159. return (result);
  160. result = isc_thread_key_setspecific(irs_context_key, context);
  161. if (result != ISC_R_SUCCESS) {
  162. irs_context_destroy(&context);
  163. return (result);
  164. }
  165. }
  166. #endif /* ISC_PLATFORM_USETHREADS */
  167. *contextp = context;
  168. return (ISC_R_SUCCESS);
  169. }
  170. isc_result_t
  171. irs_context_create(irs_context_t **contextp) {
  172. isc_result_t result;
  173. irs_context_t *context;
  174. isc_appctx_t *actx = NULL;
  175. isc_mem_t *mctx = NULL;
  176. isc_taskmgr_t *taskmgr = NULL;
  177. isc_socketmgr_t *socketmgr = NULL;
  178. isc_timermgr_t *timermgr = NULL;
  179. dns_client_t *client = NULL;
  180. isc_sockaddrlist_t *nameservers;
  181. irs_dnsconf_dnskeylist_t *trustedkeys;
  182. irs_dnsconf_dnskey_t *trustedkey;
  183. isc_lib_register();
  184. result = dns_lib_init();
  185. if (result != ISC_R_SUCCESS)
  186. return (result);
  187. result = ctxs_init(&mctx, &actx, &taskmgr, &socketmgr, &timermgr);
  188. if (result != ISC_R_SUCCESS)
  189. return (result);
  190. result = isc_app_ctxstart(actx);
  191. if (result != ISC_R_SUCCESS) {
  192. ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr);
  193. return (result);
  194. }
  195. context = isc_mem_get(mctx, sizeof(*context));
  196. if (context == NULL) {
  197. ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr);
  198. return (ISC_R_NOMEMORY);
  199. }
  200. context->mctx = mctx;
  201. context->actx = actx;
  202. context->taskmgr = taskmgr;
  203. context->socketmgr = socketmgr;
  204. context->timermgr = timermgr;
  205. context->resconf = NULL;
  206. context->dnsconf = NULL;
  207. context->task = NULL;
  208. result = isc_task_create(taskmgr, 0, &context->task);
  209. if (result != ISC_R_SUCCESS)
  210. goto fail;
  211. /* Create a DNS client object */
  212. result = dns_client_createx(mctx, actx, taskmgr, socketmgr, timermgr,
  213. 0, &client);
  214. if (result != ISC_R_SUCCESS)
  215. goto fail;
  216. context->dnsclient = client;
  217. /* Read resolver configuration file */
  218. result = irs_resconf_load(mctx, RESOLV_CONF, &context->resconf);
  219. if (result != ISC_R_SUCCESS)
  220. goto fail;
  221. /* Set nameservers */
  222. nameservers = irs_resconf_getnameservers(context->resconf);
  223. result = dns_client_setservers(client, dns_rdataclass_in, NULL,
  224. nameservers);
  225. if (result != ISC_R_SUCCESS)
  226. goto fail;
  227. /* Read advanced DNS configuration (if any) */
  228. result = irs_dnsconf_load(mctx, DNS_CONF, &context->dnsconf);
  229. if (result != ISC_R_SUCCESS)
  230. goto fail;
  231. trustedkeys = irs_dnsconf_gettrustedkeys(context->dnsconf);
  232. for (trustedkey = ISC_LIST_HEAD(*trustedkeys);
  233. trustedkey != NULL;
  234. trustedkey = ISC_LIST_NEXT(trustedkey, link)) {
  235. result = dns_client_addtrustedkey(client, dns_rdataclass_in,
  236. trustedkey->keyname,
  237. trustedkey->keydatabuf);
  238. if (result != ISC_R_SUCCESS)
  239. goto fail;
  240. }
  241. context->magic = IRS_CONTEXT_MAGIC;
  242. *contextp = context;
  243. return (ISC_R_SUCCESS);
  244. fail:
  245. if (context->task != NULL)
  246. isc_task_detach(&context->task);
  247. if (context->resconf != NULL)
  248. irs_resconf_destroy(&context->resconf);
  249. if (context->dnsconf != NULL)
  250. irs_dnsconf_destroy(&context->dnsconf);
  251. if (client != NULL)
  252. dns_client_destroy(&client);
  253. ctxs_destroy(NULL, &actx, &taskmgr, &socketmgr, &timermgr);
  254. isc_mem_putanddetach(&mctx, context, sizeof(*context));
  255. return (result);
  256. }
  257. void
  258. irs_context_destroy(irs_context_t **contextp) {
  259. irs_context_t *context;
  260. REQUIRE(contextp != NULL);
  261. context = *contextp;
  262. REQUIRE(IRS_CONTEXT_VALID(context));
  263. isc_task_detach(&context->task);
  264. irs_dnsconf_destroy(&context->dnsconf);
  265. irs_resconf_destroy(&context->resconf);
  266. dns_client_destroy(&context->dnsclient);
  267. ctxs_destroy(NULL, &context->actx, &context->taskmgr,
  268. &context->socketmgr, &context->timermgr);
  269. context->magic = 0;
  270. isc_mem_putanddetach(&context->mctx, context, sizeof(*context));
  271. *contextp = NULL;
  272. #ifndef ISC_PLATFORM_USETHREADS
  273. irs_g_context = NULL;
  274. #else
  275. (void)isc_thread_key_setspecific(irs_context_key, NULL);
  276. #endif
  277. }
  278. isc_mem_t *
  279. irs_context_getmctx(irs_context_t *context) {
  280. REQUIRE(IRS_CONTEXT_VALID(context));
  281. return (context->mctx);
  282. }
  283. isc_appctx_t *
  284. irs_context_getappctx(irs_context_t *context) {
  285. REQUIRE(IRS_CONTEXT_VALID(context));
  286. return (context->actx);
  287. }
  288. isc_taskmgr_t *
  289. irs_context_gettaskmgr(irs_context_t *context) {
  290. REQUIRE(IRS_CONTEXT_VALID(context));
  291. return (context->taskmgr);
  292. }
  293. isc_timermgr_t *
  294. irs_context_gettimermgr(irs_context_t *context) {
  295. REQUIRE(IRS_CONTEXT_VALID(context));
  296. return (context->timermgr);
  297. }
  298. isc_task_t *
  299. irs_context_gettask(irs_context_t *context) {
  300. REQUIRE(IRS_CONTEXT_VALID(context));
  301. return (context->task);
  302. }
  303. dns_client_t *
  304. irs_context_getdnsclient(irs_context_t *context) {
  305. REQUIRE(IRS_CONTEXT_VALID(context));
  306. return (context->dnsclient);
  307. }
  308. irs_resconf_t *
  309. irs_context_getresconf(irs_context_t *context) {
  310. REQUIRE(IRS_CONTEXT_VALID(context));
  311. return (context->resconf);
  312. }
  313. irs_dnsconf_t *
  314. irs_context_getdnsconf(irs_context_t *context) {
  315. REQUIRE(IRS_CONTEXT_VALID(context));
  316. return (context->dnsconf);
  317. }