]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/unbound/libunbound/libunbound.c
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / contrib / unbound / 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 LIMITED
25  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35
36 /**
37  * \file
38  *
39  * This file contains functions to resolve DNS queries and 
40  * validate the answers. Synchonously 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 "config.h"
47 #include <ctype.h>
48 #include "libunbound/context.h"
49 #include "libunbound/libworker.h"
50 #include "util/locks.h"
51 #include "util/config_file.h"
52 #include "util/alloc.h"
53 #include "util/module.h"
54 #include "util/regional.h"
55 #include "util/log.h"
56 #include "util/random.h"
57 #include "util/net_help.h"
58 #include "util/tube.h"
59 #include "services/modstack.h"
60 #include "services/localzone.h"
61 #include "services/cache/infra.h"
62 #include "services/cache/rrset.h"
63
64 #if defined(UB_ON_WINDOWS) && defined (HAVE_WINDOWS_H)
65 #include <windows.h>
66 #include <iphlpapi.h>
67 #endif /* UB_ON_WINDOWS */
68
69 struct ub_ctx* 
70 ub_ctx_create(void)
71 {
72         struct ub_ctx* ctx;
73         unsigned int seed;
74 #ifdef USE_WINSOCK
75         int r;
76         WSADATA wsa_data;
77 #endif
78         
79         log_init(NULL, 0, NULL); /* logs to stderr */
80         log_ident_set("libunbound");
81 #ifdef USE_WINSOCK
82         if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) {
83                 log_err("could not init winsock. WSAStartup: %s",
84                         wsa_strerror(r));
85                 return NULL;
86         }
87 #endif
88         verbosity = 0; /* errors only */
89         checklock_start();
90         ctx = (struct ub_ctx*)calloc(1, sizeof(*ctx));
91         if(!ctx) {
92                 errno = ENOMEM;
93                 return NULL;
94         }
95         alloc_init(&ctx->superalloc, NULL, 0);
96         seed = (unsigned int)time(NULL) ^ (unsigned int)getpid();
97         if(!(ctx->seed_rnd = ub_initstate(seed, NULL))) {
98                 seed = 0;
99                 ub_randfree(ctx->seed_rnd);
100                 free(ctx);
101                 errno = ENOMEM;
102                 return NULL;
103         }
104         seed = 0;
105         if((ctx->qq_pipe = tube_create()) == NULL) {
106                 int e = errno;
107                 ub_randfree(ctx->seed_rnd);
108                 free(ctx);
109                 errno = e;
110                 return NULL;
111         }
112         if((ctx->rr_pipe = tube_create()) == NULL) {
113                 int e = errno;
114                 tube_delete(ctx->qq_pipe);
115                 ub_randfree(ctx->seed_rnd);
116                 free(ctx);
117                 errno = e;
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                 tube_delete(ctx->qq_pipe);
126                 tube_delete(ctx->rr_pipe);
127                 ub_randfree(ctx->seed_rnd);
128                 free(ctx);
129                 errno = ENOMEM;
130                 return NULL;
131         }
132         ctx->env->cfg = config_create_forlib();
133         if(!ctx->env->cfg) {
134                 tube_delete(ctx->qq_pipe);
135                 tube_delete(ctx->rr_pipe);
136                 free(ctx->env);
137                 ub_randfree(ctx->seed_rnd);
138                 free(ctx);
139                 errno = ENOMEM;
140                 return NULL;
141         }
142         ctx->env->alloc = &ctx->superalloc;
143         ctx->env->worker = NULL;
144         ctx->env->need_to_validate = 0;
145         modstack_init(&ctx->mods);
146         rbtree_init(&ctx->queries, &context_query_cmp);
147         return ctx;
148 }
149
150 /** delete q */
151 static void
152 delq(rbnode_t* n, void* ATTR_UNUSED(arg))
153 {
154         struct ctx_query* q = (struct ctx_query*)n;
155         context_query_delete(q);
156 }
157
158 void 
159 ub_ctx_delete(struct ub_ctx* ctx)
160 {
161         struct alloc_cache* a, *na;
162         if(!ctx) return;
163         /* stop the bg thread */
164         lock_basic_lock(&ctx->cfglock);
165         if(ctx->created_bg) {
166                 uint8_t* msg;
167                 uint32_t len;
168                 uint32_t cmd = UB_LIBCMD_QUIT;
169                 lock_basic_unlock(&ctx->cfglock);
170                 lock_basic_lock(&ctx->qqpipe_lock);
171                 (void)tube_write_msg(ctx->qq_pipe, (uint8_t*)&cmd, 
172                         (uint32_t)sizeof(cmd), 0);
173                 lock_basic_unlock(&ctx->qqpipe_lock);
174                 lock_basic_lock(&ctx->rrpipe_lock);
175                 while(tube_read_msg(ctx->rr_pipe, &msg, &len, 0)) {
176                         /* discard all results except a quit confirm */
177                         if(context_serial_getcmd(msg, len) == UB_LIBCMD_QUIT) {
178                                 free(msg);
179                                 break;
180                         }
181                         free(msg);
182                 }
183                 lock_basic_unlock(&ctx->rrpipe_lock);
184
185                 /* if bg worker is a thread, wait for it to exit, so that all
186                  * resources are really gone. */
187                 lock_basic_lock(&ctx->cfglock);
188                 if(ctx->dothread) {
189                         lock_basic_unlock(&ctx->cfglock);
190                         ub_thread_join(ctx->bg_tid);
191                 } else {
192                         lock_basic_unlock(&ctx->cfglock);
193                 }
194         }
195         else {
196                 lock_basic_unlock(&ctx->cfglock);
197         }
198
199
200         modstack_desetup(&ctx->mods, ctx->env);
201         a = ctx->alloc_list;
202         while(a) {
203                 na = a->super;
204                 a->super = &ctx->superalloc;
205                 alloc_clear(a);
206                 free(a);
207                 a = na;
208         }
209         local_zones_delete(ctx->local_zones);
210         lock_basic_destroy(&ctx->qqpipe_lock);
211         lock_basic_destroy(&ctx->rrpipe_lock);
212         lock_basic_destroy(&ctx->cfglock);
213         tube_delete(ctx->qq_pipe);
214         tube_delete(ctx->rr_pipe);
215         if(ctx->env) {
216                 slabhash_delete(ctx->env->msg_cache);
217                 rrset_cache_delete(ctx->env->rrset_cache);
218                 infra_delete(ctx->env->infra_cache);
219                 config_delete(ctx->env->cfg);
220                 free(ctx->env);
221         }
222         ub_randfree(ctx->seed_rnd);
223         alloc_clear(&ctx->superalloc);
224         traverse_postorder(&ctx->queries, delq, NULL);
225         free(ctx);
226 #ifdef USE_WINSOCK
227         WSACleanup();
228 #endif
229 }
230
231 int 
232 ub_ctx_set_option(struct ub_ctx* ctx, const char* opt, const char* val)
233 {
234         lock_basic_lock(&ctx->cfglock);
235         if(ctx->finalized) {
236                 lock_basic_unlock(&ctx->cfglock);
237                 return UB_AFTERFINAL;
238         }
239         if(!config_set_option(ctx->env->cfg, opt, val)) {
240                 lock_basic_unlock(&ctx->cfglock);
241                 return UB_SYNTAX;
242         }
243         lock_basic_unlock(&ctx->cfglock);
244         return UB_NOERROR;
245 }
246
247 int
248 ub_ctx_get_option(struct ub_ctx* ctx, const char* opt, char** str)
249 {
250         int r;
251         lock_basic_lock(&ctx->cfglock);
252         r = config_get_option_collate(ctx->env->cfg, opt, str);
253         lock_basic_unlock(&ctx->cfglock);
254         if(r == 0) r = UB_NOERROR;
255         else if(r == 1) r = UB_SYNTAX;
256         else if(r == 2) r = UB_NOMEM;
257         return r;
258 }
259
260 int 
261 ub_ctx_config(struct ub_ctx* ctx, const char* fname)
262 {
263         lock_basic_lock(&ctx->cfglock);
264         if(ctx->finalized) {
265                 lock_basic_unlock(&ctx->cfglock);
266                 return UB_AFTERFINAL;
267         }
268         if(!config_read(ctx->env->cfg, fname, NULL)) {
269                 lock_basic_unlock(&ctx->cfglock);
270                 return UB_SYNTAX;
271         }
272         lock_basic_unlock(&ctx->cfglock);
273         return UB_NOERROR;
274 }
275
276 int 
277 ub_ctx_add_ta(struct ub_ctx* ctx, const char* ta)
278 {
279         char* dup = strdup(ta);
280         if(!dup) return UB_NOMEM;
281         lock_basic_lock(&ctx->cfglock);
282         if(ctx->finalized) {
283                 lock_basic_unlock(&ctx->cfglock);
284                 free(dup);
285                 return UB_AFTERFINAL;
286         }
287         if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_list, dup)) {
288                 lock_basic_unlock(&ctx->cfglock);
289                 free(dup);
290                 return UB_NOMEM;
291         }
292         lock_basic_unlock(&ctx->cfglock);
293         return UB_NOERROR;
294 }
295
296 int 
297 ub_ctx_add_ta_file(struct ub_ctx* ctx, const char* fname)
298 {
299         char* dup = strdup(fname);
300         if(!dup) return UB_NOMEM;
301         lock_basic_lock(&ctx->cfglock);
302         if(ctx->finalized) {
303                 lock_basic_unlock(&ctx->cfglock);
304                 free(dup);
305                 return UB_AFTERFINAL;
306         }
307         if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_file_list, dup)) {
308                 lock_basic_unlock(&ctx->cfglock);
309                 free(dup);
310                 return UB_NOMEM;
311         }
312         lock_basic_unlock(&ctx->cfglock);
313         return UB_NOERROR;
314 }
315
316 int 
317 ub_ctx_trustedkeys(struct ub_ctx* ctx, const char* fname)
318 {
319         char* dup = strdup(fname);
320         if(!dup) return UB_NOMEM;
321         lock_basic_lock(&ctx->cfglock);
322         if(ctx->finalized) {
323                 lock_basic_unlock(&ctx->cfglock);
324                 free(dup);
325                 return UB_AFTERFINAL;
326         }
327         if(!cfg_strlist_insert(&ctx->env->cfg->trusted_keys_file_list, dup)) {
328                 lock_basic_unlock(&ctx->cfglock);
329                 free(dup);
330                 return UB_NOMEM;
331         }
332         lock_basic_unlock(&ctx->cfglock);
333         return UB_NOERROR;
334 }
335
336 int
337 ub_ctx_debuglevel(struct ub_ctx* ctx, int d)
338 {
339         lock_basic_lock(&ctx->cfglock);
340         verbosity = d;
341         ctx->env->cfg->verbosity = d;
342         lock_basic_unlock(&ctx->cfglock);
343         return UB_NOERROR;
344 }
345
346 int ub_ctx_debugout(struct ub_ctx* ctx, void* out)
347 {
348         lock_basic_lock(&ctx->cfglock);
349         log_file((FILE*)out);
350         ctx->logfile_override = 1;
351         ctx->log_out = out;
352         lock_basic_unlock(&ctx->cfglock);
353         return UB_NOERROR;
354 }
355
356 int 
357 ub_ctx_async(struct ub_ctx* ctx, int dothread)
358 {
359 #ifdef THREADS_DISABLED
360         if(dothread) /* cannot do threading */
361                 return UB_NOERROR;
362 #endif
363         lock_basic_lock(&ctx->cfglock);
364         if(ctx->finalized) {
365                 lock_basic_unlock(&ctx->cfglock);
366                 return UB_AFTERFINAL;
367         }
368         ctx->dothread = dothread;
369         lock_basic_unlock(&ctx->cfglock);
370         return UB_NOERROR;
371 }
372
373 int 
374 ub_poll(struct ub_ctx* ctx)
375 {
376         /* no need to hold lock while testing for readability. */
377         return tube_poll(ctx->rr_pipe);
378 }
379
380 int 
381 ub_fd(struct ub_ctx* ctx)
382 {
383         return tube_read_fd(ctx->rr_pipe);
384 }
385
386 /** process answer from bg worker */
387 static int
388 process_answer_detail(struct ub_ctx* ctx, uint8_t* msg, uint32_t len,
389         ub_callback_t* cb, void** cbarg, int* err,
390         struct ub_result** res)
391 {
392         struct ctx_query* q;
393         if(context_serial_getcmd(msg, len) != UB_LIBCMD_ANSWER) {
394                 log_err("error: bad data from bg worker %d",
395                         (int)context_serial_getcmd(msg, len));
396                 return 0;
397         }
398
399         lock_basic_lock(&ctx->cfglock);
400         q = context_deserialize_answer(ctx, msg, len, err);
401         if(!q) {
402                 lock_basic_unlock(&ctx->cfglock);
403                 /* probably simply the lookup that failed, i.e.
404                  * response returned before cancel was sent out, so noerror */
405                 return 1;
406         }
407         log_assert(q->async);
408
409         /* grab cb while locked */
410         if(q->cancelled) {
411                 *cb = NULL;
412                 *cbarg = NULL;
413         } else {
414                 *cb = q->cb;
415                 *cbarg = q->cb_arg;
416         }
417         if(*err) {
418                 *res = NULL;
419                 ub_resolve_free(q->res);
420         } else {
421                 /* parse the message, extract rcode, fill result */
422                 ldns_buffer* buf = ldns_buffer_new(q->msg_len);
423                 struct regional* region = regional_create();
424                 *res = q->res;
425                 (*res)->rcode = LDNS_RCODE_SERVFAIL;
426                 if(region && buf) {
427                         ldns_buffer_clear(buf);
428                         ldns_buffer_write(buf, q->msg, q->msg_len);
429                         ldns_buffer_flip(buf);
430                         libworker_enter_result(*res, buf, region,
431                                 q->msg_security);
432                 }
433                 (*res)->answer_packet = q->msg;
434                 (*res)->answer_len = (int)q->msg_len;
435                 q->msg = NULL;
436                 ldns_buffer_free(buf);
437                 regional_destroy(region);
438         }
439         q->res = NULL;
440         /* delete the q from list */
441         (void)rbtree_delete(&ctx->queries, q->node.key);
442         ctx->num_async--;
443         context_query_delete(q);
444         lock_basic_unlock(&ctx->cfglock);
445
446         if(*cb) return 2;
447         ub_resolve_free(*res);
448         return 1;
449 }
450
451 /** process answer from bg worker */
452 static int
453 process_answer(struct ub_ctx* ctx, uint8_t* msg, uint32_t len)
454 {
455         int err;
456         ub_callback_t cb;
457         void* cbarg;
458         struct ub_result* res;
459         int r;
460
461         r = process_answer_detail(ctx, msg, len, &cb, &cbarg, &err, &res);
462
463         /* no locks held while calling callback, so that library is
464          * re-entrant. */
465         if(r == 2)
466                 (*cb)(cbarg, err, res);
467
468         return r;
469 }
470
471 int 
472 ub_process(struct ub_ctx* ctx)
473 {
474         int r;
475         uint8_t* msg;
476         uint32_t len;
477         while(1) {
478                 msg = NULL;
479                 lock_basic_lock(&ctx->rrpipe_lock);
480                 r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1);
481                 lock_basic_unlock(&ctx->rrpipe_lock);
482                 if(r == 0)
483                         return UB_PIPE;
484                 else if(r == -1)
485                         break;
486                 if(!process_answer(ctx, msg, len)) {
487                         free(msg);
488                         return UB_PIPE;
489                 }
490                 free(msg);
491         }
492         return UB_NOERROR;
493 }
494
495 int 
496 ub_wait(struct ub_ctx* ctx)
497 {
498         int err;
499         ub_callback_t cb;
500         void* cbarg;
501         struct ub_result* res;
502         int r;
503         uint8_t* msg;
504         uint32_t len;
505         /* this is basically the same loop as _process(), but with changes.
506          * holds the rrpipe lock and waits with tube_wait */
507         while(1) {
508                 lock_basic_lock(&ctx->rrpipe_lock);
509                 lock_basic_lock(&ctx->cfglock);
510                 if(ctx->num_async == 0) {
511                         lock_basic_unlock(&ctx->cfglock);
512                         lock_basic_unlock(&ctx->rrpipe_lock);
513                         break;
514                 }
515                 lock_basic_unlock(&ctx->cfglock);
516
517                 /* keep rrpipe locked, while
518                  *      o waiting for pipe readable
519                  *      o parsing message
520                  *      o possibly decrementing num_async
521                  * do callback without lock
522                  */
523                 r = tube_wait(ctx->rr_pipe);
524                 if(r) {
525                         r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1);
526                         if(r == 0) {
527                                 lock_basic_unlock(&ctx->rrpipe_lock);
528                                 return UB_PIPE;
529                         }
530                         if(r == -1) {
531                                 lock_basic_unlock(&ctx->rrpipe_lock);
532                                 continue;
533                         }
534                         r = process_answer_detail(ctx, msg, len, 
535                                 &cb, &cbarg, &err, &res);
536                         lock_basic_unlock(&ctx->rrpipe_lock);
537                         free(msg);
538                         if(r == 0)
539                                 return UB_PIPE;
540                         if(r == 2)
541                                 (*cb)(cbarg, err, res);
542                 } else {
543                         lock_basic_unlock(&ctx->rrpipe_lock);
544                 }
545         }
546         return UB_NOERROR;
547 }
548
549 int 
550 ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype, 
551         int rrclass, struct ub_result** result)
552 {
553         struct ctx_query* q;
554         int r;
555         *result = NULL;
556
557         lock_basic_lock(&ctx->cfglock);
558         if(!ctx->finalized) {
559                 r = context_finalize(ctx);
560                 if(r) {
561                         lock_basic_unlock(&ctx->cfglock);
562                         return r;
563                 }
564         }
565         /* create new ctx_query and attempt to add to the list */
566         lock_basic_unlock(&ctx->cfglock);
567         q = context_new(ctx, name, rrtype, rrclass, NULL, NULL);
568         if(!q)
569                 return UB_NOMEM;
570         /* become a resolver thread for a bit */
571
572         r = libworker_fg(ctx, q);
573         if(r) {
574                 lock_basic_lock(&ctx->cfglock);
575                 (void)rbtree_delete(&ctx->queries, q->node.key);
576                 context_query_delete(q);
577                 lock_basic_unlock(&ctx->cfglock);
578                 return r;
579         }
580         q->res->answer_packet = q->msg;
581         q->res->answer_len = (int)q->msg_len;
582         q->msg = NULL;
583         *result = q->res;
584         q->res = NULL;
585
586         lock_basic_lock(&ctx->cfglock);
587         (void)rbtree_delete(&ctx->queries, q->node.key);
588         context_query_delete(q);
589         lock_basic_unlock(&ctx->cfglock);
590         return UB_NOERROR;
591 }
592
593 int 
594 ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype, 
595         int rrclass, void* mydata, ub_callback_t callback, int* async_id)
596 {
597         struct ctx_query* q;
598         uint8_t* msg = NULL;
599         uint32_t len = 0;
600
601         if(async_id)
602                 *async_id = 0;
603         lock_basic_lock(&ctx->cfglock);
604         if(!ctx->finalized) {
605                 int r = context_finalize(ctx);
606                 if(r) {
607                         lock_basic_unlock(&ctx->cfglock);
608                         return r;
609                 }
610         }
611         if(!ctx->created_bg) {
612                 int r;
613                 ctx->created_bg = 1;
614                 lock_basic_unlock(&ctx->cfglock);
615                 r = libworker_bg(ctx);
616                 if(r) {
617                         lock_basic_lock(&ctx->cfglock);
618                         ctx->created_bg = 0;
619                         lock_basic_unlock(&ctx->cfglock);
620                         return r;
621                 }
622         } else {
623                 lock_basic_unlock(&ctx->cfglock);
624         }
625
626         /* create new ctx_query and attempt to add to the list */
627         q = context_new(ctx, name, rrtype, rrclass, callback, mydata);
628         if(!q)
629                 return UB_NOMEM;
630
631         /* write over pipe to background worker */
632         lock_basic_lock(&ctx->cfglock);
633         msg = context_serialize_new_query(q, &len);
634         if(!msg) {
635                 (void)rbtree_delete(&ctx->queries, q->node.key);
636                 ctx->num_async--;
637                 context_query_delete(q);
638                 lock_basic_unlock(&ctx->cfglock);
639                 return UB_NOMEM;
640         }
641         if(async_id)
642                 *async_id = q->querynum;
643         lock_basic_unlock(&ctx->cfglock);
644         
645         lock_basic_lock(&ctx->qqpipe_lock);
646         if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) {
647                 lock_basic_unlock(&ctx->qqpipe_lock);
648                 free(msg);
649                 return UB_PIPE;
650         }
651         lock_basic_unlock(&ctx->qqpipe_lock);
652         free(msg);
653         return UB_NOERROR;
654 }
655
656 int 
657 ub_cancel(struct ub_ctx* ctx, int async_id)
658 {
659         struct ctx_query* q;
660         uint8_t* msg = NULL;
661         uint32_t len = 0;
662         lock_basic_lock(&ctx->cfglock);
663         q = (struct ctx_query*)rbtree_search(&ctx->queries, &async_id);
664         if(!q || !q->async) {
665                 /* it is not there, so nothing to do */
666                 lock_basic_unlock(&ctx->cfglock);
667                 return UB_NOID;
668         }
669         log_assert(q->async);
670         q->cancelled = 1;
671         
672         /* delete it */
673         if(!ctx->dothread) { /* if forked */
674                 (void)rbtree_delete(&ctx->queries, q->node.key);
675                 ctx->num_async--;
676                 msg = context_serialize_cancel(q, &len);
677                 context_query_delete(q);
678                 lock_basic_unlock(&ctx->cfglock);
679                 if(!msg) {
680                         return UB_NOMEM;
681                 }
682                 /* send cancel to background worker */
683                 lock_basic_lock(&ctx->qqpipe_lock);
684                 if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) {
685                         lock_basic_unlock(&ctx->qqpipe_lock);
686                         free(msg);
687                         return UB_PIPE;
688                 }
689                 lock_basic_unlock(&ctx->qqpipe_lock);
690                 free(msg);
691         } else {
692                 lock_basic_unlock(&ctx->cfglock);
693         }
694         return UB_NOERROR;
695 }
696
697 void 
698 ub_resolve_free(struct ub_result* result)
699 {
700         char** p;
701         if(!result) return;
702         free(result->qname);
703         if(result->canonname != result->qname)
704                 free(result->canonname);
705         if(result->data)
706                 for(p = result->data; *p; p++)
707                         free(*p);
708         free(result->data);
709         free(result->len);
710         free(result->answer_packet);
711         free(result->why_bogus);
712         free(result);
713 }
714
715 const char* 
716 ub_strerror(int err)
717 {
718         switch(err) {
719                 case UB_NOERROR: return "no error";
720                 case UB_SOCKET: return "socket io error";
721                 case UB_NOMEM: return "out of memory";
722                 case UB_SYNTAX: return "syntax error";
723                 case UB_SERVFAIL: return "server failure";
724                 case UB_FORKFAIL: return "could not fork";
725                 case UB_INITFAIL: return "initialization failure";
726                 case UB_AFTERFINAL: return "setting change after finalize";
727                 case UB_PIPE: return "error in pipe communication with async";
728                 case UB_READFILE: return "error reading file";
729                 case UB_NOID: return "error async_id does not exist";
730                 default: return "unknown error";
731         }
732 }
733
734 int 
735 ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr)
736 {
737         struct sockaddr_storage storage;
738         socklen_t stlen;
739         struct config_stub* s;
740         char* dupl;
741         lock_basic_lock(&ctx->cfglock);
742         if(ctx->finalized) {
743                 lock_basic_unlock(&ctx->cfglock);
744                 errno=EINVAL;
745                 return UB_AFTERFINAL;
746         }
747         if(!addr) {
748                 /* disable fwd mode - the root stub should be first. */
749                 if(ctx->env->cfg->forwards &&
750                         strcmp(ctx->env->cfg->forwards->name, ".") == 0) {
751                         s = ctx->env->cfg->forwards;
752                         ctx->env->cfg->forwards = s->next;
753                         s->next = NULL;
754                         config_delstubs(s);
755                 }
756                 lock_basic_unlock(&ctx->cfglock);
757                 return UB_NOERROR;
758         }
759         lock_basic_unlock(&ctx->cfglock);
760
761         /* check syntax for addr */
762         if(!extstrtoaddr(addr, &storage, &stlen)) {
763                 errno=EINVAL;
764                 return UB_SYNTAX;
765         }
766         
767         /* it parses, add root stub in front of list */
768         lock_basic_lock(&ctx->cfglock);
769         if(!ctx->env->cfg->forwards ||
770                 strcmp(ctx->env->cfg->forwards->name, ".") != 0) {
771                 s = calloc(1, sizeof(*s));
772                 if(!s) {
773                         lock_basic_unlock(&ctx->cfglock);
774                         errno=ENOMEM;
775                         return UB_NOMEM;
776                 }
777                 s->name = strdup(".");
778                 if(!s->name) {
779                         free(s);
780                         lock_basic_unlock(&ctx->cfglock);
781                         errno=ENOMEM;
782                         return UB_NOMEM;
783                 }
784                 s->next = ctx->env->cfg->forwards;
785                 ctx->env->cfg->forwards = s;
786         } else {
787                 log_assert(ctx->env->cfg->forwards);
788                 s = ctx->env->cfg->forwards;
789         }
790         dupl = strdup(addr);
791         if(!dupl) {
792                 lock_basic_unlock(&ctx->cfglock);
793                 errno=ENOMEM;
794                 return UB_NOMEM;
795         }
796         if(!cfg_strlist_insert(&s->addrs, dupl)) {
797                 free(dupl);
798                 lock_basic_unlock(&ctx->cfglock);
799                 errno=ENOMEM;
800                 return UB_NOMEM;
801         }
802         lock_basic_unlock(&ctx->cfglock);
803         return UB_NOERROR;
804 }
805
806 int 
807 ub_ctx_resolvconf(struct ub_ctx* ctx, const char* fname)
808 {
809         FILE* in;
810         int numserv = 0;
811         char buf[1024];
812         char* parse, *addr;
813         int r;
814
815         if(fname == NULL) {
816 #if !defined(UB_ON_WINDOWS) || !defined(HAVE_WINDOWS_H)
817                 fname = "/etc/resolv.conf";
818 #else
819                 FIXED_INFO *info;
820                 ULONG buflen = sizeof(*info);
821                 IP_ADDR_STRING *ptr;
822
823                 info = (FIXED_INFO *) malloc(sizeof (FIXED_INFO));
824                 if (info == NULL) 
825                         return UB_READFILE;
826
827                 if (GetNetworkParams(info, &buflen) == ERROR_BUFFER_OVERFLOW) {
828                         free(info);
829                         info = (FIXED_INFO *) malloc(buflen);
830                         if (info == NULL)
831                                 return UB_READFILE;
832                 }
833
834                 if (GetNetworkParams(info, &buflen) == NO_ERROR) {
835                         int retval=0;
836                         ptr = &(info->DnsServerList);
837                         while (ptr) {
838                                 numserv++;
839                                 if((retval=ub_ctx_set_fwd(ctx, 
840                                         ptr->IpAddress.String)!=0)) {
841                                         free(info);
842                                         return retval;
843                                 }
844                                 ptr = ptr->Next;
845                         }
846                         free(info);
847                         if (numserv==0)
848                                 return UB_READFILE;
849                         return UB_NOERROR;
850                 }
851                 free(info);
852                 return UB_READFILE;
853 #endif /* WINDOWS */
854         }
855         in = fopen(fname, "r");
856         if(!in) {
857                 /* error in errno! perror(fname) */
858                 return UB_READFILE;
859         }
860         while(fgets(buf, (int)sizeof(buf), in)) {
861                 buf[sizeof(buf)-1] = 0;
862                 parse=buf;
863                 while(*parse == ' ' || *parse == '\t')
864                         parse++;
865                 if(strncmp(parse, "nameserver", 10) == 0) {
866                         numserv++;
867                         parse += 10; /* skip 'nameserver' */
868                         /* skip whitespace */
869                         while(*parse == ' ' || *parse == '\t')
870                                 parse++;
871                         addr = parse;
872                         /* skip [0-9a-fA-F.:]*, i.e. IP4 and IP6 address */
873                         while(isxdigit(*parse) || *parse=='.' || *parse==':')
874                                 parse++;
875                         /* terminate after the address, remove newline */
876                         *parse = 0;
877                         
878                         if((r = ub_ctx_set_fwd(ctx, addr)) != UB_NOERROR) {
879                                 fclose(in);
880                                 return r;
881                         }
882                 }
883         }
884         fclose(in);
885         if(numserv == 0) {
886                 /* from resolv.conf(5) if none given, use localhost */
887                 return ub_ctx_set_fwd(ctx, "127.0.0.1");
888         }
889         return UB_NOERROR;
890 }
891
892 int
893 ub_ctx_hosts(struct ub_ctx* ctx, const char* fname)
894 {
895         FILE* in;
896         char buf[1024], ldata[1024];
897         char* parse, *addr, *name, *ins;
898         lock_basic_lock(&ctx->cfglock);
899         if(ctx->finalized) {
900                 lock_basic_unlock(&ctx->cfglock);
901                 errno=EINVAL;
902                 return UB_AFTERFINAL;
903         }
904         lock_basic_unlock(&ctx->cfglock);
905         if(fname == NULL) {
906 #if defined(UB_ON_WINDOWS) && defined(HAVE_WINDOWS_H)
907                 /*
908                  * If this is Windows NT/XP/2K it's in
909                  * %WINDIR%\system32\drivers\etc\hosts.
910                  * If this is Windows 95/98/Me it's in %WINDIR%\hosts.
911                  */
912                 name = getenv("WINDIR");
913                 if (name != NULL) {
914                         int retval=0;
915                         snprintf(buf, sizeof(buf), "%s%s", name, 
916                                 "\\system32\\drivers\\etc\\hosts");
917                         if((retval=ub_ctx_hosts(ctx, buf)) !=0 ) {
918                                 snprintf(buf, sizeof(buf), "%s%s", name, 
919                                         "\\hosts");
920                                 retval=ub_ctx_hosts(ctx, buf);
921                         }
922                         free(name);
923                         return retval;
924                 }
925                 return UB_READFILE;
926 #else
927                 fname = "/etc/hosts";
928 #endif /* WIN32 */
929         }
930         in = fopen(fname, "r");
931         if(!in) {
932                 /* error in errno! perror(fname) */
933                 return UB_READFILE;
934         }
935         while(fgets(buf, (int)sizeof(buf), in)) {
936                 buf[sizeof(buf)-1] = 0;
937                 parse=buf;
938                 while(*parse == ' ' || *parse == '\t')
939                         parse++;
940                 if(*parse == '#')
941                         continue; /* skip comment */
942                 /* format: <addr> spaces <name> spaces <name> ... */
943                 addr = parse;
944                 /* skip addr */
945                 while(isxdigit(*parse) || *parse == '.' || *parse == ':')
946                         parse++;
947                 if(*parse == '\n' || *parse == 0)
948                         continue;
949                 if(*parse == '%') 
950                         continue; /* ignore macOSX fe80::1%lo0 localhost */
951                 if(*parse != ' ' && *parse != '\t') {
952                         /* must have whitespace after address */
953                         fclose(in);
954                         errno=EINVAL;
955                         return UB_SYNTAX;
956                 }
957                 *parse++ = 0; /* end delimiter for addr ... */
958                 /* go to names and add them */
959                 while(*parse) {
960                         while(*parse == ' ' || *parse == '\t' || *parse=='\n')
961                                 parse++;
962                         if(*parse == 0 || *parse == '#')
963                                 break;
964                         /* skip name, allows (too) many printable characters */
965                         name = parse;
966                         while('!' <= *parse && *parse <= '~')
967                                 parse++;
968                         if(*parse)
969                                 *parse++ = 0; /* end delimiter for name */
970                         snprintf(ldata, sizeof(ldata), "%s %s %s",
971                                 name, str_is_ip6(addr)?"AAAA":"A", addr);
972                         ins = strdup(ldata);
973                         if(!ins) {
974                                 /* out of memory */
975                                 fclose(in);
976                                 errno=ENOMEM;
977                                 return UB_NOMEM;
978                         }
979                         lock_basic_lock(&ctx->cfglock);
980                         if(!cfg_strlist_insert(&ctx->env->cfg->local_data, 
981                                 ins)) {
982                                 lock_basic_unlock(&ctx->cfglock);
983                                 fclose(in);
984                                 free(ins);
985                                 errno=ENOMEM;
986                                 return UB_NOMEM;
987                         }
988                         lock_basic_unlock(&ctx->cfglock);
989                 }
990         }
991         fclose(in);
992         return UB_NOERROR;
993 }
994
995 /** finalize the context, if not already finalized */
996 static int ub_ctx_finalize(struct ub_ctx* ctx)
997 {
998         int res = 0;
999         lock_basic_lock(&ctx->cfglock);
1000         if (!ctx->finalized) {
1001                 res = context_finalize(ctx);
1002         }
1003         lock_basic_unlock(&ctx->cfglock);
1004         return res;
1005 }
1006
1007 /* Print local zones and RR data */
1008 int ub_ctx_print_local_zones(struct ub_ctx* ctx)
1009 {   
1010         int res = ub_ctx_finalize(ctx);
1011         if (res) return res;
1012
1013         local_zones_print(ctx->local_zones);
1014
1015         return UB_NOERROR;
1016 }
1017
1018 /* Add a new zone */
1019 int ub_ctx_zone_add(struct ub_ctx* ctx, char *zone_name, char *zone_type)
1020 {
1021         enum localzone_type t;
1022         struct local_zone* z;
1023         uint8_t* nm;
1024         int nmlabs;
1025         size_t nmlen;
1026
1027         int res = ub_ctx_finalize(ctx);
1028         if (res) return res;
1029
1030         if(!local_zone_str2type(zone_type, &t)) {
1031                 return UB_SYNTAX;
1032         }
1033
1034         if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) {
1035                 return UB_SYNTAX;
1036         }
1037
1038         lock_quick_lock(&ctx->local_zones->lock);
1039         if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, 
1040                 LDNS_RR_CLASS_IN))) {
1041                 /* already present in tree */
1042                 lock_rw_wrlock(&z->lock);
1043                 z->type = t; /* update type anyway */
1044                 lock_rw_unlock(&z->lock);
1045                 lock_quick_unlock(&ctx->local_zones->lock);
1046                 free(nm);
1047                 return UB_NOERROR;
1048         }
1049         if(!local_zones_add_zone(ctx->local_zones, nm, nmlen, nmlabs, 
1050                 LDNS_RR_CLASS_IN, t)) {
1051                 lock_quick_unlock(&ctx->local_zones->lock);
1052                 return UB_NOMEM;
1053         }
1054         lock_quick_unlock(&ctx->local_zones->lock);
1055         return UB_NOERROR;
1056 }
1057
1058 /* Remove zone */
1059 int ub_ctx_zone_remove(struct ub_ctx* ctx, char *zone_name)
1060 {   
1061         struct local_zone* z;
1062         uint8_t* nm;
1063         int nmlabs;
1064         size_t nmlen;
1065
1066         int res = ub_ctx_finalize(ctx);
1067         if (res) return res;
1068
1069         if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) {
1070                 return UB_SYNTAX;
1071         }
1072
1073         lock_quick_lock(&ctx->local_zones->lock);
1074         if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, 
1075                 LDNS_RR_CLASS_IN))) {
1076                 /* present in tree */
1077                 local_zones_del_zone(ctx->local_zones, z);
1078         }
1079         lock_quick_unlock(&ctx->local_zones->lock);
1080         free(nm);
1081         return UB_NOERROR;
1082 }
1083
1084 /* Add new RR data */
1085 int ub_ctx_data_add(struct ub_ctx* ctx, char *data)
1086 {
1087         ldns_buffer* buf;
1088         int res = ub_ctx_finalize(ctx);
1089         if (res) return res;
1090
1091         lock_basic_lock(&ctx->cfglock);
1092         buf = ldns_buffer_new(ctx->env->cfg->msg_buffer_size);
1093         lock_basic_unlock(&ctx->cfglock);
1094         if(!buf) return UB_NOMEM;
1095
1096         res = local_zones_add_RR(ctx->local_zones, data, buf);
1097
1098         ldns_buffer_free(buf);
1099         return (!res) ? UB_NOMEM : UB_NOERROR;
1100 }
1101
1102 /* Remove RR data */
1103 int ub_ctx_data_remove(struct ub_ctx* ctx, char *data)
1104 {
1105         uint8_t* nm;
1106         int nmlabs;
1107         size_t nmlen;
1108         int res = ub_ctx_finalize(ctx);
1109         if (res) return res;
1110
1111         if(!parse_dname(data, &nm, &nmlen, &nmlabs)) 
1112                 return UB_SYNTAX;
1113
1114         local_zones_del_data(ctx->local_zones, nm, nmlen, nmlabs, 
1115                 LDNS_RR_CLASS_IN);
1116
1117         free(nm);
1118         return UB_NOERROR;
1119 }
1120
1121 const char* ub_version(void)
1122 {
1123         return PACKAGE_VERSION;
1124 }