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