xref: /netbsd/external/mpl/bind/dist/lib/irs/context.c (revision c0b5d9fb)
1 /*	$NetBSD: context.c,v 1.7 2022/09/23 12:15:32 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * SPDX-License-Identifier: MPL-2.0
7  *
8  * This Source Code Form is subject to the terms of the Mozilla Public
9  * License, v. 2.0.  If a copy of the MPL was not distributed with this
10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11  *
12  * See the COPYRIGHT file distributed with this work for additional
13  * information regarding copyright ownership.
14  */
15 
16 #include <stdbool.h>
17 
18 #include <isc/app.h>
19 #include <isc/lib.h>
20 #include <isc/magic.h>
21 #include <isc/managers.h>
22 #include <isc/mem.h>
23 #include <isc/netmgr.h>
24 #include <isc/once.h>
25 #include <isc/socket.h>
26 #include <isc/task.h>
27 #include <isc/thread.h>
28 #include <isc/timer.h>
29 #include <isc/util.h>
30 
31 #include <dns/client.h>
32 #include <dns/lib.h>
33 
34 #include <irs/context.h>
35 #include <irs/dnsconf.h>
36 #include <irs/resconf.h>
37 
38 #define IRS_CONTEXT_MAGIC    ISC_MAGIC('I', 'R', 'S', 'c')
39 #define IRS_CONTEXT_VALID(c) ISC_MAGIC_VALID(c, IRS_CONTEXT_MAGIC)
40 
41 #ifndef RESOLV_CONF
42 /*% location of resolve.conf */
43 #define RESOLV_CONF "/etc/resolv.conf"
44 #endif /* ifndef RESOLV_CONF */
45 
46 #ifndef DNS_CONF
47 /*% location of dns.conf */
48 #define DNS_CONF "/etc/dns.conf"
49 #endif /* ifndef DNS_CONF */
50 
51 ISC_THREAD_LOCAL irs_context_t *irs_context = NULL;
52 
53 struct irs_context {
54 	/*
55 	 * An IRS context is a thread-specific object, and does not need to
56 	 * be locked.
57 	 */
58 	unsigned int magic;
59 	isc_mem_t *mctx;
60 	isc_appctx_t *actx;
61 	isc_nm_t *netmgr;
62 	isc_taskmgr_t *taskmgr;
63 	isc_task_t *task;
64 	isc_socketmgr_t *socketmgr;
65 	isc_timermgr_t *timermgr;
66 	dns_client_t *dnsclient;
67 	irs_resconf_t *resconf;
68 	irs_dnsconf_t *dnsconf;
69 };
70 
71 static void
ctxs_destroy(isc_mem_t ** mctxp,isc_appctx_t ** actxp,isc_nm_t ** netmgrp,isc_taskmgr_t ** taskmgrp,isc_socketmgr_t ** socketmgrp,isc_timermgr_t ** timermgrp)72 ctxs_destroy(isc_mem_t **mctxp, isc_appctx_t **actxp, isc_nm_t **netmgrp,
73 	     isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp,
74 	     isc_timermgr_t **timermgrp) {
75 	isc_managers_destroy(netmgrp == NULL ? NULL : netmgrp,
76 			     taskmgrp == NULL ? NULL : taskmgrp);
77 
78 	if (timermgrp != NULL) {
79 		isc_timermgr_destroy(timermgrp);
80 	}
81 
82 	if (socketmgrp != NULL) {
83 		isc_socketmgr_destroy(socketmgrp);
84 	}
85 
86 	if (actxp != NULL) {
87 		isc_appctx_destroy(actxp);
88 	}
89 
90 	if (mctxp != NULL) {
91 		isc_mem_destroy(mctxp);
92 	}
93 }
94 
95 static isc_result_t
ctxs_init(isc_mem_t ** mctxp,isc_appctx_t ** actxp,isc_nm_t ** netmgrp,isc_taskmgr_t ** taskmgrp,isc_socketmgr_t ** socketmgrp,isc_timermgr_t ** timermgrp)96 ctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp, isc_nm_t **netmgrp,
97 	  isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp,
98 	  isc_timermgr_t **timermgrp) {
99 	isc_result_t result;
100 
101 	isc_mem_create(mctxp);
102 
103 	result = isc_appctx_create(*mctxp, actxp);
104 	if (result != ISC_R_SUCCESS) {
105 		goto fail;
106 	}
107 
108 	result = isc_managers_create(*mctxp, 1, 0, netmgrp, taskmgrp);
109 	if (result != ISC_R_SUCCESS) {
110 		goto fail;
111 	}
112 
113 	result = isc_socketmgr_create(*mctxp, socketmgrp);
114 	if (result != ISC_R_SUCCESS) {
115 		goto fail;
116 	}
117 
118 	result = isc_timermgr_create(*mctxp, timermgrp);
119 	if (result != ISC_R_SUCCESS) {
120 		goto fail;
121 	}
122 
123 	return (ISC_R_SUCCESS);
124 
125 fail:
126 	ctxs_destroy(mctxp, actxp, netmgrp, taskmgrp, socketmgrp, timermgrp);
127 
128 	return (result);
129 }
130 
131 isc_result_t
irs_context_get(irs_context_t ** contextp)132 irs_context_get(irs_context_t **contextp) {
133 	isc_result_t result;
134 
135 	REQUIRE(contextp != NULL && *contextp == NULL);
136 
137 	if (irs_context == NULL) {
138 		result = irs_context_create(&irs_context);
139 		if (result != ISC_R_SUCCESS) {
140 			return (result);
141 		}
142 	}
143 
144 	*contextp = irs_context;
145 
146 	return (ISC_R_SUCCESS);
147 }
148 
149 isc_result_t
irs_context_create(irs_context_t ** contextp)150 irs_context_create(irs_context_t **contextp) {
151 	isc_result_t result;
152 	irs_context_t *context;
153 	isc_appctx_t *actx = NULL;
154 	isc_mem_t *mctx = NULL;
155 	isc_nm_t *netmgr = NULL;
156 	isc_taskmgr_t *taskmgr = NULL;
157 	isc_socketmgr_t *socketmgr = NULL;
158 	isc_timermgr_t *timermgr = NULL;
159 	dns_client_t *client = NULL;
160 	isc_sockaddrlist_t *nameservers;
161 	irs_dnsconf_dnskeylist_t *trustedkeys;
162 	irs_dnsconf_dnskey_t *trustedkey;
163 
164 	isc_lib_register();
165 	result = dns_lib_init();
166 	if (result != ISC_R_SUCCESS) {
167 		return (result);
168 	}
169 
170 	result = ctxs_init(&mctx, &actx, &netmgr, &taskmgr, &socketmgr,
171 			   &timermgr);
172 	if (result != ISC_R_SUCCESS) {
173 		return (result);
174 	}
175 
176 	result = isc_app_ctxstart(actx);
177 	if (result != ISC_R_SUCCESS) {
178 		ctxs_destroy(&mctx, &actx, &netmgr, &taskmgr, &socketmgr,
179 			     &timermgr);
180 		return (result);
181 	}
182 
183 	context = isc_mem_get(mctx, sizeof(*context));
184 
185 	context->mctx = mctx;
186 	context->actx = actx;
187 	context->taskmgr = taskmgr;
188 	context->socketmgr = socketmgr;
189 	context->timermgr = timermgr;
190 	context->resconf = NULL;
191 	context->dnsconf = NULL;
192 	context->task = NULL;
193 	result = isc_task_create(taskmgr, 0, &context->task);
194 	if (result != ISC_R_SUCCESS) {
195 		goto fail;
196 	}
197 
198 	/* Create a DNS client object */
199 	result = dns_client_create(mctx, actx, taskmgr, socketmgr, timermgr, 0,
200 				   &client, NULL, NULL);
201 	if (result != ISC_R_SUCCESS) {
202 		goto fail;
203 	}
204 	context->dnsclient = client;
205 
206 	/* Read resolver configuration file */
207 	result = irs_resconf_load(mctx, RESOLV_CONF, &context->resconf);
208 	if (result != ISC_R_SUCCESS) {
209 		goto fail;
210 	}
211 	/* Set nameservers */
212 	nameservers = irs_resconf_getnameservers(context->resconf);
213 	result = dns_client_setservers(client, dns_rdataclass_in, NULL,
214 				       nameservers);
215 	if (result != ISC_R_SUCCESS) {
216 		goto fail;
217 	}
218 
219 	/* Read advanced DNS configuration (if any) */
220 	result = irs_dnsconf_load(mctx, DNS_CONF, &context->dnsconf);
221 	if (result != ISC_R_SUCCESS) {
222 		goto fail;
223 	}
224 	trustedkeys = irs_dnsconf_gettrustedkeys(context->dnsconf);
225 	for (trustedkey = ISC_LIST_HEAD(*trustedkeys); trustedkey != NULL;
226 	     trustedkey = ISC_LIST_NEXT(trustedkey, link))
227 	{
228 		result = dns_client_addtrustedkey(
229 			client, dns_rdataclass_in, dns_rdatatype_dnskey,
230 			trustedkey->keyname, trustedkey->keydatabuf);
231 		if (result != ISC_R_SUCCESS) {
232 			goto fail;
233 		}
234 	}
235 
236 	context->magic = IRS_CONTEXT_MAGIC;
237 	*contextp = context;
238 
239 	return (ISC_R_SUCCESS);
240 
241 fail:
242 	if (context->task != NULL) {
243 		isc_task_detach(&context->task);
244 	}
245 	if (context->resconf != NULL) {
246 		irs_resconf_destroy(&context->resconf);
247 	}
248 	if (context->dnsconf != NULL) {
249 		irs_dnsconf_destroy(&context->dnsconf);
250 	}
251 	if (client != NULL) {
252 		dns_client_destroy(&client);
253 	}
254 	ctxs_destroy(NULL, &actx, &netmgr, &taskmgr, &socketmgr, &timermgr);
255 	isc_mem_putanddetach(&mctx, context, sizeof(*context));
256 
257 	return (result);
258 }
259 
260 void
irs_context_destroy(irs_context_t ** contextp)261 irs_context_destroy(irs_context_t **contextp) {
262 	irs_context_t *context;
263 
264 	REQUIRE(contextp != NULL);
265 	context = *contextp;
266 	REQUIRE(IRS_CONTEXT_VALID(context));
267 	*contextp = irs_context = NULL;
268 
269 	isc_task_detach(&context->task);
270 	irs_dnsconf_destroy(&context->dnsconf);
271 	irs_resconf_destroy(&context->resconf);
272 	dns_client_destroy(&context->dnsclient);
273 
274 	ctxs_destroy(NULL, &context->actx, &context->netmgr, &context->taskmgr,
275 		     &context->socketmgr, &context->timermgr);
276 
277 	context->magic = 0;
278 
279 	isc_mem_putanddetach(&context->mctx, context, sizeof(*context));
280 }
281 
282 isc_mem_t *
irs_context_getmctx(irs_context_t * context)283 irs_context_getmctx(irs_context_t *context) {
284 	REQUIRE(IRS_CONTEXT_VALID(context));
285 
286 	return (context->mctx);
287 }
288 
289 isc_appctx_t *
irs_context_getappctx(irs_context_t * context)290 irs_context_getappctx(irs_context_t *context) {
291 	REQUIRE(IRS_CONTEXT_VALID(context));
292 
293 	return (context->actx);
294 }
295 
296 isc_taskmgr_t *
irs_context_gettaskmgr(irs_context_t * context)297 irs_context_gettaskmgr(irs_context_t *context) {
298 	REQUIRE(IRS_CONTEXT_VALID(context));
299 
300 	return (context->taskmgr);
301 }
302 
303 isc_timermgr_t *
irs_context_gettimermgr(irs_context_t * context)304 irs_context_gettimermgr(irs_context_t *context) {
305 	REQUIRE(IRS_CONTEXT_VALID(context));
306 
307 	return (context->timermgr);
308 }
309 
310 isc_task_t *
irs_context_gettask(irs_context_t * context)311 irs_context_gettask(irs_context_t *context) {
312 	REQUIRE(IRS_CONTEXT_VALID(context));
313 
314 	return (context->task);
315 }
316 
317 dns_client_t *
irs_context_getdnsclient(irs_context_t * context)318 irs_context_getdnsclient(irs_context_t *context) {
319 	REQUIRE(IRS_CONTEXT_VALID(context));
320 
321 	return (context->dnsclient);
322 }
323 
324 irs_resconf_t *
irs_context_getresconf(irs_context_t * context)325 irs_context_getresconf(irs_context_t *context) {
326 	REQUIRE(IRS_CONTEXT_VALID(context));
327 
328 	return (context->resconf);
329 }
330 
331 irs_dnsconf_t *
irs_context_getdnsconf(irs_context_t * context)332 irs_context_getdnsconf(irs_context_t *context) {
333 	REQUIRE(IRS_CONTEXT_VALID(context));
334 
335 	return (context->dnsconf);
336 }
337