1 /* $NetBSD: context.c,v 1.5 2014/12/10 04:37:59 christos Exp $ */
4 * Copyright (C) 2009, 2014 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
19 /* Id: context.c,v 1.3 2009/09/02 23:48:02 tbox Exp */
25 #include <isc/magic.h>
28 #include <isc/socket.h>
30 #include <isc/thread.h>
31 #include <isc/timer.h>
34 #include <dns/client.h>
37 #include <irs/context.h>
38 #include <irs/dnsconf.h>
39 #include <irs/resconf.h>
41 #define IRS_CONTEXT_MAGIC ISC_MAGIC('I', 'R', 'S', 'c')
42 #define IRS_CONTEXT_VALID(c) ISC_MAGIC_VALID(c, IRS_CONTEXT_MAGIC)
45 /*% location of resolve.conf */
46 #define RESOLV_CONF "/etc/resolv.conf"
50 /*% location of dns.conf */
51 #define DNS_CONF "/etc/dns.conf"
54 #ifndef ISC_PLATFORM_USETHREADS
55 irs_context_t
*irs_g_context
= NULL
;
57 static isc_boolean_t thread_key_initialized
= ISC_FALSE
;
58 static isc_mutex_t thread_key_mutex
;
59 static isc_thread_key_t irs_context_key
;
60 static isc_once_t once
= ISC_ONCE_INIT
;
66 * An IRS context is a thread-specific object, and does not need to
72 isc_taskmgr_t
*taskmgr
;
74 isc_socketmgr_t
*socketmgr
;
75 isc_timermgr_t
*timermgr
;
76 dns_client_t
*dnsclient
;
77 irs_resconf_t
*resconf
;
78 irs_dnsconf_t
*dnsconf
;
82 ctxs_destroy(isc_mem_t
**mctxp
, isc_appctx_t
**actxp
,
83 isc_taskmgr_t
**taskmgrp
, isc_socketmgr_t
**socketmgrp
,
84 isc_timermgr_t
**timermgrp
)
87 isc_taskmgr_destroy(taskmgrp
);
89 if (timermgrp
!= NULL
)
90 isc_timermgr_destroy(timermgrp
);
92 if (socketmgrp
!= NULL
)
93 isc_socketmgr_destroy(socketmgrp
);
96 isc_appctx_destroy(actxp
);
99 isc_mem_destroy(mctxp
);
103 ctxs_init(isc_mem_t
**mctxp
, isc_appctx_t
**actxp
,
104 isc_taskmgr_t
**taskmgrp
, isc_socketmgr_t
**socketmgrp
,
105 isc_timermgr_t
**timermgrp
)
109 result
= isc_mem_create(0, 0, mctxp
);
110 if (result
!= ISC_R_SUCCESS
)
113 result
= isc_appctx_create(*mctxp
, actxp
);
114 if (result
!= ISC_R_SUCCESS
)
117 result
= isc_taskmgr_createinctx(*mctxp
, *actxp
, 1, 0, taskmgrp
);
118 if (result
!= ISC_R_SUCCESS
)
121 result
= isc_socketmgr_createinctx(*mctxp
, *actxp
, socketmgrp
);
122 if (result
!= ISC_R_SUCCESS
)
125 result
= isc_timermgr_createinctx(*mctxp
, *actxp
, timermgrp
);
126 if (result
!= ISC_R_SUCCESS
)
129 return (ISC_R_SUCCESS
);
132 ctxs_destroy(mctxp
, actxp
, taskmgrp
, socketmgrp
, timermgrp
);
137 #ifdef ISC_PLATFORM_USETHREADS
139 free_specific_context(void *arg
) {
140 irs_context_t
*context
= arg
;
142 irs_context_destroy(&context
);
144 isc_thread_key_setspecific(irs_context_key
, NULL
);
148 thread_key_mutex_init(void) {
149 RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex
) == ISC_R_SUCCESS
);
153 thread_key_init(void) {
156 result
= isc_once_do(&once
, thread_key_mutex_init
);
157 if (result
!= ISC_R_SUCCESS
)
160 if (!thread_key_initialized
) {
161 LOCK(&thread_key_mutex
);
163 if (!thread_key_initialized
&&
164 isc_thread_key_create(&irs_context_key
,
165 free_specific_context
) != 0) {
166 result
= ISC_R_FAILURE
;
168 thread_key_initialized
= ISC_TRUE
;
170 UNLOCK(&thread_key_mutex
);
175 #endif /* ISC_PLATFORM_USETHREADS */
178 irs_context_get(irs_context_t
**contextp
) {
179 irs_context_t
*context
;
182 REQUIRE(contextp
!= NULL
&& *contextp
== NULL
);
184 #ifndef ISC_PLATFORM_USETHREADS
185 if (irs_g_context
== NULL
) {
186 result
= irs_context_create(&irs_g_context
);
187 if (result
!= ISC_R_SUCCESS
)
191 context
= irs_g_context
;
193 result
= thread_key_init();
194 if (result
!= ISC_R_SUCCESS
)
197 context
= isc_thread_key_getspecific(irs_context_key
);
198 if (context
== NULL
) {
199 result
= irs_context_create(&context
);
200 if (result
!= ISC_R_SUCCESS
)
202 result
= isc_thread_key_setspecific(irs_context_key
, context
);
203 if (result
!= ISC_R_SUCCESS
) {
204 irs_context_destroy(&context
);
208 #endif /* ISC_PLATFORM_USETHREADS */
212 return (ISC_R_SUCCESS
);
216 irs_context_create(irs_context_t
**contextp
) {
218 irs_context_t
*context
;
219 isc_appctx_t
*actx
= NULL
;
220 isc_mem_t
*mctx
= NULL
;
221 isc_taskmgr_t
*taskmgr
= NULL
;
222 isc_socketmgr_t
*socketmgr
= NULL
;
223 isc_timermgr_t
*timermgr
= NULL
;
224 dns_client_t
*client
= NULL
;
225 isc_sockaddrlist_t
*nameservers
;
226 irs_dnsconf_dnskeylist_t
*trustedkeys
;
227 irs_dnsconf_dnskey_t
*trustedkey
;
230 result
= dns_lib_init();
231 if (result
!= ISC_R_SUCCESS
)
234 result
= ctxs_init(&mctx
, &actx
, &taskmgr
, &socketmgr
, &timermgr
);
235 if (result
!= ISC_R_SUCCESS
)
238 result
= isc_app_ctxstart(actx
);
239 if (result
!= ISC_R_SUCCESS
) {
240 ctxs_destroy(&mctx
, &actx
, &taskmgr
, &socketmgr
, &timermgr
);
244 context
= isc_mem_get(mctx
, sizeof(*context
));
245 if (context
== NULL
) {
246 ctxs_destroy(&mctx
, &actx
, &taskmgr
, &socketmgr
, &timermgr
);
247 return (ISC_R_NOMEMORY
);
250 context
->mctx
= mctx
;
251 context
->actx
= actx
;
252 context
->taskmgr
= taskmgr
;
253 context
->socketmgr
= socketmgr
;
254 context
->timermgr
= timermgr
;
255 context
->resconf
= NULL
;
256 context
->dnsconf
= NULL
;
257 context
->task
= NULL
;
258 result
= isc_task_create(taskmgr
, 0, &context
->task
);
259 if (result
!= ISC_R_SUCCESS
)
262 /* Create a DNS client object */
263 result
= dns_client_createx(mctx
, actx
, taskmgr
, socketmgr
, timermgr
,
265 if (result
!= ISC_R_SUCCESS
)
267 context
->dnsclient
= client
;
269 /* Read resolver configuration file */
270 result
= irs_resconf_load(mctx
, RESOLV_CONF
, &context
->resconf
);
271 if (result
!= ISC_R_SUCCESS
)
273 /* Set nameservers */
274 nameservers
= irs_resconf_getnameservers(context
->resconf
);
275 result
= dns_client_setservers(client
, dns_rdataclass_in
, NULL
,
277 if (result
!= ISC_R_SUCCESS
)
280 /* Read advanced DNS configuration (if any) */
281 result
= irs_dnsconf_load(mctx
, DNS_CONF
, &context
->dnsconf
);
282 if (result
!= ISC_R_SUCCESS
)
284 trustedkeys
= irs_dnsconf_gettrustedkeys(context
->dnsconf
);
285 for (trustedkey
= ISC_LIST_HEAD(*trustedkeys
);
287 trustedkey
= ISC_LIST_NEXT(trustedkey
, link
)) {
288 result
= dns_client_addtrustedkey(client
, dns_rdataclass_in
,
290 trustedkey
->keydatabuf
);
291 if (result
!= ISC_R_SUCCESS
)
295 context
->magic
= IRS_CONTEXT_MAGIC
;
298 return (ISC_R_SUCCESS
);
301 if (context
->task
!= NULL
)
302 isc_task_detach(&context
->task
);
303 if (context
->resconf
!= NULL
)
304 irs_resconf_destroy(&context
->resconf
);
305 if (context
->dnsconf
!= NULL
)
306 irs_dnsconf_destroy(&context
->dnsconf
);
308 dns_client_destroy(&client
);
309 ctxs_destroy(NULL
, &actx
, &taskmgr
, &socketmgr
, &timermgr
);
310 isc_mem_putanddetach(&mctx
, context
, sizeof(*context
));
316 irs_context_destroy(irs_context_t
**contextp
) {
317 irs_context_t
*context
;
319 REQUIRE(contextp
!= NULL
);
321 REQUIRE(IRS_CONTEXT_VALID(context
));
323 isc_task_detach(&context
->task
);
324 irs_dnsconf_destroy(&context
->dnsconf
);
325 irs_resconf_destroy(&context
->resconf
);
326 dns_client_destroy(&context
->dnsclient
);
328 ctxs_destroy(NULL
, &context
->actx
, &context
->taskmgr
,
329 &context
->socketmgr
, &context
->timermgr
);
333 isc_mem_putanddetach(&context
->mctx
, context
, sizeof(*context
));
337 #ifndef ISC_PLATFORM_USETHREADS
338 irs_g_context
= NULL
;
340 (void)isc_thread_key_setspecific(irs_context_key
, NULL
);
345 irs_context_getmctx(irs_context_t
*context
) {
346 REQUIRE(IRS_CONTEXT_VALID(context
));
348 return (context
->mctx
);
352 irs_context_getappctx(irs_context_t
*context
) {
353 REQUIRE(IRS_CONTEXT_VALID(context
));
355 return (context
->actx
);
359 irs_context_gettaskmgr(irs_context_t
*context
) {
360 REQUIRE(IRS_CONTEXT_VALID(context
));
362 return (context
->taskmgr
);
366 irs_context_gettimermgr(irs_context_t
*context
) {
367 REQUIRE(IRS_CONTEXT_VALID(context
));
369 return (context
->timermgr
);
373 irs_context_gettask(irs_context_t
*context
) {
374 REQUIRE(IRS_CONTEXT_VALID(context
));
376 return (context
->task
);
380 irs_context_getdnsclient(irs_context_t
*context
) {
381 REQUIRE(IRS_CONTEXT_VALID(context
));
383 return (context
->dnsclient
);
387 irs_context_getresconf(irs_context_t
*context
) {
388 REQUIRE(IRS_CONTEXT_VALID(context
));
390 return (context
->resconf
);
394 irs_context_getdnsconf(irs_context_t
*context
) {
395 REQUIRE(IRS_CONTEXT_VALID(context
));
397 return (context
->dnsconf
);