]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/unbound/libunbound/libworker.c
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / contrib / unbound / libunbound / libworker.c
1 /*
2  * libunbound/worker.c - worker thread or process that resolves
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 the worker process or thread that performs
40  * the DNS resolving and validation. The worker is called by a procedure
41  * and if in the background continues until exit, if in the foreground
42  * returns from the procedure when done.
43  */
44 #include "config.h"
45 #include <ldns/dname.h>
46 #include <ldns/wire2host.h>
47 #ifdef HAVE_SSL
48 #include <openssl/ssl.h>
49 #endif
50 #include "libunbound/libworker.h"
51 #include "libunbound/context.h"
52 #include "libunbound/unbound.h"
53 #include "libunbound/worker.h"
54 #include "services/outside_network.h"
55 #include "services/mesh.h"
56 #include "services/localzone.h"
57 #include "services/cache/rrset.h"
58 #include "services/outbound_list.h"
59 #include "util/fptr_wlist.h"
60 #include "util/module.h"
61 #include "util/regional.h"
62 #include "util/random.h"
63 #include "util/config_file.h"
64 #include "util/netevent.h"
65 #include "util/storage/lookup3.h"
66 #include "util/storage/slabhash.h"
67 #include "util/net_help.h"
68 #include "util/data/dname.h"
69 #include "util/data/msgreply.h"
70 #include "util/data/msgencode.h"
71 #include "util/tube.h"
72 #include "iterator/iter_fwd.h"
73 #include "iterator/iter_hints.h"
74
75 /** handle new query command for bg worker */
76 static void handle_newq(struct libworker* w, uint8_t* buf, uint32_t len);
77
78 /** delete libworker struct */
79 static void
80 libworker_delete(struct libworker* w)
81 {
82         if(!w) return;
83         if(w->env) {
84                 outside_network_quit_prepare(w->back);
85                 mesh_delete(w->env->mesh);
86                 context_release_alloc(w->ctx, w->env->alloc, 
87                         !w->is_bg || w->is_bg_thread);
88                 ldns_buffer_free(w->env->scratch_buffer);
89                 regional_destroy(w->env->scratch);
90                 forwards_delete(w->env->fwds);
91                 hints_delete(w->env->hints);
92                 ub_randfree(w->env->rnd);
93                 free(w->env);
94         }
95 #ifdef HAVE_SSL
96         SSL_CTX_free(w->sslctx);
97 #endif
98         outside_network_delete(w->back);
99         comm_base_delete(w->base);
100         free(w);
101 }
102
103 /** setup fresh libworker struct */
104 static struct libworker*
105 libworker_setup(struct ub_ctx* ctx, int is_bg)
106 {
107         unsigned int seed;
108         struct libworker* w = (struct libworker*)calloc(1, sizeof(*w));
109         struct config_file* cfg = ctx->env->cfg;
110         int* ports;
111         int numports;
112         if(!w) return NULL;
113         w->is_bg = is_bg;
114         w->ctx = ctx;
115         w->env = (struct module_env*)malloc(sizeof(*w->env));
116         if(!w->env) {
117                 free(w);
118                 return NULL;
119         }
120         *w->env = *ctx->env;
121         w->env->alloc = context_obtain_alloc(ctx, !w->is_bg || w->is_bg_thread);
122         if(!w->env->alloc) {
123                 libworker_delete(w);
124                 return NULL;
125         }
126         w->thread_num = w->env->alloc->thread_num;
127         alloc_set_id_cleanup(w->env->alloc, &libworker_alloc_cleanup, w);
128         if(!w->is_bg || w->is_bg_thread) {
129                 lock_basic_lock(&ctx->cfglock);
130         }
131         w->env->scratch = regional_create_custom(cfg->msg_buffer_size);
132         w->env->scratch_buffer = ldns_buffer_new(cfg->msg_buffer_size);
133         w->env->fwds = forwards_create();
134         if(w->env->fwds && !forwards_apply_cfg(w->env->fwds, cfg)) { 
135                 forwards_delete(w->env->fwds);
136                 w->env->fwds = NULL;
137         }
138         w->env->hints = hints_create();
139         if(w->env->hints && !hints_apply_cfg(w->env->hints, cfg)) { 
140                 hints_delete(w->env->hints);
141                 w->env->hints = NULL;
142         }
143         if(cfg->ssl_upstream) {
144                 w->sslctx = connect_sslctx_create(NULL, NULL, NULL);
145                 if(!w->sslctx) {
146                         /* to make the setup fail after unlock */
147                         hints_delete(w->env->hints);
148                         w->env->hints = NULL;
149                 }
150         }
151         if(!w->is_bg || w->is_bg_thread) {
152                 lock_basic_unlock(&ctx->cfglock);
153         }
154         if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds ||
155                 !w->env->hints) {
156                 libworker_delete(w);
157                 return NULL;
158         }
159         w->env->worker = (struct worker*)w;
160         w->env->probe_timer = NULL;
161         seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^
162                 (((unsigned int)w->thread_num)<<17);
163         seed ^= (unsigned int)w->env->alloc->next_id;
164         if(!w->is_bg || w->is_bg_thread) {
165                 lock_basic_lock(&ctx->cfglock);
166         }
167         if(!(w->env->rnd = ub_initstate(seed, ctx->seed_rnd))) {
168                 if(!w->is_bg || w->is_bg_thread) {
169                         lock_basic_unlock(&ctx->cfglock);
170                 }
171                 seed = 0;
172                 libworker_delete(w);
173                 return NULL;
174         }
175         if(!w->is_bg || w->is_bg_thread) {
176                 lock_basic_unlock(&ctx->cfglock);
177         }
178         if(1) {
179                 /* primitive lockout for threading: if it overwrites another
180                  * thread it is like wiping the cache (which is likely empty
181                  * at the start) */
182                 /* note we are holding the ctx lock in normal threaded
183                  * cases so that is solved properly, it is only for many ctx
184                  * in different threads that this may clash */
185                 static int done_raninit = 0;
186                 if(!done_raninit) {
187                         done_raninit = 1;
188                         hash_set_raninit((uint32_t)ub_random(w->env->rnd));
189                 }
190         }
191         seed = 0;
192
193         w->base = comm_base_create(0);
194         if(!w->base) {
195                 libworker_delete(w);
196                 return NULL;
197         }
198         if(!w->is_bg || w->is_bg_thread) {
199                 lock_basic_lock(&ctx->cfglock);
200         }
201         numports = cfg_condense_ports(cfg, &ports);
202         if(numports == 0) {
203                 libworker_delete(w);
204                 return NULL;
205         }
206         w->back = outside_network_create(w->base, cfg->msg_buffer_size,
207                 (size_t)cfg->outgoing_num_ports, cfg->out_ifs,
208                 cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6, 
209                 cfg->do_tcp?cfg->outgoing_num_tcp:0,
210                 w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id,
211                 ports, numports, cfg->unwanted_threshold,
212                 &libworker_alloc_cleanup, w, cfg->do_udp, w->sslctx);
213         if(!w->is_bg || w->is_bg_thread) {
214                 lock_basic_unlock(&ctx->cfglock);
215         }
216         free(ports);
217         if(!w->back) {
218                 libworker_delete(w);
219                 return NULL;
220         }
221         w->env->mesh = mesh_create(&ctx->mods, w->env);
222         if(!w->env->mesh) {
223                 libworker_delete(w);
224                 return NULL;
225         }
226         w->env->send_query = &libworker_send_query;
227         w->env->detach_subs = &mesh_detach_subs;
228         w->env->attach_sub = &mesh_attach_sub;
229         w->env->kill_sub = &mesh_state_delete;
230         w->env->detect_cycle = &mesh_detect_cycle;
231         comm_base_timept(w->base, &w->env->now, &w->env->now_tv);
232         return w;
233 }
234
235 /** handle cancel command for bg worker */
236 static void
237 handle_cancel(struct libworker* w, uint8_t* buf, uint32_t len)
238 {
239         struct ctx_query* q;
240         if(w->is_bg_thread) {
241                 lock_basic_lock(&w->ctx->cfglock);
242                 q = context_deserialize_cancel(w->ctx, buf, len);
243                 lock_basic_unlock(&w->ctx->cfglock);
244         } else {
245                 q = context_deserialize_cancel(w->ctx, buf, len);
246         }
247         if(!q) {
248                 /* probably simply lookup failed, i.e. the message had been
249                  * processed and answered before the cancel arrived */
250                 return;
251         }
252         q->cancelled = 1;
253         free(buf);
254 }
255
256 /** do control command coming into bg server */
257 static void
258 libworker_do_cmd(struct libworker* w, uint8_t* msg, uint32_t len)
259 {
260         switch(context_serial_getcmd(msg, len)) {
261                 default:
262                 case UB_LIBCMD_ANSWER:
263                         log_err("unknown command for bg worker %d", 
264                                 (int)context_serial_getcmd(msg, len));
265                         /* and fall through to quit */
266                 case UB_LIBCMD_QUIT:
267                         free(msg);
268                         comm_base_exit(w->base);
269                         break;
270                 case UB_LIBCMD_NEWQUERY:
271                         handle_newq(w, msg, len);
272                         break;
273                 case UB_LIBCMD_CANCEL:
274                         handle_cancel(w, msg, len);
275                         break;
276         }
277 }
278
279 /** handle control command coming into server */
280 void 
281 libworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), 
282         uint8_t* msg, size_t len, int err, void* arg)
283 {
284         struct libworker* w = (struct libworker*)arg;
285
286         if(err != 0) {
287                 free(msg);
288                 /* it is of no use to go on, exit */
289                 comm_base_exit(w->base);
290                 return;
291         }
292         libworker_do_cmd(w, msg, len); /* also frees the buf */
293 }
294
295 /** the background thread func */
296 static void*
297 libworker_dobg(void* arg)
298 {
299         /* setup */
300         uint32_t m;
301         struct libworker* w = (struct libworker*)arg;
302         struct ub_ctx* ctx;
303         if(!w) {
304                 log_err("libunbound bg worker init failed, nomem");
305                 return NULL;
306         }
307         ctx = w->ctx;
308         log_thread_set(&w->thread_num);
309 #ifdef THREADS_DISABLED
310         /* we are forked */
311         w->is_bg_thread = 0;
312         /* close non-used parts of the pipes */
313         tube_close_write(ctx->qq_pipe);
314         tube_close_read(ctx->rr_pipe);
315 #endif
316         if(!tube_setup_bg_listen(ctx->qq_pipe, w->base, 
317                 libworker_handle_control_cmd, w)) {
318                 log_err("libunbound bg worker init failed, no bglisten");
319                 return NULL;
320         }
321         if(!tube_setup_bg_write(ctx->rr_pipe, w->base)) {
322                 log_err("libunbound bg worker init failed, no bgwrite");
323                 return NULL;
324         }
325
326         /* do the work */
327         comm_base_dispatch(w->base);
328
329         /* cleanup */
330         m = UB_LIBCMD_QUIT;
331         tube_remove_bg_listen(w->ctx->qq_pipe);
332         tube_remove_bg_write(w->ctx->rr_pipe);
333         libworker_delete(w);
334         (void)tube_write_msg(ctx->rr_pipe, (uint8_t*)&m, 
335                 (uint32_t)sizeof(m), 0);
336 #ifdef THREADS_DISABLED
337         /* close pipes from forked process before exit */
338         tube_close_read(ctx->qq_pipe);
339         tube_close_write(ctx->rr_pipe);
340 #endif
341         return NULL;
342 }
343
344 int libworker_bg(struct ub_ctx* ctx)
345 {
346         struct libworker* w;
347         /* fork or threadcreate */
348         lock_basic_lock(&ctx->cfglock);
349         if(ctx->dothread) {
350                 lock_basic_unlock(&ctx->cfglock);
351                 w = libworker_setup(ctx, 1);
352                 if(!w) return UB_NOMEM;
353                 w->is_bg_thread = 1;
354 #ifdef ENABLE_LOCK_CHECKS
355                 w->thread_num = 1; /* for nicer DEBUG checklocks */
356 #endif
357                 ub_thread_create(&ctx->bg_tid, libworker_dobg, w);
358         } else {
359                 lock_basic_unlock(&ctx->cfglock);
360 #ifndef HAVE_FORK
361                 /* no fork on windows */
362                 return UB_FORKFAIL;
363 #else /* HAVE_FORK */
364                 switch((ctx->bg_pid=fork())) {
365                         case 0:
366                                 w = libworker_setup(ctx, 1);
367                                 if(!w) fatal_exit("out of memory");
368                                 /* close non-used parts of the pipes */
369                                 tube_close_write(ctx->qq_pipe);
370                                 tube_close_read(ctx->rr_pipe);
371                                 (void)libworker_dobg(w);
372                                 exit(0);
373                                 break;
374                         case -1:
375                                 return UB_FORKFAIL;
376                         default:
377                                 break;
378                 }
379 #endif /* HAVE_FORK */ 
380         }
381         return UB_NOERROR;
382 }
383
384 /** get msg reply struct (in temp region) */
385 static struct reply_info*
386 parse_reply(ldns_buffer* pkt, struct regional* region, struct query_info* qi)
387 {
388         struct reply_info* rep;
389         struct msg_parse* msg;
390         if(!(msg = regional_alloc(region, sizeof(*msg)))) {
391                 return NULL;
392         }
393         memset(msg, 0, sizeof(*msg));
394         ldns_buffer_set_position(pkt, 0);
395         if(parse_packet(pkt, msg, region) != 0)
396                 return 0;
397         if(!parse_create_msg(pkt, msg, NULL, qi, &rep, region)) {
398                 return 0;
399         }
400         return rep;
401 }
402
403 /** insert canonname */
404 static int
405 fill_canon(struct ub_result* res, uint8_t* s)
406 {
407         char buf[255+2];
408         dname_str(s, buf);
409         res->canonname = strdup(buf);
410         return res->canonname != 0;
411 }
412
413 /** fill data into result */
414 static int
415 fill_res(struct ub_result* res, struct ub_packed_rrset_key* answer,
416         uint8_t* finalcname, struct query_info* rq, struct reply_info* rep)
417 {
418         size_t i;
419         struct packed_rrset_data* data;
420         res->ttl = 0;
421         if(!answer) {
422                 if(finalcname) {
423                         if(!fill_canon(res, finalcname))
424                                 return 0; /* out of memory */
425                 }
426                 if(rep->rrset_count != 0)
427                         res->ttl = (int)rep->ttl;
428                 res->data = (char**)calloc(1, sizeof(char*));
429                 res->len = (int*)calloc(1, sizeof(int));
430                 return (res->data && res->len);
431         }
432         data = (struct packed_rrset_data*)answer->entry.data;
433         if(query_dname_compare(rq->qname, answer->rk.dname) != 0) {
434                 if(!fill_canon(res, answer->rk.dname))
435                         return 0; /* out of memory */
436         } else  res->canonname = NULL;
437         res->data = (char**)calloc(data->count+1, sizeof(char*));
438         res->len = (int*)calloc(data->count+1, sizeof(int));
439         if(!res->data || !res->len)
440                 return 0; /* out of memory */
441         for(i=0; i<data->count; i++) {
442                 /* remove rdlength from rdata */
443                 res->len[i] = (int)(data->rr_len[i] - 2);
444                 res->data[i] = memdup(data->rr_data[i]+2, (size_t)res->len[i]);
445                 if(!res->data[i])
446                         return 0; /* out of memory */
447         }
448         /* ttl for positive answers, from CNAME and answer RRs */
449         if(data->count != 0) {
450                 size_t j;
451                 res->ttl = (int)data->ttl;
452                 for(j=0; j<rep->an_numrrsets; j++) {
453                         struct packed_rrset_data* d =
454                                 (struct packed_rrset_data*)rep->rrsets[j]->
455                                 entry.data;
456                         if((int)d->ttl < res->ttl)
457                                 res->ttl = (int)d->ttl;
458                 }
459         }
460         /* ttl for negative answers */
461         if(data->count == 0 && rep->rrset_count != 0)
462                 res->ttl = (int)rep->ttl;
463         res->data[data->count] = NULL;
464         res->len[data->count] = 0;
465         return 1;
466 }
467
468 /** fill result from parsed message, on error fills servfail */
469 void
470 libworker_enter_result(struct ub_result* res, ldns_buffer* buf,
471         struct regional* temp, enum sec_status msg_security)
472 {
473         struct query_info rq;
474         struct reply_info* rep;
475         res->rcode = LDNS_RCODE_SERVFAIL;
476         rep = parse_reply(buf, temp, &rq);
477         if(!rep) {
478                 log_err("cannot parse buf");
479                 return; /* error parsing buf, or out of memory */
480         }
481         if(!fill_res(res, reply_find_answer_rrset(&rq, rep), 
482                 reply_find_final_cname_target(&rq, rep), &rq, rep))
483                 return; /* out of memory */
484         /* rcode, havedata, nxdomain, secure, bogus */
485         res->rcode = (int)FLAGS_GET_RCODE(rep->flags);
486         if(res->data && res->data[0])
487                 res->havedata = 1;
488         if(res->rcode == LDNS_RCODE_NXDOMAIN)
489                 res->nxdomain = 1;
490         if(msg_security == sec_status_secure)
491                 res->secure = 1;
492         if(msg_security == sec_status_bogus)
493                 res->bogus = 1;
494 }
495
496 /** fillup fg results */
497 static void
498 libworker_fillup_fg(struct ctx_query* q, int rcode, ldns_buffer* buf, 
499         enum sec_status s, char* why_bogus)
500 {
501         if(why_bogus)
502                 q->res->why_bogus = strdup(why_bogus);
503         if(rcode != 0) {
504                 q->res->rcode = rcode;
505                 q->msg_security = s;
506                 return;
507         }
508
509         q->res->rcode = LDNS_RCODE_SERVFAIL;
510         q->msg_security = 0;
511         q->msg = memdup(ldns_buffer_begin(buf), ldns_buffer_limit(buf));
512         q->msg_len = ldns_buffer_limit(buf);
513         if(!q->msg) {
514                 return; /* the error is in the rcode */
515         }
516
517         /* canonname and results */
518         q->msg_security = s;
519         libworker_enter_result(q->res, buf, q->w->env->scratch, s);
520 }
521
522 void
523 libworker_fg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s,
524         char* why_bogus)
525 {
526         struct ctx_query* q = (struct ctx_query*)arg;
527         /* fg query is done; exit comm base */
528         comm_base_exit(q->w->base);
529
530         libworker_fillup_fg(q, rcode, buf, s, why_bogus);
531 }
532
533 /** setup qinfo and edns */
534 static int
535 setup_qinfo_edns(struct libworker* w, struct ctx_query* q, 
536         struct query_info* qinfo, struct edns_data* edns)
537 {
538         ldns_rdf* rdf;
539         qinfo->qtype = (uint16_t)q->res->qtype;
540         qinfo->qclass = (uint16_t)q->res->qclass;
541         rdf = ldns_dname_new_frm_str(q->res->qname);
542         if(!rdf) {
543                 return 0;
544         }
545 #ifdef UNBOUND_ALLOC_LITE
546         qinfo->qname = memdup(ldns_rdf_data(rdf), ldns_rdf_size(rdf));
547         qinfo->qname_len = ldns_rdf_size(rdf);
548         ldns_rdf_deep_free(rdf);
549         rdf = 0;
550 #else
551         qinfo->qname = ldns_rdf_data(rdf);
552         qinfo->qname_len = ldns_rdf_size(rdf);
553 #endif
554         edns->edns_present = 1;
555         edns->ext_rcode = 0;
556         edns->edns_version = 0;
557         edns->bits = EDNS_DO;
558         if(ldns_buffer_capacity(w->back->udp_buff) < 65535)
559                 edns->udp_size = (uint16_t)ldns_buffer_capacity(
560                         w->back->udp_buff);
561         else    edns->udp_size = 65535;
562         ldns_rdf_free(rdf);
563         return 1;
564 }
565
566 int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
567 {
568         struct libworker* w = libworker_setup(ctx, 0);
569         uint16_t qflags, qid;
570         struct query_info qinfo;
571         struct edns_data edns;
572         if(!w)
573                 return UB_INITFAIL;
574         if(!setup_qinfo_edns(w, q, &qinfo, &edns)) {
575                 libworker_delete(w);
576                 return UB_SYNTAX;
577         }
578         qid = 0;
579         qflags = BIT_RD;
580         q->w = w;
581         /* see if there is a fixed answer */
582         ldns_buffer_write_u16_at(w->back->udp_buff, 0, qid);
583         ldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags);
584         if(local_zones_answer(ctx->local_zones, &qinfo, &edns, 
585                 w->back->udp_buff, w->env->scratch)) {
586                 regional_free_all(w->env->scratch);
587                 libworker_fillup_fg(q, LDNS_RCODE_NOERROR, 
588                         w->back->udp_buff, sec_status_insecure, NULL);
589                 libworker_delete(w);
590                 free(qinfo.qname);
591                 return UB_NOERROR;
592         }
593         /* process new query */
594         if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, 
595                 w->back->udp_buff, qid, libworker_fg_done_cb, q)) {
596                 free(qinfo.qname);
597                 return UB_NOMEM;
598         }
599         free(qinfo.qname);
600
601         /* wait for reply */
602         comm_base_dispatch(w->base);
603
604         libworker_delete(w);
605         return UB_NOERROR;
606 }
607
608 /** add result to the bg worker result queue */
609 static void
610 add_bg_result(struct libworker* w, struct ctx_query* q, ldns_buffer* pkt, 
611         int err, char* reason)
612 {
613         uint8_t* msg = NULL;
614         uint32_t len = 0;
615
616         /* serialize and delete unneeded q */
617         if(w->is_bg_thread) {
618                 lock_basic_lock(&w->ctx->cfglock);
619                 if(reason)
620                         q->res->why_bogus = strdup(reason);
621                 if(pkt) {
622                         q->msg_len = ldns_buffer_remaining(pkt);
623                         q->msg = memdup(ldns_buffer_begin(pkt), q->msg_len);
624                         if(!q->msg)
625                                 msg = context_serialize_answer(q, UB_NOMEM, 
626                                 NULL, &len);
627                         else    msg = context_serialize_answer(q, err, 
628                                 NULL, &len);
629                 } else msg = context_serialize_answer(q, err, NULL, &len);
630                 lock_basic_unlock(&w->ctx->cfglock);
631         } else {
632                 if(reason)
633                         q->res->why_bogus = strdup(reason);
634                 msg = context_serialize_answer(q, err, pkt, &len);
635                 (void)rbtree_delete(&w->ctx->queries, q->node.key);
636                 w->ctx->num_async--;
637                 context_query_delete(q);
638         }
639
640         if(!msg) {
641                 log_err("out of memory for async answer");
642                 return;
643         }
644         if(!tube_queue_item(w->ctx->rr_pipe, msg, len)) {
645                 log_err("out of memory for async answer");
646                 return;
647         }
648 }
649
650 void
651 libworker_bg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s,
652         char* why_bogus)
653 {
654         struct ctx_query* q = (struct ctx_query*)arg;
655
656         if(q->cancelled) {
657                 if(q->w->is_bg_thread) {
658                         /* delete it now */
659                         struct ub_ctx* ctx = q->w->ctx;
660                         lock_basic_lock(&ctx->cfglock);
661                         (void)rbtree_delete(&ctx->queries, q->node.key);
662                         ctx->num_async--;
663                         context_query_delete(q);
664                         lock_basic_unlock(&ctx->cfglock);
665                 }
666                 /* cancelled, do not give answer */
667                 return;
668         }
669         q->msg_security = s;
670         if(!buf)
671                 buf = q->w->env->scratch_buffer;
672         if(rcode != 0) {
673                 error_encode(buf, rcode, NULL, 0, BIT_RD, NULL);
674         }
675         add_bg_result(q->w, q, buf, UB_NOERROR, why_bogus);
676 }
677
678
679 /** handle new query command for bg worker */
680 static void
681 handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
682 {
683         uint16_t qflags, qid;
684         struct query_info qinfo;
685         struct edns_data edns;
686         struct ctx_query* q;
687         if(w->is_bg_thread) {
688                 lock_basic_lock(&w->ctx->cfglock);
689                 q = context_lookup_new_query(w->ctx, buf, len);
690                 lock_basic_unlock(&w->ctx->cfglock);
691         } else {
692                 q = context_deserialize_new_query(w->ctx, buf, len);
693         }
694         free(buf);
695         if(!q) {
696                 log_err("failed to deserialize newq");
697                 return;
698         }
699         if(!setup_qinfo_edns(w, q, &qinfo, &edns)) {
700                 add_bg_result(w, q, NULL, UB_SYNTAX, NULL);
701                 return;
702         }
703         qid = 0;
704         qflags = BIT_RD;
705         /* see if there is a fixed answer */
706         ldns_buffer_write_u16_at(w->back->udp_buff, 0, qid);
707         ldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags);
708         if(local_zones_answer(w->ctx->local_zones, &qinfo, &edns, 
709                 w->back->udp_buff, w->env->scratch)) {
710                 regional_free_all(w->env->scratch);
711                 q->msg_security = sec_status_insecure;
712                 add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL);
713                 free(qinfo.qname);
714                 return;
715         }
716         q->w = w;
717         /* process new query */
718         if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, 
719                 w->back->udp_buff, qid, libworker_bg_done_cb, q)) {
720                 add_bg_result(w, q, NULL, UB_NOMEM, NULL);
721         }
722         free(qinfo.qname);
723 }
724
725 void libworker_alloc_cleanup(void* arg)
726 {
727         struct libworker* w = (struct libworker*)arg;
728         slabhash_clear(&w->env->rrset_cache->table);
729         slabhash_clear(w->env->msg_cache);
730 }
731
732 struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
733         uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
734         int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
735         uint8_t* zone, size_t zonelen, struct module_qstate* q)
736 {
737         struct libworker* w = (struct libworker*)q->env->worker;
738         struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
739                 q->region, sizeof(*e));
740         if(!e)
741                 return NULL;
742         e->qstate = q;
743         e->qsent = outnet_serviced_query(w->back, qname,
744                 qnamelen, qtype, qclass, flags, dnssec, want_dnssec,
745                 q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr,
746                 addrlen, zone, zonelen, libworker_handle_service_reply, e,
747                 w->back->udp_buff);
748         if(!e->qsent) {
749                 return NULL;
750         }
751         return e;
752 }
753
754 int 
755 libworker_handle_reply(struct comm_point* c, void* arg, int error,
756         struct comm_reply* reply_info)
757 {
758         struct module_qstate* q = (struct module_qstate*)arg;
759         struct libworker* lw = (struct libworker*)q->env->worker;
760         struct outbound_entry e;
761         e.qstate = q;
762         e.qsent = NULL;
763
764         if(error != 0) {
765                 mesh_report_reply(lw->env->mesh, &e, reply_info, error);
766                 return 0;
767         }
768         /* sanity check. */
769         if(!LDNS_QR_WIRE(ldns_buffer_begin(c->buffer))
770                 || LDNS_OPCODE_WIRE(ldns_buffer_begin(c->buffer)) !=
771                         LDNS_PACKET_QUERY
772                 || LDNS_QDCOUNT(ldns_buffer_begin(c->buffer)) > 1) {
773                 /* error becomes timeout for the module as if this reply
774                  * never arrived. */
775                 mesh_report_reply(lw->env->mesh, &e, reply_info, 
776                         NETEVENT_TIMEOUT);
777                 return 0;
778         }
779         mesh_report_reply(lw->env->mesh, &e, reply_info, NETEVENT_NOERROR);
780         return 0;
781 }
782
783 int 
784 libworker_handle_service_reply(struct comm_point* c, void* arg, int error,
785         struct comm_reply* reply_info)
786 {
787         struct outbound_entry* e = (struct outbound_entry*)arg;
788         struct libworker* lw = (struct libworker*)e->qstate->env->worker;
789
790         if(error != 0) {
791                 mesh_report_reply(lw->env->mesh, e, reply_info, error);
792                 return 0;
793         }
794         /* sanity check. */
795         if(!LDNS_QR_WIRE(ldns_buffer_begin(c->buffer))
796                 || LDNS_OPCODE_WIRE(ldns_buffer_begin(c->buffer)) !=
797                         LDNS_PACKET_QUERY
798                 || LDNS_QDCOUNT(ldns_buffer_begin(c->buffer)) > 1) {
799                 /* error becomes timeout for the module as if this reply
800                  * never arrived. */
801                 mesh_report_reply(lw->env->mesh, e, reply_info, 
802                         NETEVENT_TIMEOUT);
803                 return 0;
804         }
805         mesh_report_reply(lw->env->mesh,  e, reply_info, NETEVENT_NOERROR);
806         return 0;
807 }
808
809 /* --- fake callbacks for fptr_wlist to work --- */
810 void worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), 
811         uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len),
812         int ATTR_UNUSED(error), void* ATTR_UNUSED(arg))
813 {
814         log_assert(0);
815 }
816
817 int worker_handle_request(struct comm_point* ATTR_UNUSED(c), 
818         void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
819         struct comm_reply* ATTR_UNUSED(repinfo))
820 {
821         log_assert(0);
822         return 0;
823 }
824
825 int worker_handle_reply(struct comm_point* ATTR_UNUSED(c), 
826         void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
827         struct comm_reply* ATTR_UNUSED(reply_info))
828 {
829         log_assert(0);
830         return 0;
831 }
832
833 int worker_handle_service_reply(struct comm_point* ATTR_UNUSED(c), 
834         void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
835         struct comm_reply* ATTR_UNUSED(reply_info))
836 {
837         log_assert(0);
838         return 0;
839 }
840
841 int remote_accept_callback(struct comm_point* ATTR_UNUSED(c), 
842         void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
843         struct comm_reply* ATTR_UNUSED(repinfo))
844 {
845         log_assert(0);
846         return 0;
847 }
848
849 int remote_control_callback(struct comm_point* ATTR_UNUSED(c), 
850         void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
851         struct comm_reply* ATTR_UNUSED(repinfo))
852 {
853         log_assert(0);
854         return 0;
855 }
856
857 void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg))
858 {
859         log_assert(0);
860 }
861
862 struct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname), 
863         size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype), 
864         uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags), 
865         int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
866         struct sockaddr_storage* ATTR_UNUSED(addr), 
867         socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
868         size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
869 {
870         log_assert(0);
871         return 0;
872 }
873
874 void 
875 worker_alloc_cleanup(void* ATTR_UNUSED(arg))
876 {
877         log_assert(0);
878 }
879
880 void worker_stat_timer_cb(void* ATTR_UNUSED(arg))
881 {
882         log_assert(0);
883 }
884
885 void worker_probe_timer_cb(void* ATTR_UNUSED(arg))
886 {
887         log_assert(0);
888 }
889
890 void worker_start_accept(void* ATTR_UNUSED(arg))
891 {
892         log_assert(0);
893 }
894
895 void worker_stop_accept(void* ATTR_UNUSED(arg))
896 {
897         log_assert(0);
898 }
899
900 int order_lock_cmp(const void* ATTR_UNUSED(e1), const void* ATTR_UNUSED(e2))
901 {
902         log_assert(0);
903         return 0;
904 }
905
906 int
907 codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
908 {
909         log_assert(0);
910         return 0;
911 }
912
913 int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
914 {
915         log_assert(0);
916         return 0;
917 }
918
919 void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg))
920 {
921         log_assert(0);
922 }
923
924 #ifdef UB_ON_WINDOWS
925 void
926 worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void* 
927         ATTR_UNUSED(arg)) {
928         log_assert(0);
929 }
930
931 void
932 wsvc_cron_cb(void* ATTR_UNUSED(arg))
933 {
934         log_assert(0);
935 }
936 #endif /* UB_ON_WINDOWS */