1 /*
2  * unbound.c - unbound validating resolver public API implementation
3  *
4  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5  *
6  * This software is open source.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * Neither the name of the NLNET LABS nor the names of its contributors may
20  * be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 /**
37  * \file
38  *
39  * This file contains functions to resolve DNS queries and
40  * validate the answers. Synchronously and asynchronously.
41  *
42  */
43 
44 /* include the public api first, it should be able to stand alone */
45 #include "libunbound/unbound.h"
46 #include "libunbound/unbound-event.h"
47 #include "config.h"
48 #include <ctype.h>
49 #include "libunbound/context.h"
50 #include "libunbound/libworker.h"
51 #include "util/locks.h"
52 #include "util/config_file.h"
53 #include "util/alloc.h"
54 #include "util/module.h"
55 #include "util/regional.h"
56 #include "util/log.h"
57 #include "util/random.h"
58 #include "util/net_help.h"
59 #include "util/tube.h"
60 #include "util/ub_event.h"
61 #include "services/modstack.h"
62 #include "services/localzone.h"
63 #include "services/cache/infra.h"
64 #include "services/cache/rrset.h"
65 #include "sldns/sbuffer.h"
66 #ifdef HAVE_PTHREAD
67 #include <signal.h>
68 #endif
69 #ifdef HAVE_SYS_WAIT_H
70 #include <sys/wait.h>
71 #endif
72 #ifdef HAVE_TIME_H
73 #include <time.h>
74 #endif
75 
76 #if defined(UB_ON_WINDOWS) && defined (HAVE_WINDOWS_H)
77 #include <windows.h>
78 #include <iphlpapi.h>
79 #endif /* UB_ON_WINDOWS */
80 
81 /** create context functionality, but no pipes */
82 static struct ub_ctx* ub_ctx_create_nopipe(void)
83 {
84 	struct ub_ctx* ctx;
85 	unsigned int seed;
86 #ifdef USE_WINSOCK
87 	int r;
88 	WSADATA wsa_data;
89 #endif
90 
91 	log_init(NULL, 0, NULL); /* logs to stderr */
92 	log_ident_set("libunbound");
93 #ifdef USE_WINSOCK
94 	if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) {
95 		log_err("could not init winsock. WSAStartup: %s",
96 			wsa_strerror(r));
97 		return NULL;
98 	}
99 #endif
100 	verbosity = 0; /* errors only */
101 	checklock_start();
102 	ctx = (struct ub_ctx*)calloc(1, sizeof(*ctx));
103 	if(!ctx) {
104 		errno = ENOMEM;
105 		return NULL;
106 	}
107 	alloc_init(&ctx->superalloc, NULL, 0);
108 	seed = (unsigned int)time(NULL) ^ (unsigned int)getpid();
109 	if(!(ctx->seed_rnd = ub_initstate(seed, NULL))) {
110 		seed = 0;
111 		ub_randfree(ctx->seed_rnd);
112 		free(ctx);
113 		errno = ENOMEM;
114 		return NULL;
115 	}
116 	seed = 0;
117 	lock_basic_init(&ctx->qqpipe_lock);
118 	lock_basic_init(&ctx->rrpipe_lock);
119 	lock_basic_init(&ctx->cfglock);
120 	ctx->env = (struct module_env*)calloc(1, sizeof(*ctx->env));
121 	if(!ctx->env) {
122 		ub_randfree(ctx->seed_rnd);
123 		free(ctx);
124 		errno = ENOMEM;
125 		return NULL;
126 	}
127 	ctx->env->cfg = config_create_forlib();
128 	if(!ctx->env->cfg) {
129 		free(ctx->env);
130 		ub_randfree(ctx->seed_rnd);
131 		free(ctx);
132 		errno = ENOMEM;
133 		return NULL;
134 	}
135 	/* init edns_known_options */
136 	if(!edns_known_options_init(ctx->env)) {
137 		config_delete(ctx->env->cfg);
138 		free(ctx->env);
139 		ub_randfree(ctx->seed_rnd);
140 		free(ctx);
141 		errno = ENOMEM;
142 		return NULL;
143 	}
144 	ctx->env->alloc = &ctx->superalloc;
145 	ctx->env->worker = NULL;
146 	ctx->env->need_to_validate = 0;
147 	modstack_init(&ctx->mods);
148 	rbtree_init(&ctx->queries, &context_query_cmp);
149 	return ctx;
150 }
151 
152 struct ub_ctx*
153 ub_ctx_create(void)
154 {
155 	struct ub_ctx* ctx = ub_ctx_create_nopipe();
156 	if(!ctx)
157 		return NULL;
158 	if((ctx->qq_pipe = tube_create()) == NULL) {
159 		int e = errno;
160 		ub_randfree(ctx->seed_rnd);
161 		config_delete(ctx->env->cfg);
162 		modstack_desetup(&ctx->mods, ctx->env);
163 		edns_known_options_delete(ctx->env);
164 		free(ctx->env);
165 		free(ctx);
166 		errno = e;
167 		return NULL;
168 	}
169 	if((ctx->rr_pipe = tube_create()) == NULL) {
170 		int e = errno;
171 		tube_delete(ctx->qq_pipe);
172 		ub_randfree(ctx->seed_rnd);
173 		config_delete(ctx->env->cfg);
174 		modstack_desetup(&ctx->mods, ctx->env);
175 		edns_known_options_delete(ctx->env);
176 		free(ctx->env);
177 		free(ctx);
178 		errno = e;
179 		return NULL;
180 	}
181 	return ctx;
182 }
183 
184 struct ub_ctx*
185 ub_ctx_create_ub_event(struct ub_event_base* ueb)
186 {
187 	struct ub_ctx* ctx = ub_ctx_create_nopipe();
188 	if(!ctx)
189 		return NULL;
190 	/* no pipes, but we have the locks to make sure everything works */
191 	ctx->created_bg = 0;
192 	ctx->dothread = 1; /* the processing is in the same process,
193 		makes ub_cancel and ub_ctx_delete do the right thing */
194 	ctx->event_base = ueb;
195 	return ctx;
196 }
197 
198 struct ub_ctx*
199 ub_ctx_create_event(struct event_base* eb)
200 {
201 	struct ub_ctx* ctx = ub_ctx_create_nopipe();
202 	if(!ctx)
203 		return NULL;
204 	/* no pipes, but we have the locks to make sure everything works */
205 	ctx->created_bg = 0;
206 	ctx->dothread = 1; /* the processing is in the same process,
207 		makes ub_cancel and ub_ctx_delete do the right thing */
208 	ctx->event_base = ub_libevent_event_base(eb);
209 	if (!ctx->event_base) {
210 		ub_ctx_delete(ctx);
211 		return NULL;
212 	}
213 	return ctx;
214 }
215 
216 /** delete q */
217 static void
218 delq(rbnode_type* n, void* ATTR_UNUSED(arg))
219 {
220 	struct ctx_query* q = (struct ctx_query*)n;
221 	context_query_delete(q);
222 }
223 
224 /** stop the bg thread */
225 static void ub_stop_bg(struct ub_ctx* ctx)
226 {
227 	/* stop the bg thread */
228 	lock_basic_lock(&ctx->cfglock);
229 	if(ctx->created_bg) {
230 		uint8_t* msg;
231 		uint32_t len;
232 		uint32_t cmd = UB_LIBCMD_QUIT;
233 		lock_basic_unlock(&ctx->cfglock);
234 		lock_basic_lock(&ctx->qqpipe_lock);
235 		(void)tube_write_msg(ctx->qq_pipe, (uint8_t*)&cmd,
236 			(uint32_t)sizeof(cmd), 0);
237 		lock_basic_unlock(&ctx->qqpipe_lock);
238 		lock_basic_lock(&ctx->rrpipe_lock);
239 		while(tube_read_msg(ctx->rr_pipe, &msg, &len, 0)) {
240 			/* discard all results except a quit confirm */
241 			if(context_serial_getcmd(msg, len) == UB_LIBCMD_QUIT) {
242 				free(msg);
243 				break;
244 			}
245 			free(msg);
246 		}
247 		lock_basic_unlock(&ctx->rrpipe_lock);
248 
249 		/* if bg worker is a thread, wait for it to exit, so that all
250 	 	 * resources are really gone. */
251 		lock_basic_lock(&ctx->cfglock);
252 		if(ctx->dothread) {
253 			lock_basic_unlock(&ctx->cfglock);
254 			ub_thread_join(ctx->bg_tid);
255 		} else {
256 			lock_basic_unlock(&ctx->cfglock);
257 #ifndef UB_ON_WINDOWS
258 			if(waitpid(ctx->bg_pid, NULL, 0) == -1) {
259 				if(verbosity > 2)
260 					log_err("waitpid: %s", strerror(errno));
261 			}
262 #endif
263 		}
264 	}
265 	else {
266 		lock_basic_unlock(&ctx->cfglock);
267 	}
268 }
269 
270 void
271 ub_ctx_delete(struct ub_ctx* ctx)
272 {
273 	struct alloc_cache* a, *na;
274 	int do_stop = 1;
275 	if(!ctx) return;
276 
277 	/* see if bg thread is created and if threads have been killed */
278 	/* no locks, because those may be held by terminated threads */
279 	/* for processes the read pipe is closed and we see that on read */
280 #ifdef HAVE_PTHREAD
281 	if(ctx->created_bg && ctx->dothread) {
282 		if(pthread_kill(ctx->bg_tid, 0) == ESRCH) {
283 			/* thread has been killed */
284 			do_stop = 0;
285 		}
286 	}
287 #endif /* HAVE_PTHREAD */
288 	if(do_stop)
289 		ub_stop_bg(ctx);
290 	libworker_delete_event(ctx->event_worker);
291 
292 	modstack_desetup(&ctx->mods, ctx->env);
293 	a = ctx->alloc_list;
294 	while(a) {
295 		na = a->super;
296 		a->super = &ctx->superalloc;
297 		alloc_clear(a);
298 		free(a);
299 		a = na;
300 	}
301 	local_zones_delete(ctx->local_zones);
302 	lock_basic_destroy(&ctx->qqpipe_lock);
303 	lock_basic_destroy(&ctx->rrpipe_lock);
304 	lock_basic_destroy(&ctx->cfglock);
305 	tube_delete(ctx->qq_pipe);
306 	tube_delete(ctx->rr_pipe);
307 	if(ctx->env) {
308 		slabhash_delete(ctx->env->msg_cache);
309 		rrset_cache_delete(ctx->env->rrset_cache);
310 		infra_delete(ctx->env->infra_cache);
311 		config_delete(ctx->env->cfg);
312 		edns_known_options_delete(ctx->env);
313 		free(ctx->env);
314 	}
315 	ub_randfree(ctx->seed_rnd);
316 	alloc_clear(&ctx->superalloc);
317 	traverse_postorder(&ctx->queries, delq, NULL);
318 	free(ctx);
319 #ifdef USE_WINSOCK
320 	WSACleanup();
321 #endif
322 }
323 
324 int
325 ub_ctx_set_option(struct ub_ctx* ctx, const char* opt, const char* val)
326 {
327 	lock_basic_lock(&ctx->cfglock);
328 	if(ctx->finalized) {
329 		lock_basic_unlock(&ctx->cfglock);
330 		return UB_AFTERFINAL;
331 	}
332 	if(!config_set_option(ctx->env->cfg, opt, val)) {
333 		lock_basic_unlock(&ctx->cfglock);
334 		return UB_SYNTAX;
335 	}
336 	lock_basic_unlock(&ctx->cfglock);
337 	return UB_NOERROR;
338 }
339 
340 int
341 ub_ctx_get_option(struct ub_ctx* ctx, const char* opt, char** str)
342 {
343 	int r;
344 	lock_basic_lock(&ctx->cfglock);
345 	r = config_get_option_collate(ctx->env->cfg, opt, str);
346 	lock_basic_unlock(&ctx->cfglock);
347 	if(r == 0) r = UB_NOERROR;
348 	else if(r == 1) r = UB_SYNTAX;
349 	else if(r == 2) r = UB_NOMEM;
350 	return r;
351 }
352 
353 int
354 ub_ctx_config(struct ub_ctx* ctx, const char* fname)
355 {
356 	lock_basic_lock(&ctx->cfglock);
357 	if(ctx->finalized) {
358 		lock_basic_unlock(&ctx->cfglock);
359 		return UB_AFTERFINAL;
360 	}
361 	if(!config_read(ctx->env->cfg, fname, NULL)) {
362 		lock_basic_unlock(&ctx->cfglock);
363 		return UB_SYNTAX;
364 	}
365 	lock_basic_unlock(&ctx->cfglock);
366 	return UB_NOERROR;
367 }
368 
369 int
370 ub_ctx_add_ta(struct ub_ctx* ctx, const char* ta)
371 {
372 	char* dup = strdup(ta);
373 	if(!dup) return UB_NOMEM;
374 	lock_basic_lock(&ctx->cfglock);
375 	if(ctx->finalized) {
376 		lock_basic_unlock(&ctx->cfglock);
377 		free(dup);
378 		return UB_AFTERFINAL;
379 	}
380 	if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_list, dup)) {
381 		lock_basic_unlock(&ctx->cfglock);
382 		free(dup);
383 		return UB_NOMEM;
384 	}
385 	lock_basic_unlock(&ctx->cfglock);
386 	return UB_NOERROR;
387 }
388 
389 int
390 ub_ctx_add_ta_file(struct ub_ctx* ctx, const char* fname)
391 {
392 	char* dup = strdup(fname);
393 	if(!dup) return UB_NOMEM;
394 	lock_basic_lock(&ctx->cfglock);
395 	if(ctx->finalized) {
396 		lock_basic_unlock(&ctx->cfglock);
397 		free(dup);
398 		return UB_AFTERFINAL;
399 	}
400 	if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_file_list, dup)) {
401 		lock_basic_unlock(&ctx->cfglock);
402 		free(dup);
403 		return UB_NOMEM;
404 	}
405 	lock_basic_unlock(&ctx->cfglock);
406 	return UB_NOERROR;
407 }
408 
409 int ub_ctx_add_ta_autr(struct ub_ctx* ctx, const char* fname)
410 {
411 	char* dup = strdup(fname);
412 	if(!dup) return UB_NOMEM;
413 	lock_basic_lock(&ctx->cfglock);
414 	if(ctx->finalized) {
415 		lock_basic_unlock(&ctx->cfglock);
416 		free(dup);
417 		return UB_AFTERFINAL;
418 	}
419 	if(!cfg_strlist_insert(&ctx->env->cfg->auto_trust_anchor_file_list,
420 		dup)) {
421 		lock_basic_unlock(&ctx->cfglock);
422 		free(dup);
423 		return UB_NOMEM;
424 	}
425 	lock_basic_unlock(&ctx->cfglock);
426 	return UB_NOERROR;
427 }
428 
429 int
430 ub_ctx_trustedkeys(struct ub_ctx* ctx, const char* fname)
431 {
432 	char* dup = strdup(fname);
433 	if(!dup) return UB_NOMEM;
434 	lock_basic_lock(&ctx->cfglock);
435 	if(ctx->finalized) {
436 		lock_basic_unlock(&ctx->cfglock);
437 		free(dup);
438 		return UB_AFTERFINAL;
439 	}
440 	if(!cfg_strlist_insert(&ctx->env->cfg->trusted_keys_file_list, dup)) {
441 		lock_basic_unlock(&ctx->cfglock);
442 		free(dup);
443 		return UB_NOMEM;
444 	}
445 	lock_basic_unlock(&ctx->cfglock);
446 	return UB_NOERROR;
447 }
448 
449 int
450 ub_ctx_debuglevel(struct ub_ctx* ctx, int d)
451 {
452 	lock_basic_lock(&ctx->cfglock);
453 	verbosity = d;
454 	ctx->env->cfg->verbosity = d;
455 	lock_basic_unlock(&ctx->cfglock);
456 	return UB_NOERROR;
457 }
458 
459 int ub_ctx_debugout(struct ub_ctx* ctx, void* out)
460 {
461 	lock_basic_lock(&ctx->cfglock);
462 	log_file((FILE*)out);
463 	ctx->logfile_override = 1;
464 	ctx->log_out = out;
465 	lock_basic_unlock(&ctx->cfglock);
466 	return UB_NOERROR;
467 }
468 
469 int
470 ub_ctx_async(struct ub_ctx* ctx, int dothread)
471 {
472 #ifdef THREADS_DISABLED
473 	if(dothread) /* cannot do threading */
474 		return UB_NOERROR;
475 #endif
476 	lock_basic_lock(&ctx->cfglock);
477 	if(ctx->finalized) {
478 		lock_basic_unlock(&ctx->cfglock);
479 		return UB_AFTERFINAL;
480 	}
481 	ctx->dothread = dothread;
482 	lock_basic_unlock(&ctx->cfglock);
483 	return UB_NOERROR;
484 }
485 
486 int
487 ub_poll(struct ub_ctx* ctx)
488 {
489 	/* no need to hold lock while testing for readability. */
490 	return tube_poll(ctx->rr_pipe);
491 }
492 
493 int
494 ub_fd(struct ub_ctx* ctx)
495 {
496 	return tube_read_fd(ctx->rr_pipe);
497 }
498 
499 /** process answer from bg worker */
500 static int
501 process_answer_detail(struct ub_ctx* ctx, uint8_t* msg, uint32_t len,
502 	ub_callback_type* cb, void** cbarg, int* err,
503 	struct ub_result** res)
504 {
505 	struct ctx_query* q;
506 	if(context_serial_getcmd(msg, len) != UB_LIBCMD_ANSWER) {
507 		log_err("error: bad data from bg worker %d",
508 			(int)context_serial_getcmd(msg, len));
509 		return 0;
510 	}
511 
512 	lock_basic_lock(&ctx->cfglock);
513 	q = context_deserialize_answer(ctx, msg, len, err);
514 	if(!q) {
515 		lock_basic_unlock(&ctx->cfglock);
516 		/* probably simply the lookup that failed, i.e.
517 		 * response returned before cancel was sent out, so noerror */
518 		return 1;
519 	}
520 	log_assert(q->async);
521 
522 	/* grab cb while locked */
523 	if(q->cancelled) {
524 		*cb = NULL;
525 		*cbarg = NULL;
526 	} else {
527 		*cb = q->cb;
528 		*cbarg = q->cb_arg;
529 	}
530 	if(*err) {
531 		*res = NULL;
532 		ub_resolve_free(q->res);
533 	} else {
534 		/* parse the message, extract rcode, fill result */
535 		sldns_buffer* buf = sldns_buffer_new(q->msg_len);
536 		struct regional* region = regional_create();
537 		*res = q->res;
538 		(*res)->rcode = LDNS_RCODE_SERVFAIL;
539 		if(region && buf) {
540 			sldns_buffer_clear(buf);
541 			sldns_buffer_write(buf, q->msg, q->msg_len);
542 			sldns_buffer_flip(buf);
543 			libworker_enter_result(*res, buf, region,
544 				q->msg_security);
545 		}
546 		(*res)->answer_packet = q->msg;
547 		(*res)->answer_len = (int)q->msg_len;
548 		q->msg = NULL;
549 		sldns_buffer_free(buf);
550 		regional_destroy(region);
551 	}
552 	q->res = NULL;
553 	/* delete the q from list */
554 	(void)rbtree_delete(&ctx->queries, q->node.key);
555 	ctx->num_async--;
556 	context_query_delete(q);
557 	lock_basic_unlock(&ctx->cfglock);
558 
559 	if(*cb) return 2;
560 	ub_resolve_free(*res);
561 	return 1;
562 }
563 
564 /** process answer from bg worker */
565 static int
566 process_answer(struct ub_ctx* ctx, uint8_t* msg, uint32_t len)
567 {
568 	int err;
569 	ub_callback_type cb;
570 	void* cbarg;
571 	struct ub_result* res;
572 	int r;
573 
574 	r = process_answer_detail(ctx, msg, len, &cb, &cbarg, &err, &res);
575 
576 	/* no locks held while calling callback, so that library is
577 	 * re-entrant. */
578 	if(r == 2)
579 		(*cb)(cbarg, err, res);
580 
581 	return r;
582 }
583 
584 int
585 ub_process(struct ub_ctx* ctx)
586 {
587 	int r;
588 	uint8_t* msg;
589 	uint32_t len;
590 	while(1) {
591 		msg = NULL;
592 		lock_basic_lock(&ctx->rrpipe_lock);
593 		r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1);
594 		lock_basic_unlock(&ctx->rrpipe_lock);
595 		if(r == 0)
596 			return UB_PIPE;
597 		else if(r == -1)
598 			break;
599 		if(!process_answer(ctx, msg, len)) {
600 			free(msg);
601 			return UB_PIPE;
602 		}
603 		free(msg);
604 	}
605 	return UB_NOERROR;
606 }
607 
608 int
609 ub_wait(struct ub_ctx* ctx)
610 {
611 	int err;
612 	ub_callback_type cb;
613 	void* cbarg;
614 	struct ub_result* res;
615 	int r;
616 	uint8_t* msg;
617 	uint32_t len;
618 	/* this is basically the same loop as _process(), but with changes.
619 	 * holds the rrpipe lock and waits with tube_wait */
620 	while(1) {
621 		lock_basic_lock(&ctx->rrpipe_lock);
622 		lock_basic_lock(&ctx->cfglock);
623 		if(ctx->num_async == 0) {
624 			lock_basic_unlock(&ctx->cfglock);
625 			lock_basic_unlock(&ctx->rrpipe_lock);
626 			break;
627 		}
628 		lock_basic_unlock(&ctx->cfglock);
629 
630 		/* keep rrpipe locked, while
631 		 * 	o waiting for pipe readable
632 		 * 	o parsing message
633 		 * 	o possibly decrementing num_async
634 		 * do callback without lock
635 		 */
636 		r = tube_wait(ctx->rr_pipe);
637 		if(r) {
638 			r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1);
639 			if(r == 0) {
640 				lock_basic_unlock(&ctx->rrpipe_lock);
641 				return UB_PIPE;
642 			}
643 			if(r == -1) {
644 				lock_basic_unlock(&ctx->rrpipe_lock);
645 				continue;
646 			}
647 			r = process_answer_detail(ctx, msg, len,
648 				&cb, &cbarg, &err, &res);
649 			lock_basic_unlock(&ctx->rrpipe_lock);
650 			free(msg);
651 			if(r == 0)
652 				return UB_PIPE;
653 			if(r == 2)
654 				(*cb)(cbarg, err, res);
655 		} else {
656 			lock_basic_unlock(&ctx->rrpipe_lock);
657 		}
658 	}
659 	return UB_NOERROR;
660 }
661 
662 int
663 ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype,
664 	int rrclass, struct ub_result** result)
665 {
666 	struct ctx_query* q;
667 	int r;
668 	*result = NULL;
669 
670 	lock_basic_lock(&ctx->cfglock);
671 	if(!ctx->finalized) {
672 		r = context_finalize(ctx);
673 		if(r) {
674 			lock_basic_unlock(&ctx->cfglock);
675 			return r;
676 		}
677 	}
678 	/* create new ctx_query and attempt to add to the list */
679 	lock_basic_unlock(&ctx->cfglock);
680 	q = context_new(ctx, name, rrtype, rrclass, NULL, NULL);
681 	if(!q)
682 		return UB_NOMEM;
683 	/* become a resolver thread for a bit */
684 
685 	r = libworker_fg(ctx, q);
686 	if(r) {
687 		lock_basic_lock(&ctx->cfglock);
688 		(void)rbtree_delete(&ctx->queries, q->node.key);
689 		context_query_delete(q);
690 		lock_basic_unlock(&ctx->cfglock);
691 		return r;
692 	}
693 	q->res->answer_packet = q->msg;
694 	q->res->answer_len = (int)q->msg_len;
695 	q->msg = NULL;
696 	*result = q->res;
697 	q->res = NULL;
698 
699 	lock_basic_lock(&ctx->cfglock);
700 	(void)rbtree_delete(&ctx->queries, q->node.key);
701 	context_query_delete(q);
702 	lock_basic_unlock(&ctx->cfglock);
703 	return UB_NOERROR;
704 }
705 
706 int
707 ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
708 	int rrclass, void* mydata, ub_event_callback_type callback,
709 	int* async_id)
710 {
711 	struct ctx_query* q;
712 	int r;
713 
714 	if(async_id)
715 		*async_id = 0;
716 	lock_basic_lock(&ctx->cfglock);
717 	if(!ctx->finalized) {
718 		int r = context_finalize(ctx);
719 		if(r) {
720 			lock_basic_unlock(&ctx->cfglock);
721 			return r;
722 		}
723 	}
724 	lock_basic_unlock(&ctx->cfglock);
725 	if(!ctx->event_worker) {
726 		ctx->event_worker = libworker_create_event(ctx,
727 			ctx->event_base);
728 		if(!ctx->event_worker) {
729 			return UB_INITFAIL;
730 		}
731 	}
732 
733 	/* set time in case answer comes from cache */
734 	ub_comm_base_now(ctx->event_worker->base);
735 
736 	/* create new ctx_query and attempt to add to the list */
737 	q = context_new(ctx, name, rrtype, rrclass, (ub_callback_type)callback,
738 		mydata);
739 	if(!q)
740 		return UB_NOMEM;
741 
742 	/* attach to mesh */
743 	if((r=libworker_attach_mesh(ctx, q, async_id)) != 0)
744 		return r;
745 	return UB_NOERROR;
746 }
747 
748 
749 int
750 ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype,
751 	int rrclass, void* mydata, ub_callback_type callback, int* async_id)
752 {
753 	struct ctx_query* q;
754 	uint8_t* msg = NULL;
755 	uint32_t len = 0;
756 
757 	if(async_id)
758 		*async_id = 0;
759 	lock_basic_lock(&ctx->cfglock);
760 	if(!ctx->finalized) {
761 		int r = context_finalize(ctx);
762 		if(r) {
763 			lock_basic_unlock(&ctx->cfglock);
764 			return r;
765 		}
766 	}
767 	if(!ctx->created_bg) {
768 		int r;
769 		ctx->created_bg = 1;
770 		lock_basic_unlock(&ctx->cfglock);
771 		r = libworker_bg(ctx);
772 		if(r) {
773 			lock_basic_lock(&ctx->cfglock);
774 			ctx->created_bg = 0;
775 			lock_basic_unlock(&ctx->cfglock);
776 			return r;
777 		}
778 	} else {
779 		lock_basic_unlock(&ctx->cfglock);
780 	}
781 
782 	/* create new ctx_query and attempt to add to the list */
783 	q = context_new(ctx, name, rrtype, rrclass, callback, mydata);
784 	if(!q)
785 		return UB_NOMEM;
786 
787 	/* write over pipe to background worker */
788 	lock_basic_lock(&ctx->cfglock);
789 	msg = context_serialize_new_query(q, &len);
790 	if(!msg) {
791 		(void)rbtree_delete(&ctx->queries, q->node.key);
792 		ctx->num_async--;
793 		context_query_delete(q);
794 		lock_basic_unlock(&ctx->cfglock);
795 		return UB_NOMEM;
796 	}
797 	if(async_id)
798 		*async_id = q->querynum;
799 	lock_basic_unlock(&ctx->cfglock);
800 
801 	lock_basic_lock(&ctx->qqpipe_lock);
802 	if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) {
803 		lock_basic_unlock(&ctx->qqpipe_lock);
804 		free(msg);
805 		return UB_PIPE;
806 	}
807 	lock_basic_unlock(&ctx->qqpipe_lock);
808 	free(msg);
809 	return UB_NOERROR;
810 }
811 
812 int
813 ub_cancel(struct ub_ctx* ctx, int async_id)
814 {
815 	struct ctx_query* q;
816 	uint8_t* msg = NULL;
817 	uint32_t len = 0;
818 	lock_basic_lock(&ctx->cfglock);
819 	q = (struct ctx_query*)rbtree_search(&ctx->queries, &async_id);
820 	if(!q || !q->async) {
821 		/* it is not there, so nothing to do */
822 		lock_basic_unlock(&ctx->cfglock);
823 		return UB_NOID;
824 	}
825 	log_assert(q->async);
826 	q->cancelled = 1;
827 
828 	/* delete it */
829 	if(!ctx->dothread) { /* if forked */
830 		(void)rbtree_delete(&ctx->queries, q->node.key);
831 		ctx->num_async--;
832 		msg = context_serialize_cancel(q, &len);
833 		context_query_delete(q);
834 		lock_basic_unlock(&ctx->cfglock);
835 		if(!msg) {
836 			return UB_NOMEM;
837 		}
838 		/* send cancel to background worker */
839 		lock_basic_lock(&ctx->qqpipe_lock);
840 		if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) {
841 			lock_basic_unlock(&ctx->qqpipe_lock);
842 			free(msg);
843 			return UB_PIPE;
844 		}
845 		lock_basic_unlock(&ctx->qqpipe_lock);
846 		free(msg);
847 	} else {
848 		lock_basic_unlock(&ctx->cfglock);
849 	}
850 	return UB_NOERROR;
851 }
852 
853 void
854 ub_resolve_free(struct ub_result* result)
855 {
856 	char** p;
857 	if(!result) return;
858 	free(result->qname);
859 	if(result->canonname != result->qname)
860 		free(result->canonname);
861 	if(result->data)
862 		for(p = result->data; *p; p++)
863 			free(*p);
864 	free(result->data);
865 	free(result->len);
866 	free(result->answer_packet);
867 	free(result->why_bogus);
868 	free(result);
869 }
870 
871 const char*
872 ub_strerror(int err)
873 {
874 	switch(err) {
875 		case UB_NOERROR: return "no error";
876 		case UB_SOCKET: return "socket io error";
877 		case UB_NOMEM: return "out of memory";
878 		case UB_SYNTAX: return "syntax error";
879 		case UB_SERVFAIL: return "server failure";
880 		case UB_FORKFAIL: return "could not fork";
881 		case UB_INITFAIL: return "initialization failure";
882 		case UB_AFTERFINAL: return "setting change after finalize";
883 		case UB_PIPE: return "error in pipe communication with async";
884 		case UB_READFILE: return "error reading file";
885 		case UB_NOID: return "error async_id does not exist";
886 		default: return "unknown error";
887 	}
888 }
889 
890 int
891 ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr)
892 {
893 	struct sockaddr_storage storage;
894 	socklen_t stlen;
895 	struct config_stub* s;
896 	char* dupl;
897 	lock_basic_lock(&ctx->cfglock);
898 	if(ctx->finalized) {
899 		lock_basic_unlock(&ctx->cfglock);
900 		errno=EINVAL;
901 		return UB_AFTERFINAL;
902 	}
903 	if(!addr) {
904 		/* disable fwd mode - the root stub should be first. */
905 		if(ctx->env->cfg->forwards &&
906 			strcmp(ctx->env->cfg->forwards->name, ".") == 0) {
907 			s = ctx->env->cfg->forwards;
908 			ctx->env->cfg->forwards = s->next;
909 			s->next = NULL;
910 			config_delstubs(s);
911 		}
912 		lock_basic_unlock(&ctx->cfglock);
913 		return UB_NOERROR;
914 	}
915 	lock_basic_unlock(&ctx->cfglock);
916 
917 	/* check syntax for addr */
918 	if(!extstrtoaddr(addr, &storage, &stlen)) {
919 		errno=EINVAL;
920 		return UB_SYNTAX;
921 	}
922 
923 	/* it parses, add root stub in front of list */
924 	lock_basic_lock(&ctx->cfglock);
925 	if(!ctx->env->cfg->forwards ||
926 		strcmp(ctx->env->cfg->forwards->name, ".") != 0) {
927 		s = calloc(1, sizeof(*s));
928 		if(!s) {
929 			lock_basic_unlock(&ctx->cfglock);
930 			errno=ENOMEM;
931 			return UB_NOMEM;
932 		}
933 		s->name = strdup(".");
934 		if(!s->name) {
935 			free(s);
936 			lock_basic_unlock(&ctx->cfglock);
937 			errno=ENOMEM;
938 			return UB_NOMEM;
939 		}
940 		s->next = ctx->env->cfg->forwards;
941 		ctx->env->cfg->forwards = s;
942 	} else {
943 		log_assert(ctx->env->cfg->forwards);
944 		s = ctx->env->cfg->forwards;
945 	}
946 	dupl = strdup(addr);
947 	if(!dupl) {
948 		lock_basic_unlock(&ctx->cfglock);
949 		errno=ENOMEM;
950 		return UB_NOMEM;
951 	}
952 	if(!cfg_strlist_insert(&s->addrs, dupl)) {
953 		free(dupl);
954 		lock_basic_unlock(&ctx->cfglock);
955 		errno=ENOMEM;
956 		return UB_NOMEM;
957 	}
958 	lock_basic_unlock(&ctx->cfglock);
959 	return UB_NOERROR;
960 }
961 
962 int ub_ctx_set_stub(struct ub_ctx* ctx, const char* zone, const char* addr,
963 	int isprime)
964 {
965 	char* a;
966 	struct config_stub **prev, *elem;
967 
968 	/* check syntax for zone name */
969 	if(zone) {
970 		uint8_t* nm;
971 		int nmlabs;
972 		size_t nmlen;
973 		if(!parse_dname(zone, &nm, &nmlen, &nmlabs)) {
974 			errno=EINVAL;
975 			return UB_SYNTAX;
976 		}
977 		free(nm);
978 	} else {
979 		zone = ".";
980 	}
981 
982 	/* check syntax for addr (if not NULL) */
983 	if(addr) {
984 		struct sockaddr_storage storage;
985 		socklen_t stlen;
986 		if(!extstrtoaddr(addr, &storage, &stlen)) {
987 			errno=EINVAL;
988 			return UB_SYNTAX;
989 		}
990 	}
991 
992 	lock_basic_lock(&ctx->cfglock);
993 	if(ctx->finalized) {
994 		lock_basic_unlock(&ctx->cfglock);
995 		errno=EINVAL;
996 		return UB_AFTERFINAL;
997 	}
998 
999 	/* arguments all right, now find or add the stub */
1000 	prev = &ctx->env->cfg->stubs;
1001 	elem = cfg_stub_find(&prev, zone);
1002 	if(!elem && !addr) {
1003 		/* not found and we want to delete, nothing to do */
1004 		lock_basic_unlock(&ctx->cfglock);
1005 		return UB_NOERROR;
1006 	} else if(elem && !addr) {
1007 		/* found, and we want to delete */
1008 		*prev = elem->next;
1009 		config_delstub(elem);
1010 		lock_basic_unlock(&ctx->cfglock);
1011 		return UB_NOERROR;
1012 	} else if(!elem) {
1013 		/* not found, create the stub entry */
1014 		elem=(struct config_stub*)calloc(1, sizeof(struct config_stub));
1015 		if(elem) elem->name = strdup(zone);
1016 		if(!elem || !elem->name) {
1017 			free(elem);
1018 			lock_basic_unlock(&ctx->cfglock);
1019 			errno = ENOMEM;
1020 			return UB_NOMEM;
1021 		}
1022 		elem->next = ctx->env->cfg->stubs;
1023 		ctx->env->cfg->stubs = elem;
1024 	}
1025 
1026 	/* add the address to the list and set settings */
1027 	elem->isprime = isprime;
1028 	a = strdup(addr);
1029 	if(!a) {
1030 		lock_basic_unlock(&ctx->cfglock);
1031 		errno = ENOMEM;
1032 		return UB_NOMEM;
1033 	}
1034 	if(!cfg_strlist_insert(&elem->addrs, a)) {
1035 		lock_basic_unlock(&ctx->cfglock);
1036 		free(a);
1037 		errno = ENOMEM;
1038 		return UB_NOMEM;
1039 	}
1040 	lock_basic_unlock(&ctx->cfglock);
1041 	return UB_NOERROR;
1042 }
1043 
1044 int
1045 ub_ctx_resolvconf(struct ub_ctx* ctx, const char* fname)
1046 {
1047 	FILE* in;
1048 	int numserv = 0;
1049 	char buf[1024];
1050 	char* parse, *addr;
1051 	int r;
1052 
1053 	if(fname == NULL) {
1054 #if !defined(UB_ON_WINDOWS) || !defined(HAVE_WINDOWS_H)
1055 		fname = "/etc/resolv.conf";
1056 #else
1057 		FIXED_INFO *info;
1058 		ULONG buflen = sizeof(*info);
1059 		IP_ADDR_STRING *ptr;
1060 
1061 		info = (FIXED_INFO *) malloc(sizeof (FIXED_INFO));
1062 		if (info == NULL)
1063 			return UB_READFILE;
1064 
1065 		if (GetNetworkParams(info, &buflen) == ERROR_BUFFER_OVERFLOW) {
1066 			free(info);
1067 			info = (FIXED_INFO *) malloc(buflen);
1068 			if (info == NULL)
1069 				return UB_READFILE;
1070 		}
1071 
1072 		if (GetNetworkParams(info, &buflen) == NO_ERROR) {
1073 			int retval=0;
1074 			ptr = &(info->DnsServerList);
1075 			while (ptr) {
1076 				numserv++;
1077 				if((retval=ub_ctx_set_fwd(ctx,
1078 					ptr->IpAddress.String))!=0) {
1079 					free(info);
1080 					return retval;
1081 				}
1082 				ptr = ptr->Next;
1083 			}
1084 			free(info);
1085 			if (numserv==0)
1086 				return UB_READFILE;
1087 			return UB_NOERROR;
1088 		}
1089 		free(info);
1090 		return UB_READFILE;
1091 #endif /* WINDOWS */
1092 	}
1093 	in = fopen(fname, "r");
1094 	if(!in) {
1095 		/* error in errno! perror(fname) */
1096 		return UB_READFILE;
1097 	}
1098 	while(fgets(buf, (int)sizeof(buf), in)) {
1099 		buf[sizeof(buf)-1] = 0;
1100 		parse=buf;
1101 		while(*parse == ' ' || *parse == '\t')
1102 			parse++;
1103 		if(strncmp(parse, "nameserver", 10) == 0) {
1104 			numserv++;
1105 			parse += 10; /* skip 'nameserver' */
1106 			/* skip whitespace */
1107 			while(*parse == ' ' || *parse == '\t')
1108 				parse++;
1109 			addr = parse;
1110 			/* skip [0-9a-fA-F.:]*, i.e. IP4 and IP6 address */
1111 			while(isxdigit((unsigned char)*parse) || *parse=='.' || *parse==':')
1112 				parse++;
1113 			/* terminate after the address, remove newline */
1114 			*parse = 0;
1115 
1116 			if((r = ub_ctx_set_fwd(ctx, addr)) != UB_NOERROR) {
1117 				fclose(in);
1118 				return r;
1119 			}
1120 		}
1121 	}
1122 	fclose(in);
1123 	if(numserv == 0) {
1124 		/* from resolv.conf(5) if none given, use localhost */
1125 		return ub_ctx_set_fwd(ctx, "127.0.0.1");
1126 	}
1127 	return UB_NOERROR;
1128 }
1129 
1130 int
1131 ub_ctx_hosts(struct ub_ctx* ctx, const char* fname)
1132 {
1133 	FILE* in;
1134 	char buf[1024], ldata[1024];
1135 	char* parse, *addr, *name, *ins;
1136 	lock_basic_lock(&ctx->cfglock);
1137 	if(ctx->finalized) {
1138 		lock_basic_unlock(&ctx->cfglock);
1139 		errno=EINVAL;
1140 		return UB_AFTERFINAL;
1141 	}
1142 	lock_basic_unlock(&ctx->cfglock);
1143 	if(fname == NULL) {
1144 #if defined(UB_ON_WINDOWS) && defined(HAVE_WINDOWS_H)
1145 		/*
1146 		 * If this is Windows NT/XP/2K it's in
1147 		 * %WINDIR%\system32\drivers\etc\hosts.
1148 		 * If this is Windows 95/98/Me it's in %WINDIR%\hosts.
1149 		 */
1150 		name = getenv("WINDIR");
1151 		if (name != NULL) {
1152 			int retval=0;
1153 			snprintf(buf, sizeof(buf), "%s%s", name,
1154 				"\\system32\\drivers\\etc\\hosts");
1155 			if((retval=ub_ctx_hosts(ctx, buf)) !=0 ) {
1156 				snprintf(buf, sizeof(buf), "%s%s", name,
1157 					"\\hosts");
1158 				retval=ub_ctx_hosts(ctx, buf);
1159 			}
1160 			return retval;
1161 		}
1162 		return UB_READFILE;
1163 #else
1164 		fname = "/etc/hosts";
1165 #endif /* WIN32 */
1166 	}
1167 	in = fopen(fname, "r");
1168 	if(!in) {
1169 		/* error in errno! perror(fname) */
1170 		return UB_READFILE;
1171 	}
1172 	while(fgets(buf, (int)sizeof(buf), in)) {
1173 		buf[sizeof(buf)-1] = 0;
1174 		parse=buf;
1175 		while(*parse == ' ' || *parse == '\t')
1176 			parse++;
1177 		if(*parse == '#')
1178 			continue; /* skip comment */
1179 		/* format: <addr> spaces <name> spaces <name> ... */
1180 		addr = parse;
1181 		/* skip addr */
1182 		while(isxdigit((unsigned char)*parse) || *parse == '.' || *parse == ':')
1183 			parse++;
1184 		if(*parse == '\r')
1185 			parse++;
1186 		if(*parse == '\n' || *parse == 0)
1187 			continue;
1188 		if(*parse == '%')
1189 			continue; /* ignore macOSX fe80::1%lo0 localhost */
1190 		if(*parse != ' ' && *parse != '\t') {
1191 			/* must have whitespace after address */
1192 			fclose(in);
1193 			errno=EINVAL;
1194 			return UB_SYNTAX;
1195 		}
1196 		*parse++ = 0; /* end delimiter for addr ... */
1197 		/* go to names and add them */
1198 		while(*parse) {
1199 			while(*parse == ' ' || *parse == '\t' || *parse=='\n'
1200 				|| *parse=='\r')
1201 				parse++;
1202 			if(*parse == 0 || *parse == '#')
1203 				break;
1204 			/* skip name, allows (too) many printable characters */
1205 			name = parse;
1206 			while('!' <= *parse && *parse <= '~')
1207 				parse++;
1208 			if(*parse)
1209 				*parse++ = 0; /* end delimiter for name */
1210 			snprintf(ldata, sizeof(ldata), "%s %s %s",
1211 				name, str_is_ip6(addr)?"AAAA":"A", addr);
1212 			ins = strdup(ldata);
1213 			if(!ins) {
1214 				/* out of memory */
1215 				fclose(in);
1216 				errno=ENOMEM;
1217 				return UB_NOMEM;
1218 			}
1219 			lock_basic_lock(&ctx->cfglock);
1220 			if(!cfg_strlist_insert(&ctx->env->cfg->local_data,
1221 				ins)) {
1222 				lock_basic_unlock(&ctx->cfglock);
1223 				fclose(in);
1224 				free(ins);
1225 				errno=ENOMEM;
1226 				return UB_NOMEM;
1227 			}
1228 			lock_basic_unlock(&ctx->cfglock);
1229 		}
1230 	}
1231 	fclose(in);
1232 	return UB_NOERROR;
1233 }
1234 
1235 /** finalize the context, if not already finalized */
1236 static int ub_ctx_finalize(struct ub_ctx* ctx)
1237 {
1238 	int res = 0;
1239 	lock_basic_lock(&ctx->cfglock);
1240 	if (!ctx->finalized) {
1241 		res = context_finalize(ctx);
1242 	}
1243 	lock_basic_unlock(&ctx->cfglock);
1244 	return res;
1245 }
1246 
1247 /* Print local zones and RR data */
1248 int ub_ctx_print_local_zones(struct ub_ctx* ctx)
1249 {
1250 	int res = ub_ctx_finalize(ctx);
1251 	if (res) return res;
1252 
1253 	local_zones_print(ctx->local_zones);
1254 
1255 	return UB_NOERROR;
1256 }
1257 
1258 /* Add a new zone */
1259 int ub_ctx_zone_add(struct ub_ctx* ctx, const char *zone_name,
1260 	const char *zone_type)
1261 {
1262 	enum localzone_type t;
1263 	struct local_zone* z;
1264 	uint8_t* nm;
1265 	int nmlabs;
1266 	size_t nmlen;
1267 
1268 	int res = ub_ctx_finalize(ctx);
1269 	if (res) return res;
1270 
1271 	if(!local_zone_str2type(zone_type, &t)) {
1272 		return UB_SYNTAX;
1273 	}
1274 
1275 	if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) {
1276 		return UB_SYNTAX;
1277 	}
1278 
1279 	lock_rw_wrlock(&ctx->local_zones->lock);
1280 	if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs,
1281 		LDNS_RR_CLASS_IN))) {
1282 		/* already present in tree */
1283 		lock_rw_wrlock(&z->lock);
1284 		z->type = t; /* update type anyway */
1285 		lock_rw_unlock(&z->lock);
1286 		lock_rw_unlock(&ctx->local_zones->lock);
1287 		free(nm);
1288 		return UB_NOERROR;
1289 	}
1290 	if(!local_zones_add_zone(ctx->local_zones, nm, nmlen, nmlabs,
1291 		LDNS_RR_CLASS_IN, t)) {
1292 		lock_rw_unlock(&ctx->local_zones->lock);
1293 		return UB_NOMEM;
1294 	}
1295 	lock_rw_unlock(&ctx->local_zones->lock);
1296 	return UB_NOERROR;
1297 }
1298 
1299 /* Remove zone */
1300 int ub_ctx_zone_remove(struct ub_ctx* ctx, const char *zone_name)
1301 {
1302 	struct local_zone* z;
1303 	uint8_t* nm;
1304 	int nmlabs;
1305 	size_t nmlen;
1306 
1307 	int res = ub_ctx_finalize(ctx);
1308 	if (res) return res;
1309 
1310 	if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) {
1311 		return UB_SYNTAX;
1312 	}
1313 
1314 	lock_rw_wrlock(&ctx->local_zones->lock);
1315 	if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs,
1316 		LDNS_RR_CLASS_IN))) {
1317 		/* present in tree */
1318 		local_zones_del_zone(ctx->local_zones, z);
1319 	}
1320 	lock_rw_unlock(&ctx->local_zones->lock);
1321 	free(nm);
1322 	return UB_NOERROR;
1323 }
1324 
1325 /* Add new RR data */
1326 int ub_ctx_data_add(struct ub_ctx* ctx, const char *data)
1327 {
1328 	int res = ub_ctx_finalize(ctx);
1329 	if (res) return res;
1330 
1331 	res = local_zones_add_RR(ctx->local_zones, data);
1332 	return (!res) ? UB_NOMEM : UB_NOERROR;
1333 }
1334 
1335 /* Remove RR data */
1336 int ub_ctx_data_remove(struct ub_ctx* ctx, const char *data)
1337 {
1338 	uint8_t* nm;
1339 	int nmlabs;
1340 	size_t nmlen;
1341 	int res = ub_ctx_finalize(ctx);
1342 	if (res) return res;
1343 
1344 	if(!parse_dname(data, &nm, &nmlen, &nmlabs))
1345 		return UB_SYNTAX;
1346 
1347 	local_zones_del_data(ctx->local_zones, nm, nmlen, nmlabs,
1348 		LDNS_RR_CLASS_IN);
1349 
1350 	free(nm);
1351 	return UB_NOERROR;
1352 }
1353 
1354 const char* ub_version(void)
1355 {
1356 	return PACKAGE_VERSION;
1357 }
1358 
1359 int
1360 ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base) {
1361 	struct ub_event_base* new_base;
1362 
1363 	if (!ctx || !ctx->event_base || !base) {
1364 		return UB_INITFAIL;
1365 	}
1366 	if (ub_libevent_get_event_base(ctx->event_base) == base) {
1367 		/* already set */
1368 		return UB_NOERROR;
1369 	}
1370 
1371 	lock_basic_lock(&ctx->cfglock);
1372 	/* destroy the current worker - safe to pass in NULL */
1373 	libworker_delete_event(ctx->event_worker);
1374 	ctx->event_worker = NULL;
1375 	new_base = ub_libevent_event_base(base);
1376 	if (new_base)
1377 		ctx->event_base = new_base;
1378 	ctx->created_bg = 0;
1379 	ctx->dothread = 1;
1380 	lock_basic_unlock(&ctx->cfglock);
1381 	return new_base ? UB_NOERROR : UB_INITFAIL;
1382 }
1383