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