xref: /minix/external/bsd/dhcp/dist/omapip/isclib.c (revision bb9622b5)
1 /*	$NetBSD: isclib.c,v 1.2 2014/07/12 12:09:37 spz Exp $	*/
2 /*
3  * Copyright(c) 2009-2010,2013-2014 by Internet Systems Consortium, Inc.("ISC")
4  *
5  * Permission to use, copy, modify, and 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
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  *
17  *   Internet Systems Consortium, Inc.
18  *   950 Charter Street
19  *   Redwood City, CA 94063
20  *   <info@isc.org>
21  *   http://www.isc.org/
22  *
23  */
24 
25 #include <sys/cdefs.h>
26 __RCSID("$NetBSD: isclib.c,v 1.2 2014/07/12 12:09:37 spz Exp $");
27 
28 /*Trying to figure out what we need to define to get things to work.
29   It looks like we want/need the export library but need the fdwatchcommand
30   which may be a problem */
31 
32 #include "dhcpd.h"
33 
34 #include <sys/time.h>
35 #include <signal.h>
36 
37 dhcp_context_t dhcp_gbl_ctx;
38 int shutdown_signal = 0;
39 
40 #if defined (NSUPDATE)
41 
42 /* This routine will open up the /etc/resolv.conf file and
43  * send any nameservers it finds to the DNS client code.
44  * It may be moved to be part of the dns client code instead
45  * of being in the DHCP code
46  */
47 static isc_result_t
48 dhcp_dns_client_setservers(void)
49 {
50 	isc_result_t result;
51 	irs_resconf_t *resconf = NULL;
52 	isc_sockaddrlist_t *nameservers;
53 	isc_sockaddr_t *sa;
54 
55 	result = irs_resconf_load(dhcp_gbl_ctx.mctx, _PATH_RESOLV_CONF,
56 				  &resconf);
57 	if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
58 		log_error("irs_resconf_load failed: %d.", result);
59 		return (result);
60 	}
61 
62 	nameservers = irs_resconf_getnameservers(resconf);
63 
64 	/* Initialize port numbers */
65 	for (sa = ISC_LIST_HEAD(*nameservers);
66 	     sa != NULL;
67 	     sa = ISC_LIST_NEXT(sa, link)) {
68 		switch (sa->type.sa.sa_family) {
69 		case AF_INET:
70 			sa->type.sin.sin_port = htons(NS_DEFAULTPORT);
71 			break;
72 		case AF_INET6:
73 			sa->type.sin6.sin6_port = htons(NS_DEFAULTPORT);
74 			break;
75 		default:
76 			break;
77 		}
78 	}
79 
80 	result = dns_client_setservers(dhcp_gbl_ctx.dnsclient,
81 				       dns_rdataclass_in,
82 				       NULL, nameservers);
83 	if (result != ISC_R_SUCCESS) {
84 		log_error("dns_client_setservers failed: %d.",
85 			  result);
86 	}
87 	return (result);
88 }
89 #endif
90 
91 void
92 isclib_cleanup(void)
93 {
94 #if defined (NSUPDATE)
95 	if (dhcp_gbl_ctx.dnsclient != NULL)
96 		dns_client_destroy((dns_client_t **)&dhcp_gbl_ctx.dnsclient);
97 #endif
98 
99 	if (dhcp_gbl_ctx.task != NULL) {
100 		isc_task_shutdown(dhcp_gbl_ctx.task);
101 		isc_task_detach(&dhcp_gbl_ctx.task);
102 	}
103 
104 	if (dhcp_gbl_ctx.timermgr != NULL)
105 		isc_timermgr_destroy(&dhcp_gbl_ctx.timermgr);
106 
107 	if (dhcp_gbl_ctx.socketmgr != NULL)
108 		isc_socketmgr_destroy(&dhcp_gbl_ctx.socketmgr);
109 
110 	if (dhcp_gbl_ctx.taskmgr != NULL)
111 		isc_taskmgr_destroy(&dhcp_gbl_ctx.taskmgr);
112 
113 	if (dhcp_gbl_ctx.actx_started != ISC_FALSE) {
114 		isc_app_ctxfinish(dhcp_gbl_ctx.actx);
115 		dhcp_gbl_ctx.actx_started = ISC_FALSE;
116 	}
117 
118 	if (dhcp_gbl_ctx.actx != NULL)
119 		isc_appctx_destroy(&dhcp_gbl_ctx.actx);
120 
121 	if (dhcp_gbl_ctx.mctx != NULL)
122 		isc_mem_detach(&dhcp_gbl_ctx.mctx);
123 
124 	return;
125 }
126 
127 isc_result_t
128 dhcp_context_create(int flags,
129 		    struct in_addr  *local4,
130 		    struct in6_addr *local6) {
131 	isc_result_t result;
132 
133 	if ((flags & DHCP_CONTEXT_PRE_DB) != 0) {
134 		/*
135 		 * Set up the error messages, this isn't the right place
136 		 * for this call but it is convienent for now.
137 		 */
138 		result = dhcp_result_register();
139 		if (result != ISC_R_SUCCESS) {
140 			log_fatal("register_table() %s: %u", "failed", result);
141 		}
142 
143 		memset(&dhcp_gbl_ctx, 0, sizeof (dhcp_gbl_ctx));
144 
145 		isc_lib_register();
146 
147 		/* get the current time for use as the random seed */
148 		gettimeofday(&cur_tv, (struct timezone *)0);
149 		isc_random_seed(cur_tv.tv_sec);
150 
151 #if defined (NSUPDATE)
152 		result = dns_lib_init();
153 		if (result != ISC_R_SUCCESS)
154 			goto cleanup;
155 #else
156 		/* The dst library is inited as part of dns_lib_init, we don't
157 		 * need it if NSUPDATE is enabled */
158 		result = dst_lib_init(dhcp_gbl_ctx.mctx, NULL, 0);
159 		if (result != ISC_R_SUCCESS)
160 			goto cleanup;
161 
162 #endif
163 		result = isc_mem_create(0, 0, &dhcp_gbl_ctx.mctx);
164 		if (result != ISC_R_SUCCESS)
165 			goto cleanup;
166 
167 		result = isc_appctx_create(dhcp_gbl_ctx.mctx,
168 					   &dhcp_gbl_ctx.actx);
169 		if (result != ISC_R_SUCCESS)
170 			goto cleanup;
171 
172 		result = isc_app_ctxstart(dhcp_gbl_ctx.actx);
173 		if (result != ISC_R_SUCCESS)
174 			return (result);
175 		dhcp_gbl_ctx.actx_started = ISC_TRUE;
176 
177 		result = isc_taskmgr_createinctx(dhcp_gbl_ctx.mctx,
178 						 dhcp_gbl_ctx.actx,
179 						 1, 0,
180 						 &dhcp_gbl_ctx.taskmgr);
181 		if (result != ISC_R_SUCCESS)
182 			goto cleanup;
183 
184 		result = isc_socketmgr_createinctx(dhcp_gbl_ctx.mctx,
185 						   dhcp_gbl_ctx.actx,
186 						   &dhcp_gbl_ctx.socketmgr);
187 		if (result != ISC_R_SUCCESS)
188 			goto cleanup;
189 
190 		result = isc_timermgr_createinctx(dhcp_gbl_ctx.mctx,
191 						  dhcp_gbl_ctx.actx,
192 						  &dhcp_gbl_ctx.timermgr);
193 		if (result != ISC_R_SUCCESS)
194 			goto cleanup;
195 
196 		result = isc_task_create(dhcp_gbl_ctx.taskmgr, 0, &dhcp_gbl_ctx.task);
197 		if (result != ISC_R_SUCCESS)
198 			goto cleanup;
199 	}
200 
201 #if defined (NSUPDATE)
202 	if ((flags & DHCP_CONTEXT_POST_DB) != 0) {
203 		isc_sockaddr_t localaddr4, *localaddr4_ptr = NULL;
204 		isc_sockaddr_t localaddr6, *localaddr6_ptr = NULL;
205 		if (local4 != NULL) {
206 			isc_sockaddr_fromin(&localaddr4, local4, 0);
207 			localaddr4_ptr = &localaddr4;
208 		}
209 		if (local6 != NULL) {
210 			isc_sockaddr_fromin6(&localaddr6, local6, 0);
211 			localaddr6_ptr = &localaddr6;
212 		}
213 
214 		result = dns_client_createx2(dhcp_gbl_ctx.mctx,
215 					     dhcp_gbl_ctx.actx,
216 					     dhcp_gbl_ctx.taskmgr,
217 					     dhcp_gbl_ctx.socketmgr,
218 					     dhcp_gbl_ctx.timermgr,
219 					     0,
220 					     &dhcp_gbl_ctx.dnsclient,
221 					     localaddr4_ptr,
222 					     localaddr6_ptr);
223 		if (result != ISC_R_SUCCESS)
224 			goto cleanup;
225 
226 		result = dhcp_dns_client_setservers();
227 		if (result != ISC_R_SUCCESS)
228 			goto cleanup;
229 	}
230 #endif
231 
232 	return(ISC_R_SUCCESS);
233 
234  cleanup:
235 	/*
236 	 * Currently we don't try and cleanup, just return an error
237 	 * expecting that our caller will log the error and exit.
238 	 */
239 
240 	return(result);
241 }
242 
243 /*
244  * Convert a string name into the proper structure for the isc routines
245  *
246  * Previously we allowed names without a trailing '.' however the current
247  * dns and dst code requires the names to end in a period.  If the
248  * name doesn't have a trailing period add one as part of creating
249  * the dns name.
250  */
251 
252 isc_result_t
253 dhcp_isc_name(unsigned char   *namestr,
254 	      dns_fixedname_t *namefix,
255 	      dns_name_t     **name)
256 {
257 	size_t namelen;
258 	isc_buffer_t b;
259 	isc_result_t result;
260 
261 	namelen = strlen((char *)namestr);
262 	isc_buffer_init(&b, namestr, namelen);
263 	isc_buffer_add(&b, namelen);
264 	dns_fixedname_init(namefix);
265 	*name = dns_fixedname_name(namefix);
266 	result = dns_name_fromtext(*name, &b, dns_rootname, 0, NULL);
267 	isc_buffer_invalidate(&b);
268 	return(result);
269 }
270 
271 isc_result_t
272 isclib_make_dst_key(char          *inname,
273 		    char          *algorithm,
274 		    unsigned char *secret,
275 		    int            length,
276 		    dst_key_t    **dstkey)
277 {
278 	isc_result_t result;
279 	dns_name_t *name;
280 	dns_fixedname_t name0;
281 	isc_buffer_t b;
282 
283 	isc_buffer_init(&b, secret, length);
284 	isc_buffer_add(&b, length);
285 
286 	/* We only support HMAC_MD5 currently */
287 	if (strcasecmp(algorithm, DHCP_HMAC_MD5_NAME) != 0) {
288 		return(DHCP_R_INVALIDARG);
289 	}
290 
291 	result = dhcp_isc_name((unsigned char *)inname, &name0, &name);
292 	if (result != ISC_R_SUCCESS) {
293 		return(result);
294 	}
295 
296 	return(dst_key_frombuffer(name, DST_ALG_HMACMD5, DNS_KEYOWNER_ENTITY,
297 				  DNS_KEYPROTO_DNSSEC, dns_rdataclass_in,
298 				  &b, dhcp_gbl_ctx.mctx, dstkey));
299 }
300 
301 /**
302  * signal handler that initiates server shutdown
303  *
304  * @param signal signal code that we received
305  */
306 void dhcp_signal_handler(int signal) {
307 	isc_appctx_t *ctx = dhcp_gbl_ctx.actx;
308 	int prev = shutdown_signal;
309 
310 	if (prev != 0) {
311 		/* Already in shutdown. */
312 		return;
313 	}
314 	/* Possible race but does it matter? */
315 	shutdown_signal = signal;
316 
317 	/* Use reload (aka suspend) for easier dispatch() reenter. */
318 	if (ctx && ctx->methods && ctx->methods->ctxsuspend) {
319 		(void) isc_app_ctxsuspend(ctx);
320 	}
321 }
322