2 * libunbound/worker.c - worker thread or process that resolves
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
6 * This software is open source.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
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.
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.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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.
46 #include <openssl/ssl.h>
48 #include "libunbound/libworker.h"
49 #include "libunbound/context.h"
50 #include "libunbound/unbound.h"
51 #include "libunbound/worker.h"
52 #include "libunbound/unbound-event.h"
53 #include "services/outside_network.h"
54 #include "services/mesh.h"
55 #include "services/localzone.h"
56 #include "services/cache/rrset.h"
57 #include "services/outbound_list.h"
58 #include "util/fptr_wlist.h"
59 #include "util/module.h"
60 #include "util/regional.h"
61 #include "util/random.h"
62 #include "util/config_file.h"
63 #include "util/netevent.h"
64 #include "util/storage/lookup3.h"
65 #include "util/storage/slabhash.h"
66 #include "util/net_help.h"
67 #include "util/data/dname.h"
68 #include "util/data/msgreply.h"
69 #include "util/data/msgencode.h"
70 #include "util/tube.h"
71 #include "iterator/iter_fwd.h"
72 #include "iterator/iter_hints.h"
73 #include "ldns/sbuffer.h"
74 #include "ldns/str2wire.h"
76 /** handle new query command for bg worker */
77 static void handle_newq(struct libworker
* w
, uint8_t* buf
, uint32_t len
);
79 /** delete libworker env */
81 libworker_delete_env(struct libworker
* w
)
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 sldns_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
);
96 SSL_CTX_free(w
->sslctx
);
98 outside_network_delete(w
->back
);
101 /** delete libworker struct */
103 libworker_delete(struct libworker
* w
)
106 libworker_delete_env(w
);
107 comm_base_delete(w
->base
);
112 libworker_delete_event(struct libworker
* w
)
115 libworker_delete_env(w
);
116 comm_base_delete_no_base(w
->base
);
120 /** setup fresh libworker struct */
121 static struct libworker
*
122 libworker_setup(struct ub_ctx
* ctx
, int is_bg
, struct event_base
* eb
)
125 struct libworker
* w
= (struct libworker
*)calloc(1, sizeof(*w
));
126 struct config_file
* cfg
= ctx
->env
->cfg
;
132 w
->env
= (struct module_env
*)malloc(sizeof(*w
->env
));
138 w
->env
->alloc
= context_obtain_alloc(ctx
, !w
->is_bg
|| w
->is_bg_thread
);
143 w
->thread_num
= w
->env
->alloc
->thread_num
;
144 alloc_set_id_cleanup(w
->env
->alloc
, &libworker_alloc_cleanup
, w
);
145 if(!w
->is_bg
|| w
->is_bg_thread
) {
146 lock_basic_lock(&ctx
->cfglock
);
148 w
->env
->scratch
= regional_create_custom(cfg
->msg_buffer_size
);
149 w
->env
->scratch_buffer
= sldns_buffer_new(cfg
->msg_buffer_size
);
150 w
->env
->fwds
= forwards_create();
151 if(w
->env
->fwds
&& !forwards_apply_cfg(w
->env
->fwds
, cfg
)) {
152 forwards_delete(w
->env
->fwds
);
155 w
->env
->hints
= hints_create();
156 if(w
->env
->hints
&& !hints_apply_cfg(w
->env
->hints
, cfg
)) {
157 hints_delete(w
->env
->hints
);
158 w
->env
->hints
= NULL
;
160 if(cfg
->ssl_upstream
) {
161 w
->sslctx
= connect_sslctx_create(NULL
, NULL
, NULL
);
163 /* to make the setup fail after unlock */
164 hints_delete(w
->env
->hints
);
165 w
->env
->hints
= NULL
;
168 if(!w
->is_bg
|| w
->is_bg_thread
) {
169 lock_basic_unlock(&ctx
->cfglock
);
171 if(!w
->env
->scratch
|| !w
->env
->scratch_buffer
|| !w
->env
->fwds
||
176 w
->env
->worker
= (struct worker
*)w
;
177 w
->env
->probe_timer
= NULL
;
178 seed
= (unsigned int)time(NULL
) ^ (unsigned int)getpid() ^
179 (((unsigned int)w
->thread_num
)<<17);
180 seed
^= (unsigned int)w
->env
->alloc
->next_id
;
181 if(!w
->is_bg
|| w
->is_bg_thread
) {
182 lock_basic_lock(&ctx
->cfglock
);
184 if(!(w
->env
->rnd
= ub_initstate(seed
, ctx
->seed_rnd
))) {
185 if(!w
->is_bg
|| w
->is_bg_thread
) {
186 lock_basic_unlock(&ctx
->cfglock
);
192 if(!w
->is_bg
|| w
->is_bg_thread
) {
193 lock_basic_unlock(&ctx
->cfglock
);
196 /* primitive lockout for threading: if it overwrites another
197 * thread it is like wiping the cache (which is likely empty
199 /* note we are holding the ctx lock in normal threaded
200 * cases so that is solved properly, it is only for many ctx
201 * in different threads that this may clash */
202 static int done_raninit
= 0;
205 hash_set_raninit((uint32_t)ub_random(w
->env
->rnd
));
211 w
->base
= comm_base_create_event(eb
);
212 else w
->base
= comm_base_create(0);
217 if(!w
->is_bg
|| w
->is_bg_thread
) {
218 lock_basic_lock(&ctx
->cfglock
);
220 numports
= cfg_condense_ports(cfg
, &ports
);
222 int locked
= !w
->is_bg
|| w
->is_bg_thread
;
225 lock_basic_unlock(&ctx
->cfglock
);
229 w
->back
= outside_network_create(w
->base
, cfg
->msg_buffer_size
,
230 (size_t)cfg
->outgoing_num_ports
, cfg
->out_ifs
,
231 cfg
->num_out_ifs
, cfg
->do_ip4
, cfg
->do_ip6
,
232 cfg
->do_tcp
?cfg
->outgoing_num_tcp
:0,
233 w
->env
->infra_cache
, w
->env
->rnd
, cfg
->use_caps_bits_for_id
,
234 ports
, numports
, cfg
->unwanted_threshold
,
235 &libworker_alloc_cleanup
, w
, cfg
->do_udp
, w
->sslctx
,
236 cfg
->delay_close
, NULL
);
237 if(!w
->is_bg
|| w
->is_bg_thread
) {
238 lock_basic_unlock(&ctx
->cfglock
);
245 w
->env
->mesh
= mesh_create(&ctx
->mods
, w
->env
);
250 w
->env
->send_query
= &libworker_send_query
;
251 w
->env
->detach_subs
= &mesh_detach_subs
;
252 w
->env
->attach_sub
= &mesh_attach_sub
;
253 w
->env
->kill_sub
= &mesh_state_delete
;
254 w
->env
->detect_cycle
= &mesh_detect_cycle
;
255 comm_base_timept(w
->base
, &w
->env
->now
, &w
->env
->now_tv
);
259 struct libworker
* libworker_create_event(struct ub_ctx
* ctx
,
260 struct event_base
* eb
)
262 return libworker_setup(ctx
, 0, eb
);
265 /** handle cancel command for bg worker */
267 handle_cancel(struct libworker
* w
, uint8_t* buf
, uint32_t len
)
270 if(w
->is_bg_thread
) {
271 lock_basic_lock(&w
->ctx
->cfglock
);
272 q
= context_deserialize_cancel(w
->ctx
, buf
, len
);
273 lock_basic_unlock(&w
->ctx
->cfglock
);
275 q
= context_deserialize_cancel(w
->ctx
, buf
, len
);
278 /* probably simply lookup failed, i.e. the message had been
279 * processed and answered before the cancel arrived */
286 /** do control command coming into bg server */
288 libworker_do_cmd(struct libworker
* w
, uint8_t* msg
, uint32_t len
)
290 switch(context_serial_getcmd(msg
, len
)) {
292 case UB_LIBCMD_ANSWER
:
293 log_err("unknown command for bg worker %d",
294 (int)context_serial_getcmd(msg
, len
));
295 /* and fall through to quit */
298 comm_base_exit(w
->base
);
300 case UB_LIBCMD_NEWQUERY
:
301 handle_newq(w
, msg
, len
);
303 case UB_LIBCMD_CANCEL
:
304 handle_cancel(w
, msg
, len
);
309 /** handle control command coming into server */
311 libworker_handle_control_cmd(struct tube
* ATTR_UNUSED(tube
),
312 uint8_t* msg
, size_t len
, int err
, void* arg
)
314 struct libworker
* w
= (struct libworker
*)arg
;
318 /* it is of no use to go on, exit */
319 comm_base_exit(w
->base
);
322 libworker_do_cmd(w
, msg
, len
); /* also frees the buf */
325 /** the background thread func */
327 libworker_dobg(void* arg
)
331 struct libworker
* w
= (struct libworker
*)arg
;
334 log_err("libunbound bg worker init failed, nomem");
338 log_thread_set(&w
->thread_num
);
339 #ifdef THREADS_DISABLED
342 /* close non-used parts of the pipes */
343 tube_close_write(ctx
->qq_pipe
);
344 tube_close_read(ctx
->rr_pipe
);
346 if(!tube_setup_bg_listen(ctx
->qq_pipe
, w
->base
,
347 libworker_handle_control_cmd
, w
)) {
348 log_err("libunbound bg worker init failed, no bglisten");
351 if(!tube_setup_bg_write(ctx
->rr_pipe
, w
->base
)) {
352 log_err("libunbound bg worker init failed, no bgwrite");
357 comm_base_dispatch(w
->base
);
361 tube_remove_bg_listen(w
->ctx
->qq_pipe
);
362 tube_remove_bg_write(w
->ctx
->rr_pipe
);
364 (void)tube_write_msg(ctx
->rr_pipe
, (uint8_t*)&m
,
365 (uint32_t)sizeof(m
), 0);
366 #ifdef THREADS_DISABLED
367 /* close pipes from forked process before exit */
368 tube_close_read(ctx
->qq_pipe
);
369 tube_close_write(ctx
->rr_pipe
);
374 int libworker_bg(struct ub_ctx
* ctx
)
377 /* fork or threadcreate */
378 lock_basic_lock(&ctx
->cfglock
);
380 lock_basic_unlock(&ctx
->cfglock
);
381 w
= libworker_setup(ctx
, 1, NULL
);
382 if(!w
) return UB_NOMEM
;
384 #ifdef ENABLE_LOCK_CHECKS
385 w
->thread_num
= 1; /* for nicer DEBUG checklocks */
387 ub_thread_create(&ctx
->bg_tid
, libworker_dobg
, w
);
389 lock_basic_unlock(&ctx
->cfglock
);
391 /* no fork on windows */
393 #else /* HAVE_FORK */
394 switch((ctx
->bg_pid
=fork())) {
396 w
= libworker_setup(ctx
, 1, NULL
);
397 if(!w
) fatal_exit("out of memory");
398 /* close non-used parts of the pipes */
399 tube_close_write(ctx
->qq_pipe
);
400 tube_close_read(ctx
->rr_pipe
);
401 (void)libworker_dobg(w
);
407 /* close non-used parts, so that the worker
408 * bgprocess gets 'pipe closed' when the
409 * main process exits */
410 tube_close_read(ctx
->qq_pipe
);
411 tube_close_write(ctx
->rr_pipe
);
414 #endif /* HAVE_FORK */
419 /** get msg reply struct (in temp region) */
420 static struct reply_info
*
421 parse_reply(sldns_buffer
* pkt
, struct regional
* region
, struct query_info
* qi
)
423 struct reply_info
* rep
;
424 struct msg_parse
* msg
;
425 if(!(msg
= regional_alloc(region
, sizeof(*msg
)))) {
428 memset(msg
, 0, sizeof(*msg
));
429 sldns_buffer_set_position(pkt
, 0);
430 if(parse_packet(pkt
, msg
, region
) != 0)
432 if(!parse_create_msg(pkt
, msg
, NULL
, qi
, &rep
, region
)) {
438 /** insert canonname */
440 fill_canon(struct ub_result
* res
, uint8_t* s
)
444 res
->canonname
= strdup(buf
);
445 return res
->canonname
!= 0;
448 /** fill data into result */
450 fill_res(struct ub_result
* res
, struct ub_packed_rrset_key
* answer
,
451 uint8_t* finalcname
, struct query_info
* rq
, struct reply_info
* rep
)
454 struct packed_rrset_data
* data
;
458 if(!fill_canon(res
, finalcname
))
459 return 0; /* out of memory */
461 if(rep
->rrset_count
!= 0)
462 res
->ttl
= (int)rep
->ttl
;
463 res
->data
= (char**)calloc(1, sizeof(char*));
464 res
->len
= (int*)calloc(1, sizeof(int));
465 return (res
->data
&& res
->len
);
467 data
= (struct packed_rrset_data
*)answer
->entry
.data
;
468 if(query_dname_compare(rq
->qname
, answer
->rk
.dname
) != 0) {
469 if(!fill_canon(res
, answer
->rk
.dname
))
470 return 0; /* out of memory */
471 } else res
->canonname
= NULL
;
472 res
->data
= (char**)calloc(data
->count
+1, sizeof(char*));
473 res
->len
= (int*)calloc(data
->count
+1, sizeof(int));
474 if(!res
->data
|| !res
->len
)
475 return 0; /* out of memory */
476 for(i
=0; i
<data
->count
; i
++) {
477 /* remove rdlength from rdata */
478 res
->len
[i
] = (int)(data
->rr_len
[i
] - 2);
479 res
->data
[i
] = memdup(data
->rr_data
[i
]+2, (size_t)res
->len
[i
]);
481 return 0; /* out of memory */
483 /* ttl for positive answers, from CNAME and answer RRs */
484 if(data
->count
!= 0) {
486 res
->ttl
= (int)data
->ttl
;
487 for(j
=0; j
<rep
->an_numrrsets
; j
++) {
488 struct packed_rrset_data
* d
=
489 (struct packed_rrset_data
*)rep
->rrsets
[j
]->
491 if((int)d
->ttl
< res
->ttl
)
492 res
->ttl
= (int)d
->ttl
;
495 /* ttl for negative answers */
496 if(data
->count
== 0 && rep
->rrset_count
!= 0)
497 res
->ttl
= (int)rep
->ttl
;
498 res
->data
[data
->count
] = NULL
;
499 res
->len
[data
->count
] = 0;
503 /** fill result from parsed message, on error fills servfail */
505 libworker_enter_result(struct ub_result
* res
, sldns_buffer
* buf
,
506 struct regional
* temp
, enum sec_status msg_security
)
508 struct query_info rq
;
509 struct reply_info
* rep
;
510 res
->rcode
= LDNS_RCODE_SERVFAIL
;
511 rep
= parse_reply(buf
, temp
, &rq
);
513 log_err("cannot parse buf");
514 return; /* error parsing buf, or out of memory */
516 if(!fill_res(res
, reply_find_answer_rrset(&rq
, rep
),
517 reply_find_final_cname_target(&rq
, rep
), &rq
, rep
))
518 return; /* out of memory */
519 /* rcode, havedata, nxdomain, secure, bogus */
520 res
->rcode
= (int)FLAGS_GET_RCODE(rep
->flags
);
521 if(res
->data
&& res
->data
[0])
523 if(res
->rcode
== LDNS_RCODE_NXDOMAIN
)
525 if(msg_security
== sec_status_secure
)
527 if(msg_security
== sec_status_bogus
)
531 /** fillup fg results */
533 libworker_fillup_fg(struct ctx_query
* q
, int rcode
, sldns_buffer
* buf
,
534 enum sec_status s
, char* why_bogus
)
537 q
->res
->why_bogus
= strdup(why_bogus
);
539 q
->res
->rcode
= rcode
;
544 q
->res
->rcode
= LDNS_RCODE_SERVFAIL
;
546 q
->msg
= memdup(sldns_buffer_begin(buf
), sldns_buffer_limit(buf
));
547 q
->msg_len
= sldns_buffer_limit(buf
);
549 return; /* the error is in the rcode */
552 /* canonname and results */
554 libworker_enter_result(q
->res
, buf
, q
->w
->env
->scratch
, s
);
558 libworker_fg_done_cb(void* arg
, int rcode
, sldns_buffer
* buf
, enum sec_status s
,
561 struct ctx_query
* q
= (struct ctx_query
*)arg
;
562 /* fg query is done; exit comm base */
563 comm_base_exit(q
->w
->base
);
565 libworker_fillup_fg(q
, rcode
, buf
, s
, why_bogus
);
568 /** setup qinfo and edns */
570 setup_qinfo_edns(struct libworker
* w
, struct ctx_query
* q
,
571 struct query_info
* qinfo
, struct edns_data
* edns
)
573 qinfo
->qtype
= (uint16_t)q
->res
->qtype
;
574 qinfo
->qclass
= (uint16_t)q
->res
->qclass
;
575 qinfo
->qname
= sldns_str2wire_dname(q
->res
->qname
, &qinfo
->qname_len
);
579 edns
->edns_present
= 1;
581 edns
->edns_version
= 0;
582 edns
->bits
= EDNS_DO
;
583 if(sldns_buffer_capacity(w
->back
->udp_buff
) < 65535)
584 edns
->udp_size
= (uint16_t)sldns_buffer_capacity(
586 else edns
->udp_size
= 65535;
590 int libworker_fg(struct ub_ctx
* ctx
, struct ctx_query
* q
)
592 struct libworker
* w
= libworker_setup(ctx
, 0, NULL
);
593 uint16_t qflags
, qid
;
594 struct query_info qinfo
;
595 struct edns_data edns
;
598 if(!setup_qinfo_edns(w
, q
, &qinfo
, &edns
)) {
605 /* see if there is a fixed answer */
606 sldns_buffer_write_u16_at(w
->back
->udp_buff
, 0, qid
);
607 sldns_buffer_write_u16_at(w
->back
->udp_buff
, 2, qflags
);
608 if(local_zones_answer(ctx
->local_zones
, &qinfo
, &edns
,
609 w
->back
->udp_buff
, w
->env
->scratch
)) {
610 regional_free_all(w
->env
->scratch
);
611 libworker_fillup_fg(q
, LDNS_RCODE_NOERROR
,
612 w
->back
->udp_buff
, sec_status_insecure
, NULL
);
617 /* process new query */
618 if(!mesh_new_callback(w
->env
->mesh
, &qinfo
, qflags
, &edns
,
619 w
->back
->udp_buff
, qid
, libworker_fg_done_cb
, q
)) {
626 comm_base_dispatch(w
->base
);
633 libworker_event_done_cb(void* arg
, int rcode
, sldns_buffer
* buf
,
634 enum sec_status s
, char* why_bogus
)
636 struct ctx_query
* q
= (struct ctx_query
*)arg
;
637 ub_event_callback_t cb
= (ub_event_callback_t
)q
->cb
;
638 void* cb_arg
= q
->cb_arg
;
639 int cancelled
= q
->cancelled
;
642 struct ub_ctx
* ctx
= q
->w
->ctx
;
643 lock_basic_lock(&ctx
->cfglock
);
644 (void)rbtree_delete(&ctx
->queries
, q
->node
.key
);
646 context_query_delete(q
);
647 lock_basic_unlock(&ctx
->cfglock
);
652 if(s
== sec_status_bogus
)
654 else if(s
== sec_status_secure
)
656 (*cb
)(cb_arg
, rcode
, (void*)sldns_buffer_begin(buf
),
657 (int)sldns_buffer_limit(buf
), sec
, why_bogus
);
661 int libworker_attach_mesh(struct ub_ctx
* ctx
, struct ctx_query
* q
,
664 struct libworker
* w
= ctx
->event_worker
;
665 uint16_t qflags
, qid
;
666 struct query_info qinfo
;
667 struct edns_data edns
;
670 if(!setup_qinfo_edns(w
, q
, &qinfo
, &edns
))
675 /* see if there is a fixed answer */
676 sldns_buffer_write_u16_at(w
->back
->udp_buff
, 0, qid
);
677 sldns_buffer_write_u16_at(w
->back
->udp_buff
, 2, qflags
);
678 if(local_zones_answer(ctx
->local_zones
, &qinfo
, &edns
,
679 w
->back
->udp_buff
, w
->env
->scratch
)) {
680 regional_free_all(w
->env
->scratch
);
682 libworker_event_done_cb(q
, LDNS_RCODE_NOERROR
,
683 w
->back
->udp_buff
, sec_status_insecure
, NULL
);
686 /* process new query */
688 *async_id
= q
->querynum
;
689 if(!mesh_new_callback(w
->env
->mesh
, &qinfo
, qflags
, &edns
,
690 w
->back
->udp_buff
, qid
, libworker_event_done_cb
, q
)) {
698 /** add result to the bg worker result queue */
700 add_bg_result(struct libworker
* w
, struct ctx_query
* q
, sldns_buffer
* pkt
,
701 int err
, char* reason
)
706 /* serialize and delete unneeded q */
707 if(w
->is_bg_thread
) {
708 lock_basic_lock(&w
->ctx
->cfglock
);
710 q
->res
->why_bogus
= strdup(reason
);
712 q
->msg_len
= sldns_buffer_remaining(pkt
);
713 q
->msg
= memdup(sldns_buffer_begin(pkt
), q
->msg_len
);
715 msg
= context_serialize_answer(q
, UB_NOMEM
,
717 else msg
= context_serialize_answer(q
, err
,
719 } else msg
= context_serialize_answer(q
, err
, NULL
, &len
);
720 lock_basic_unlock(&w
->ctx
->cfglock
);
723 q
->res
->why_bogus
= strdup(reason
);
724 msg
= context_serialize_answer(q
, err
, pkt
, &len
);
725 (void)rbtree_delete(&w
->ctx
->queries
, q
->node
.key
);
727 context_query_delete(q
);
731 log_err("out of memory for async answer");
734 if(!tube_queue_item(w
->ctx
->rr_pipe
, msg
, len
)) {
735 log_err("out of memory for async answer");
741 libworker_bg_done_cb(void* arg
, int rcode
, sldns_buffer
* buf
, enum sec_status s
,
744 struct ctx_query
* q
= (struct ctx_query
*)arg
;
747 if(q
->w
->is_bg_thread
) {
749 struct ub_ctx
* ctx
= q
->w
->ctx
;
750 lock_basic_lock(&ctx
->cfglock
);
751 (void)rbtree_delete(&ctx
->queries
, q
->node
.key
);
753 context_query_delete(q
);
754 lock_basic_unlock(&ctx
->cfglock
);
756 /* cancelled, do not give answer */
761 buf
= q
->w
->env
->scratch_buffer
;
763 error_encode(buf
, rcode
, NULL
, 0, BIT_RD
, NULL
);
765 add_bg_result(q
->w
, q
, buf
, UB_NOERROR
, why_bogus
);
769 /** handle new query command for bg worker */
771 handle_newq(struct libworker
* w
, uint8_t* buf
, uint32_t len
)
773 uint16_t qflags
, qid
;
774 struct query_info qinfo
;
775 struct edns_data edns
;
777 if(w
->is_bg_thread
) {
778 lock_basic_lock(&w
->ctx
->cfglock
);
779 q
= context_lookup_new_query(w
->ctx
, buf
, len
);
780 lock_basic_unlock(&w
->ctx
->cfglock
);
782 q
= context_deserialize_new_query(w
->ctx
, buf
, len
);
786 log_err("failed to deserialize newq");
789 if(!setup_qinfo_edns(w
, q
, &qinfo
, &edns
)) {
790 add_bg_result(w
, q
, NULL
, UB_SYNTAX
, NULL
);
795 /* see if there is a fixed answer */
796 sldns_buffer_write_u16_at(w
->back
->udp_buff
, 0, qid
);
797 sldns_buffer_write_u16_at(w
->back
->udp_buff
, 2, qflags
);
798 if(local_zones_answer(w
->ctx
->local_zones
, &qinfo
, &edns
,
799 w
->back
->udp_buff
, w
->env
->scratch
)) {
800 regional_free_all(w
->env
->scratch
);
801 q
->msg_security
= sec_status_insecure
;
802 add_bg_result(w
, q
, w
->back
->udp_buff
, UB_NOERROR
, NULL
);
807 /* process new query */
808 if(!mesh_new_callback(w
->env
->mesh
, &qinfo
, qflags
, &edns
,
809 w
->back
->udp_buff
, qid
, libworker_bg_done_cb
, q
)) {
810 add_bg_result(w
, q
, NULL
, UB_NOMEM
, NULL
);
815 void libworker_alloc_cleanup(void* arg
)
817 struct libworker
* w
= (struct libworker
*)arg
;
818 slabhash_clear(&w
->env
->rrset_cache
->table
);
819 slabhash_clear(w
->env
->msg_cache
);
822 struct outbound_entry
* libworker_send_query(uint8_t* qname
, size_t qnamelen
,
823 uint16_t qtype
, uint16_t qclass
, uint16_t flags
, int dnssec
,
824 int want_dnssec
, int nocaps
, struct sockaddr_storage
* addr
,
825 socklen_t addrlen
, uint8_t* zone
, size_t zonelen
,
826 struct module_qstate
* q
)
828 struct libworker
* w
= (struct libworker
*)q
->env
->worker
;
829 struct outbound_entry
* e
= (struct outbound_entry
*)regional_alloc(
830 q
->region
, sizeof(*e
));
834 e
->qsent
= outnet_serviced_query(w
->back
, qname
,
835 qnamelen
, qtype
, qclass
, flags
, dnssec
, want_dnssec
, nocaps
,
836 q
->env
->cfg
->tcp_upstream
, q
->env
->cfg
->ssl_upstream
, addr
,
837 addrlen
, zone
, zonelen
, libworker_handle_service_reply
, e
,
846 libworker_handle_reply(struct comm_point
* c
, void* arg
, int error
,
847 struct comm_reply
* reply_info
)
849 struct module_qstate
* q
= (struct module_qstate
*)arg
;
850 struct libworker
* lw
= (struct libworker
*)q
->env
->worker
;
851 struct outbound_entry e
;
856 mesh_report_reply(lw
->env
->mesh
, &e
, reply_info
, error
);
860 if(!LDNS_QR_WIRE(sldns_buffer_begin(c
->buffer
))
861 || LDNS_OPCODE_WIRE(sldns_buffer_begin(c
->buffer
)) !=
863 || LDNS_QDCOUNT(sldns_buffer_begin(c
->buffer
)) > 1) {
864 /* error becomes timeout for the module as if this reply
866 mesh_report_reply(lw
->env
->mesh
, &e
, reply_info
,
870 mesh_report_reply(lw
->env
->mesh
, &e
, reply_info
, NETEVENT_NOERROR
);
875 libworker_handle_service_reply(struct comm_point
* c
, void* arg
, int error
,
876 struct comm_reply
* reply_info
)
878 struct outbound_entry
* e
= (struct outbound_entry
*)arg
;
879 struct libworker
* lw
= (struct libworker
*)e
->qstate
->env
->worker
;
882 mesh_report_reply(lw
->env
->mesh
, e
, reply_info
, error
);
886 if(!LDNS_QR_WIRE(sldns_buffer_begin(c
->buffer
))
887 || LDNS_OPCODE_WIRE(sldns_buffer_begin(c
->buffer
)) !=
889 || LDNS_QDCOUNT(sldns_buffer_begin(c
->buffer
)) > 1) {
890 /* error becomes timeout for the module as if this reply
892 mesh_report_reply(lw
->env
->mesh
, e
, reply_info
,
896 mesh_report_reply(lw
->env
->mesh
, e
, reply_info
, NETEVENT_NOERROR
);
900 /* --- fake callbacks for fptr_wlist to work --- */
901 void worker_handle_control_cmd(struct tube
* ATTR_UNUSED(tube
),
902 uint8_t* ATTR_UNUSED(buffer
), size_t ATTR_UNUSED(len
),
903 int ATTR_UNUSED(error
), void* ATTR_UNUSED(arg
))
908 int worker_handle_request(struct comm_point
* ATTR_UNUSED(c
),
909 void* ATTR_UNUSED(arg
), int ATTR_UNUSED(error
),
910 struct comm_reply
* ATTR_UNUSED(repinfo
))
916 int worker_handle_reply(struct comm_point
* ATTR_UNUSED(c
),
917 void* ATTR_UNUSED(arg
), int ATTR_UNUSED(error
),
918 struct comm_reply
* ATTR_UNUSED(reply_info
))
924 int worker_handle_service_reply(struct comm_point
* ATTR_UNUSED(c
),
925 void* ATTR_UNUSED(arg
), int ATTR_UNUSED(error
),
926 struct comm_reply
* ATTR_UNUSED(reply_info
))
932 int remote_accept_callback(struct comm_point
* ATTR_UNUSED(c
),
933 void* ATTR_UNUSED(arg
), int ATTR_UNUSED(error
),
934 struct comm_reply
* ATTR_UNUSED(repinfo
))
940 int remote_control_callback(struct comm_point
* ATTR_UNUSED(c
),
941 void* ATTR_UNUSED(arg
), int ATTR_UNUSED(error
),
942 struct comm_reply
* ATTR_UNUSED(repinfo
))
948 void worker_sighandler(int ATTR_UNUSED(sig
), void* ATTR_UNUSED(arg
))
953 struct outbound_entry
* worker_send_query(uint8_t* ATTR_UNUSED(qname
),
954 size_t ATTR_UNUSED(qnamelen
), uint16_t ATTR_UNUSED(qtype
),
955 uint16_t ATTR_UNUSED(qclass
), uint16_t ATTR_UNUSED(flags
),
956 int ATTR_UNUSED(dnssec
), int ATTR_UNUSED(want_dnssec
),
957 int ATTR_UNUSED(nocaps
), struct sockaddr_storage
* ATTR_UNUSED(addr
),
958 socklen_t
ATTR_UNUSED(addrlen
), uint8_t* ATTR_UNUSED(zone
),
959 size_t ATTR_UNUSED(zonelen
), struct module_qstate
* ATTR_UNUSED(q
))
966 worker_alloc_cleanup(void* ATTR_UNUSED(arg
))
971 void worker_stat_timer_cb(void* ATTR_UNUSED(arg
))
976 void worker_probe_timer_cb(void* ATTR_UNUSED(arg
))
981 void worker_start_accept(void* ATTR_UNUSED(arg
))
986 void worker_stop_accept(void* ATTR_UNUSED(arg
))
991 int order_lock_cmp(const void* ATTR_UNUSED(e1
), const void* ATTR_UNUSED(e2
))
998 codeline_cmp(const void* ATTR_UNUSED(a
), const void* ATTR_UNUSED(b
))
1004 int replay_var_compare(const void* ATTR_UNUSED(a
), const void* ATTR_UNUSED(b
))
1010 void remote_get_opt_ssl(char* ATTR_UNUSED(str
), void* ATTR_UNUSED(arg
))
1015 #ifdef UB_ON_WINDOWS
1017 worker_win_stop_cb(int ATTR_UNUSED(fd
), short ATTR_UNUSED(ev
), void*
1023 wsvc_cron_cb(void* ATTR_UNUSED(arg
))
1027 #endif /* UB_ON_WINDOWS */