PageRenderTime 34ms CodeModel.GetById 12ms app.highlight 18ms RepoModel.GetById 2ms app.codeStats 0ms

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