1933707f3Ssthen /* 2933707f3Ssthen * libunbound/worker.c - worker thread or process that resolves 3933707f3Ssthen * 4933707f3Ssthen * Copyright (c) 2007, NLnet Labs. All rights reserved. 5933707f3Ssthen * 6933707f3Ssthen * This software is open source. 7933707f3Ssthen * 8933707f3Ssthen * Redistribution and use in source and binary forms, with or without 9933707f3Ssthen * modification, are permitted provided that the following conditions 10933707f3Ssthen * are met: 11933707f3Ssthen * 12933707f3Ssthen * Redistributions of source code must retain the above copyright notice, 13933707f3Ssthen * this list of conditions and the following disclaimer. 14933707f3Ssthen * 15933707f3Ssthen * Redistributions in binary form must reproduce the above copyright notice, 16933707f3Ssthen * this list of conditions and the following disclaimer in the documentation 17933707f3Ssthen * and/or other materials provided with the distribution. 18933707f3Ssthen * 19933707f3Ssthen * Neither the name of the NLNET LABS nor the names of its contributors may 20933707f3Ssthen * be used to endorse or promote products derived from this software without 21933707f3Ssthen * specific prior written permission. 22933707f3Ssthen * 23933707f3Ssthen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 240b68ff31Ssthen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 250b68ff31Ssthen * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 260b68ff31Ssthen * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 270b68ff31Ssthen * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 280b68ff31Ssthen * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 290b68ff31Ssthen * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 300b68ff31Ssthen * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 310b68ff31Ssthen * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 320b68ff31Ssthen * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 330b68ff31Ssthen * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34933707f3Ssthen */ 35933707f3Ssthen 36933707f3Ssthen /** 37933707f3Ssthen * \file 38933707f3Ssthen * 39933707f3Ssthen * This file contains the worker process or thread that performs 40933707f3Ssthen * the DNS resolving and validation. The worker is called by a procedure 41933707f3Ssthen * and if in the background continues until exit, if in the foreground 42933707f3Ssthen * returns from the procedure when done. 43933707f3Ssthen */ 44933707f3Ssthen #include "config.h" 45e9c7b4efSsthen #ifdef HAVE_SSL 46933707f3Ssthen #include <openssl/ssl.h> 47e9c7b4efSsthen #endif 48933707f3Ssthen #include "libunbound/libworker.h" 49933707f3Ssthen #include "libunbound/context.h" 50933707f3Ssthen #include "libunbound/unbound.h" 51e10d3884Sbrad #include "libunbound/worker.h" 520b68ff31Ssthen #include "libunbound/unbound-event.h" 53933707f3Ssthen #include "services/outside_network.h" 54933707f3Ssthen #include "services/mesh.h" 55933707f3Ssthen #include "services/localzone.h" 56933707f3Ssthen #include "services/cache/rrset.h" 57933707f3Ssthen #include "services/outbound_list.h" 58938a3a5eSflorian #include "services/authzone.h" 59e10d3884Sbrad #include "util/fptr_wlist.h" 60933707f3Ssthen #include "util/module.h" 61933707f3Ssthen #include "util/regional.h" 62933707f3Ssthen #include "util/random.h" 63933707f3Ssthen #include "util/config_file.h" 64933707f3Ssthen #include "util/netevent.h" 65d896b962Ssthen #include "util/proxy_protocol.h" 66933707f3Ssthen #include "util/storage/lookup3.h" 67933707f3Ssthen #include "util/storage/slabhash.h" 68933707f3Ssthen #include "util/net_help.h" 69933707f3Ssthen #include "util/data/dname.h" 70933707f3Ssthen #include "util/data/msgreply.h" 71933707f3Ssthen #include "util/data/msgencode.h" 72933707f3Ssthen #include "util/tube.h" 73a58bff56Ssthen #include "sldns/sbuffer.h" 74a58bff56Ssthen #include "sldns/str2wire.h" 759982a05dSsthen #ifdef USE_DNSTAP 769982a05dSsthen #include "dnstap/dtstream.h" 779982a05dSsthen #endif 78933707f3Ssthen 79a3167c07Ssthen #ifdef HAVE_TARGETCONDITIONALS_H 80a3167c07Ssthen #include <TargetConditionals.h> 81a3167c07Ssthen #endif 82a3167c07Ssthen 832c144df0Ssthen #if (defined(TARGET_OS_TV) && TARGET_OS_TV) || (defined(TARGET_OS_WATCH) && TARGET_OS_WATCH) 84a3167c07Ssthen #undef HAVE_FORK 85a3167c07Ssthen #endif 86a3167c07Ssthen 87933707f3Ssthen /** handle new query command for bg worker */ 88933707f3Ssthen static void handle_newq(struct libworker* w, uint8_t* buf, uint32_t len); 89933707f3Ssthen 900b68ff31Ssthen /** delete libworker env */ 91933707f3Ssthen static void 920b68ff31Ssthen libworker_delete_env(struct libworker* w) 93933707f3Ssthen { 94933707f3Ssthen if(w->env) { 95933707f3Ssthen outside_network_quit_prepare(w->back); 96933707f3Ssthen mesh_delete(w->env->mesh); 97933707f3Ssthen context_release_alloc(w->ctx, w->env->alloc, 98933707f3Ssthen !w->is_bg || w->is_bg_thread); 990b68ff31Ssthen sldns_buffer_free(w->env->scratch_buffer); 100933707f3Ssthen regional_destroy(w->env->scratch); 101933707f3Ssthen ub_randfree(w->env->rnd); 102933707f3Ssthen free(w->env); 103933707f3Ssthen } 104e9c7b4efSsthen #ifdef HAVE_SSL 105933707f3Ssthen SSL_CTX_free(w->sslctx); 106e9c7b4efSsthen #endif 107933707f3Ssthen outside_network_delete(w->back); 1080b68ff31Ssthen } 1090b68ff31Ssthen 1100b68ff31Ssthen /** delete libworker struct */ 1110b68ff31Ssthen static void 1120b68ff31Ssthen libworker_delete(struct libworker* w) 1130b68ff31Ssthen { 1140b68ff31Ssthen if(!w) return; 1150b68ff31Ssthen libworker_delete_env(w); 116933707f3Ssthen comm_base_delete(w->base); 117933707f3Ssthen free(w); 118933707f3Ssthen } 119933707f3Ssthen 1200b68ff31Ssthen void 1210b68ff31Ssthen libworker_delete_event(struct libworker* w) 1220b68ff31Ssthen { 1230b68ff31Ssthen if(!w) return; 1240b68ff31Ssthen libworker_delete_env(w); 1250b68ff31Ssthen comm_base_delete_no_base(w->base); 1260b68ff31Ssthen free(w); 1270b68ff31Ssthen } 1280b68ff31Ssthen 129933707f3Ssthen /** setup fresh libworker struct */ 130933707f3Ssthen static struct libworker* 1312ee382b6Ssthen libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb) 132933707f3Ssthen { 133933707f3Ssthen struct libworker* w = (struct libworker*)calloc(1, sizeof(*w)); 134933707f3Ssthen struct config_file* cfg = ctx->env->cfg; 135933707f3Ssthen int* ports; 136933707f3Ssthen int numports; 137933707f3Ssthen if(!w) return NULL; 138933707f3Ssthen w->is_bg = is_bg; 139933707f3Ssthen w->ctx = ctx; 140933707f3Ssthen w->env = (struct module_env*)malloc(sizeof(*w->env)); 141933707f3Ssthen if(!w->env) { 142933707f3Ssthen free(w); 143933707f3Ssthen return NULL; 144933707f3Ssthen } 145933707f3Ssthen *w->env = *ctx->env; 146933707f3Ssthen w->env->alloc = context_obtain_alloc(ctx, !w->is_bg || w->is_bg_thread); 147933707f3Ssthen if(!w->env->alloc) { 148933707f3Ssthen libworker_delete(w); 149933707f3Ssthen return NULL; 150933707f3Ssthen } 151933707f3Ssthen w->thread_num = w->env->alloc->thread_num; 152933707f3Ssthen alloc_set_id_cleanup(w->env->alloc, &libworker_alloc_cleanup, w); 153933707f3Ssthen if(!w->is_bg || w->is_bg_thread) { 154933707f3Ssthen lock_basic_lock(&ctx->cfglock); 155933707f3Ssthen } 156933707f3Ssthen w->env->scratch = regional_create_custom(cfg->msg_buffer_size); 1570b68ff31Ssthen w->env->scratch_buffer = sldns_buffer_new(cfg->msg_buffer_size); 158d896b962Ssthen #ifdef HAVE_SSL 159938a3a5eSflorian w->sslctx = connect_sslctx_create(NULL, NULL, 16020237c55Ssthen cfg->tls_cert_bundle, cfg->tls_win_cert); 161933707f3Ssthen if(!w->sslctx) { 162163a4143Ssthen /* to make the setup fail after unlock */ 1632bdc0ed1Ssthen sldns_buffer_free(w->env->scratch_buffer); 1642bdc0ed1Ssthen w->env->scratch_buffer = NULL; 165933707f3Ssthen } 166d896b962Ssthen #endif 167933707f3Ssthen if(!w->is_bg || w->is_bg_thread) { 168933707f3Ssthen lock_basic_unlock(&ctx->cfglock); 169933707f3Ssthen } 1702bdc0ed1Ssthen if(!w->env->scratch || !w->env->scratch_buffer) { 171933707f3Ssthen libworker_delete(w); 172933707f3Ssthen return NULL; 173933707f3Ssthen } 174933707f3Ssthen w->env->worker = (struct worker*)w; 175933707f3Ssthen w->env->probe_timer = NULL; 176933707f3Ssthen if(!w->is_bg || w->is_bg_thread) { 177933707f3Ssthen lock_basic_lock(&ctx->cfglock); 178933707f3Ssthen } 179ebf5bb73Ssthen if(!(w->env->rnd = ub_initstate(ctx->seed_rnd))) { 180933707f3Ssthen if(!w->is_bg || w->is_bg_thread) { 181933707f3Ssthen lock_basic_unlock(&ctx->cfglock); 182933707f3Ssthen } 183933707f3Ssthen libworker_delete(w); 184933707f3Ssthen return NULL; 185933707f3Ssthen } 186933707f3Ssthen if(!w->is_bg || w->is_bg_thread) { 187933707f3Ssthen lock_basic_unlock(&ctx->cfglock); 188933707f3Ssthen } 189933707f3Ssthen if(1) { 190933707f3Ssthen /* primitive lockout for threading: if it overwrites another 191933707f3Ssthen * thread it is like wiping the cache (which is likely empty 192933707f3Ssthen * at the start) */ 193933707f3Ssthen /* note we are holding the ctx lock in normal threaded 194933707f3Ssthen * cases so that is solved properly, it is only for many ctx 195933707f3Ssthen * in different threads that this may clash */ 196933707f3Ssthen static int done_raninit = 0; 197933707f3Ssthen if(!done_raninit) { 198933707f3Ssthen done_raninit = 1; 199933707f3Ssthen hash_set_raninit((uint32_t)ub_random(w->env->rnd)); 200933707f3Ssthen } 201933707f3Ssthen } 202933707f3Ssthen 2030b68ff31Ssthen if(eb) 2040b68ff31Ssthen w->base = comm_base_create_event(eb); 2050b68ff31Ssthen else w->base = comm_base_create(0); 206933707f3Ssthen if(!w->base) { 207933707f3Ssthen libworker_delete(w); 208933707f3Ssthen return NULL; 209933707f3Ssthen } 210bdfc4d55Sflorian w->env->worker_base = w->base; 211933707f3Ssthen if(!w->is_bg || w->is_bg_thread) { 212933707f3Ssthen lock_basic_lock(&ctx->cfglock); 213933707f3Ssthen } 214933707f3Ssthen numports = cfg_condense_ports(cfg, &ports); 215933707f3Ssthen if(numports == 0) { 216c3b38330Ssthen if(!w->is_bg || w->is_bg_thread) { 217e9c7b4efSsthen lock_basic_unlock(&ctx->cfglock); 2180b68ff31Ssthen } 219c3b38330Ssthen libworker_delete(w); 220933707f3Ssthen return NULL; 221933707f3Ssthen } 222933707f3Ssthen w->back = outside_network_create(w->base, cfg->msg_buffer_size, 223933707f3Ssthen (size_t)cfg->outgoing_num_ports, cfg->out_ifs, 224933707f3Ssthen cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6, 225a3167c07Ssthen cfg->do_tcp?cfg->outgoing_num_tcp:0, cfg->ip_dscp, 226933707f3Ssthen w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id, 227933707f3Ssthen ports, numports, cfg->unwanted_threshold, 228bdfc4d55Sflorian cfg->outgoing_tcp_mss, &libworker_alloc_cleanup, w, 229bdfc4d55Sflorian cfg->do_udp || cfg->udp_upstream_without_downstream, w->sslctx, 230191f22c6Ssthen cfg->delay_close, cfg->tls_use_sni, NULL, cfg->udp_connect, 231191f22c6Ssthen cfg->max_reuse_tcp_queries, cfg->tcp_reuse_timeout, 232191f22c6Ssthen cfg->tcp_auth_query_timeout); 233bdfc4d55Sflorian w->env->outnet = w->back; 234933707f3Ssthen if(!w->is_bg || w->is_bg_thread) { 235933707f3Ssthen lock_basic_unlock(&ctx->cfglock); 236933707f3Ssthen } 237933707f3Ssthen free(ports); 238933707f3Ssthen if(!w->back) { 239933707f3Ssthen libworker_delete(w); 240933707f3Ssthen return NULL; 241933707f3Ssthen } 242933707f3Ssthen w->env->mesh = mesh_create(&ctx->mods, w->env); 243933707f3Ssthen if(!w->env->mesh) { 244933707f3Ssthen libworker_delete(w); 245933707f3Ssthen return NULL; 246933707f3Ssthen } 247933707f3Ssthen w->env->send_query = &libworker_send_query; 248933707f3Ssthen w->env->detach_subs = &mesh_detach_subs; 249933707f3Ssthen w->env->attach_sub = &mesh_attach_sub; 250bdfc4d55Sflorian w->env->add_sub = &mesh_add_sub; 251933707f3Ssthen w->env->kill_sub = &mesh_state_delete; 252933707f3Ssthen w->env->detect_cycle = &mesh_detect_cycle; 253933707f3Ssthen comm_base_timept(w->base, &w->env->now, &w->env->now_tv); 254d896b962Ssthen pp_init(&sldns_write_uint16, &sldns_write_uint32); 255933707f3Ssthen return w; 256933707f3Ssthen } 257933707f3Ssthen 2580b68ff31Ssthen struct libworker* libworker_create_event(struct ub_ctx* ctx, 2592ee382b6Ssthen struct ub_event_base* eb) 2600b68ff31Ssthen { 2610b68ff31Ssthen return libworker_setup(ctx, 0, eb); 2620b68ff31Ssthen } 2630b68ff31Ssthen 264933707f3Ssthen /** handle cancel command for bg worker */ 265933707f3Ssthen static void 266933707f3Ssthen handle_cancel(struct libworker* w, uint8_t* buf, uint32_t len) 267933707f3Ssthen { 268933707f3Ssthen struct ctx_query* q; 269933707f3Ssthen if(w->is_bg_thread) { 270933707f3Ssthen lock_basic_lock(&w->ctx->cfglock); 271933707f3Ssthen q = context_deserialize_cancel(w->ctx, buf, len); 272933707f3Ssthen lock_basic_unlock(&w->ctx->cfglock); 273933707f3Ssthen } else { 274933707f3Ssthen q = context_deserialize_cancel(w->ctx, buf, len); 275933707f3Ssthen } 276933707f3Ssthen if(!q) { 277933707f3Ssthen /* probably simply lookup failed, i.e. the message had been 278933707f3Ssthen * processed and answered before the cancel arrived */ 279933707f3Ssthen return; 280933707f3Ssthen } 281933707f3Ssthen q->cancelled = 1; 282933707f3Ssthen free(buf); 283933707f3Ssthen } 284933707f3Ssthen 285933707f3Ssthen /** do control command coming into bg server */ 286933707f3Ssthen static void 287933707f3Ssthen libworker_do_cmd(struct libworker* w, uint8_t* msg, uint32_t len) 288933707f3Ssthen { 289933707f3Ssthen switch(context_serial_getcmd(msg, len)) { 290933707f3Ssthen default: 291933707f3Ssthen case UB_LIBCMD_ANSWER: 292933707f3Ssthen log_err("unknown command for bg worker %d", 293933707f3Ssthen (int)context_serial_getcmd(msg, len)); 294933707f3Ssthen /* and fall through to quit */ 295*98bc733bSsthen ATTR_FALLTHROUGH 2967191de28Ssthen /* fallthrough */ 297933707f3Ssthen case UB_LIBCMD_QUIT: 298933707f3Ssthen free(msg); 299933707f3Ssthen comm_base_exit(w->base); 300933707f3Ssthen break; 301933707f3Ssthen case UB_LIBCMD_NEWQUERY: 302933707f3Ssthen handle_newq(w, msg, len); 303933707f3Ssthen break; 304933707f3Ssthen case UB_LIBCMD_CANCEL: 305933707f3Ssthen handle_cancel(w, msg, len); 306933707f3Ssthen break; 307933707f3Ssthen } 308933707f3Ssthen } 309933707f3Ssthen 310933707f3Ssthen /** handle control command coming into server */ 311933707f3Ssthen void 312933707f3Ssthen libworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), 313933707f3Ssthen uint8_t* msg, size_t len, int err, void* arg) 314933707f3Ssthen { 315933707f3Ssthen struct libworker* w = (struct libworker*)arg; 316933707f3Ssthen 317933707f3Ssthen if(err != 0) { 318933707f3Ssthen free(msg); 319933707f3Ssthen /* it is of no use to go on, exit */ 320933707f3Ssthen comm_base_exit(w->base); 321933707f3Ssthen return; 322933707f3Ssthen } 323933707f3Ssthen libworker_do_cmd(w, msg, len); /* also frees the buf */ 324933707f3Ssthen } 325933707f3Ssthen 326933707f3Ssthen /** the background thread func */ 327933707f3Ssthen static void* 328933707f3Ssthen libworker_dobg(void* arg) 329933707f3Ssthen { 330933707f3Ssthen /* setup */ 331933707f3Ssthen uint32_t m; 332933707f3Ssthen struct libworker* w = (struct libworker*)arg; 333933707f3Ssthen struct ub_ctx* ctx; 334933707f3Ssthen if(!w) { 335933707f3Ssthen log_err("libunbound bg worker init failed, nomem"); 336933707f3Ssthen return NULL; 337933707f3Ssthen } 338933707f3Ssthen ctx = w->ctx; 339933707f3Ssthen log_thread_set(&w->thread_num); 340933707f3Ssthen #ifdef THREADS_DISABLED 341933707f3Ssthen /* we are forked */ 342933707f3Ssthen w->is_bg_thread = 0; 343933707f3Ssthen /* close non-used parts of the pipes */ 344933707f3Ssthen tube_close_write(ctx->qq_pipe); 345933707f3Ssthen tube_close_read(ctx->rr_pipe); 346933707f3Ssthen #endif 347933707f3Ssthen if(!tube_setup_bg_listen(ctx->qq_pipe, w->base, 348933707f3Ssthen libworker_handle_control_cmd, w)) { 349933707f3Ssthen log_err("libunbound bg worker init failed, no bglisten"); 350933707f3Ssthen return NULL; 351933707f3Ssthen } 352933707f3Ssthen if(!tube_setup_bg_write(ctx->rr_pipe, w->base)) { 353933707f3Ssthen log_err("libunbound bg worker init failed, no bgwrite"); 354933707f3Ssthen return NULL; 355933707f3Ssthen } 356933707f3Ssthen 357933707f3Ssthen /* do the work */ 358933707f3Ssthen comm_base_dispatch(w->base); 359933707f3Ssthen 360933707f3Ssthen /* cleanup */ 361933707f3Ssthen m = UB_LIBCMD_QUIT; 36220237c55Ssthen w->want_quit = 1; 363933707f3Ssthen tube_remove_bg_listen(w->ctx->qq_pipe); 364933707f3Ssthen tube_remove_bg_write(w->ctx->rr_pipe); 365933707f3Ssthen libworker_delete(w); 366933707f3Ssthen (void)tube_write_msg(ctx->rr_pipe, (uint8_t*)&m, 367933707f3Ssthen (uint32_t)sizeof(m), 0); 368933707f3Ssthen #ifdef THREADS_DISABLED 369933707f3Ssthen /* close pipes from forked process before exit */ 370933707f3Ssthen tube_close_read(ctx->qq_pipe); 371933707f3Ssthen tube_close_write(ctx->rr_pipe); 372933707f3Ssthen #endif 373933707f3Ssthen return NULL; 374933707f3Ssthen } 375933707f3Ssthen 376933707f3Ssthen int libworker_bg(struct ub_ctx* ctx) 377933707f3Ssthen { 378933707f3Ssthen struct libworker* w; 379933707f3Ssthen /* fork or threadcreate */ 380933707f3Ssthen lock_basic_lock(&ctx->cfglock); 381933707f3Ssthen if(ctx->dothread) { 382933707f3Ssthen lock_basic_unlock(&ctx->cfglock); 3830b68ff31Ssthen w = libworker_setup(ctx, 1, NULL); 384933707f3Ssthen if(!w) return UB_NOMEM; 385933707f3Ssthen w->is_bg_thread = 1; 3868b7325afSsthen ctx->thread_worker = w; 387933707f3Ssthen #ifdef ENABLE_LOCK_CHECKS 388933707f3Ssthen w->thread_num = 1; /* for nicer DEBUG checklocks */ 389933707f3Ssthen #endif 390933707f3Ssthen ub_thread_create(&ctx->bg_tid, libworker_dobg, w); 391933707f3Ssthen } else { 392933707f3Ssthen lock_basic_unlock(&ctx->cfglock); 393933707f3Ssthen #ifndef HAVE_FORK 394933707f3Ssthen /* no fork on windows */ 395933707f3Ssthen return UB_FORKFAIL; 396933707f3Ssthen #else /* HAVE_FORK */ 397933707f3Ssthen switch((ctx->bg_pid=fork())) { 398933707f3Ssthen case 0: 3990b68ff31Ssthen w = libworker_setup(ctx, 1, NULL); 400933707f3Ssthen if(!w) fatal_exit("out of memory"); 401933707f3Ssthen /* close non-used parts of the pipes */ 402933707f3Ssthen tube_close_write(ctx->qq_pipe); 403933707f3Ssthen tube_close_read(ctx->rr_pipe); 404933707f3Ssthen (void)libworker_dobg(w); 405933707f3Ssthen exit(0); 406933707f3Ssthen break; 407933707f3Ssthen case -1: 408933707f3Ssthen return UB_FORKFAIL; 409933707f3Ssthen default: 410e9c7b4efSsthen /* close non-used parts, so that the worker 411e9c7b4efSsthen * bgprocess gets 'pipe closed' when the 412e9c7b4efSsthen * main process exits */ 413e9c7b4efSsthen tube_close_read(ctx->qq_pipe); 414e9c7b4efSsthen tube_close_write(ctx->rr_pipe); 415933707f3Ssthen break; 416933707f3Ssthen } 417933707f3Ssthen #endif /* HAVE_FORK */ 418933707f3Ssthen } 419933707f3Ssthen return UB_NOERROR; 420933707f3Ssthen } 421933707f3Ssthen 422933707f3Ssthen /** insert canonname */ 423933707f3Ssthen static int 424933707f3Ssthen fill_canon(struct ub_result* res, uint8_t* s) 425933707f3Ssthen { 426933707f3Ssthen char buf[255+2]; 427933707f3Ssthen dname_str(s, buf); 428933707f3Ssthen res->canonname = strdup(buf); 429933707f3Ssthen return res->canonname != 0; 430933707f3Ssthen } 431933707f3Ssthen 432933707f3Ssthen /** fill data into result */ 433933707f3Ssthen static int 434933707f3Ssthen fill_res(struct ub_result* res, struct ub_packed_rrset_key* answer, 435e9c7b4efSsthen uint8_t* finalcname, struct query_info* rq, struct reply_info* rep) 436933707f3Ssthen { 437933707f3Ssthen size_t i; 438933707f3Ssthen struct packed_rrset_data* data; 439e9c7b4efSsthen res->ttl = 0; 440933707f3Ssthen if(!answer) { 441933707f3Ssthen if(finalcname) { 442933707f3Ssthen if(!fill_canon(res, finalcname)) 443933707f3Ssthen return 0; /* out of memory */ 444933707f3Ssthen } 445e9c7b4efSsthen if(rep->rrset_count != 0) 446e9c7b4efSsthen res->ttl = (int)rep->ttl; 447933707f3Ssthen res->data = (char**)calloc(1, sizeof(char*)); 448191f22c6Ssthen if(!res->data) 449191f22c6Ssthen return 0; /* out of memory */ 450933707f3Ssthen res->len = (int*)calloc(1, sizeof(int)); 451191f22c6Ssthen if(!res->len) { 452191f22c6Ssthen free(res->data); 453191f22c6Ssthen res->data = NULL; 454191f22c6Ssthen return 0; /* out of memory */ 455191f22c6Ssthen } 456191f22c6Ssthen return 1; 457933707f3Ssthen } 458933707f3Ssthen data = (struct packed_rrset_data*)answer->entry.data; 459933707f3Ssthen if(query_dname_compare(rq->qname, answer->rk.dname) != 0) { 460933707f3Ssthen if(!fill_canon(res, answer->rk.dname)) 461933707f3Ssthen return 0; /* out of memory */ 462933707f3Ssthen } else res->canonname = NULL; 463933707f3Ssthen res->data = (char**)calloc(data->count+1, sizeof(char*)); 464191f22c6Ssthen if(!res->data) 465933707f3Ssthen return 0; /* out of memory */ 466191f22c6Ssthen res->len = (int*)calloc(data->count+1, sizeof(int)); 467191f22c6Ssthen if(!res->len) { 468191f22c6Ssthen free(res->data); 469191f22c6Ssthen res->data = NULL; 470191f22c6Ssthen return 0; /* out of memory */ 471191f22c6Ssthen } 472933707f3Ssthen for(i=0; i<data->count; i++) { 473933707f3Ssthen /* remove rdlength from rdata */ 474933707f3Ssthen res->len[i] = (int)(data->rr_len[i] - 2); 475933707f3Ssthen res->data[i] = memdup(data->rr_data[i]+2, (size_t)res->len[i]); 476191f22c6Ssthen if(!res->data[i]) { 477191f22c6Ssthen size_t j; 478191f22c6Ssthen for(j=0; j<i; j++) { 479191f22c6Ssthen free(res->data[j]); 480191f22c6Ssthen res->data[j] = NULL; 481191f22c6Ssthen } 482191f22c6Ssthen free(res->data); 483191f22c6Ssthen res->data = NULL; 484191f22c6Ssthen free(res->len); 485191f22c6Ssthen res->len = NULL; 486933707f3Ssthen return 0; /* out of memory */ 487933707f3Ssthen } 488191f22c6Ssthen } 489e9c7b4efSsthen /* ttl for positive answers, from CNAME and answer RRs */ 490e9c7b4efSsthen if(data->count != 0) { 491e9c7b4efSsthen size_t j; 492e9c7b4efSsthen res->ttl = (int)data->ttl; 493e9c7b4efSsthen for(j=0; j<rep->an_numrrsets; j++) { 494e9c7b4efSsthen struct packed_rrset_data* d = 495e9c7b4efSsthen (struct packed_rrset_data*)rep->rrsets[j]-> 496e9c7b4efSsthen entry.data; 497e9c7b4efSsthen if((int)d->ttl < res->ttl) 498e9c7b4efSsthen res->ttl = (int)d->ttl; 499e9c7b4efSsthen } 500e9c7b4efSsthen } 501e9c7b4efSsthen /* ttl for negative answers */ 502e9c7b4efSsthen if(data->count == 0 && rep->rrset_count != 0) 503e9c7b4efSsthen res->ttl = (int)rep->ttl; 504933707f3Ssthen res->data[data->count] = NULL; 505933707f3Ssthen res->len[data->count] = 0; 506933707f3Ssthen return 1; 507933707f3Ssthen } 508933707f3Ssthen 509933707f3Ssthen /** fill result from parsed message, on error fills servfail */ 510933707f3Ssthen void 5110b68ff31Ssthen libworker_enter_result(struct ub_result* res, sldns_buffer* buf, 512933707f3Ssthen struct regional* temp, enum sec_status msg_security) 513933707f3Ssthen { 514933707f3Ssthen struct query_info rq; 515933707f3Ssthen struct reply_info* rep; 516933707f3Ssthen res->rcode = LDNS_RCODE_SERVFAIL; 517bdfc4d55Sflorian rep = parse_reply_in_temp_region(buf, temp, &rq); 518933707f3Ssthen if(!rep) { 519933707f3Ssthen log_err("cannot parse buf"); 520933707f3Ssthen return; /* error parsing buf, or out of memory */ 521933707f3Ssthen } 522933707f3Ssthen if(!fill_res(res, reply_find_answer_rrset(&rq, rep), 523e9c7b4efSsthen reply_find_final_cname_target(&rq, rep), &rq, rep)) 524933707f3Ssthen return; /* out of memory */ 525933707f3Ssthen /* rcode, havedata, nxdomain, secure, bogus */ 526933707f3Ssthen res->rcode = (int)FLAGS_GET_RCODE(rep->flags); 527933707f3Ssthen if(res->data && res->data[0]) 528933707f3Ssthen res->havedata = 1; 529933707f3Ssthen if(res->rcode == LDNS_RCODE_NXDOMAIN) 530933707f3Ssthen res->nxdomain = 1; 531933707f3Ssthen if(msg_security == sec_status_secure) 532933707f3Ssthen res->secure = 1; 53320237c55Ssthen if(msg_security == sec_status_bogus || 53420237c55Ssthen msg_security == sec_status_secure_sentinel_fail) 535933707f3Ssthen res->bogus = 1; 536933707f3Ssthen } 537933707f3Ssthen 538933707f3Ssthen /** fillup fg results */ 539933707f3Ssthen static void 5400b68ff31Ssthen libworker_fillup_fg(struct ctx_query* q, int rcode, sldns_buffer* buf, 5412308e98cSsthen enum sec_status s, char* why_bogus, int was_ratelimited) 542933707f3Ssthen { 5432308e98cSsthen q->res->was_ratelimited = was_ratelimited; 544933707f3Ssthen if(why_bogus) 545933707f3Ssthen q->res->why_bogus = strdup(why_bogus); 546933707f3Ssthen if(rcode != 0) { 547933707f3Ssthen q->res->rcode = rcode; 548933707f3Ssthen q->msg_security = s; 549933707f3Ssthen return; 550933707f3Ssthen } 551933707f3Ssthen 552933707f3Ssthen q->res->rcode = LDNS_RCODE_SERVFAIL; 553ebf5bb73Ssthen q->msg_security = sec_status_unchecked; 5540b68ff31Ssthen q->msg = memdup(sldns_buffer_begin(buf), sldns_buffer_limit(buf)); 5550b68ff31Ssthen q->msg_len = sldns_buffer_limit(buf); 556933707f3Ssthen if(!q->msg) { 557933707f3Ssthen return; /* the error is in the rcode */ 558933707f3Ssthen } 559933707f3Ssthen 560933707f3Ssthen /* canonname and results */ 561933707f3Ssthen q->msg_security = s; 562933707f3Ssthen libworker_enter_result(q->res, buf, q->w->env->scratch, s); 563933707f3Ssthen } 564933707f3Ssthen 565933707f3Ssthen void 5660b68ff31Ssthen libworker_fg_done_cb(void* arg, int rcode, sldns_buffer* buf, enum sec_status s, 5672308e98cSsthen char* why_bogus, int was_ratelimited) 568933707f3Ssthen { 569933707f3Ssthen struct ctx_query* q = (struct ctx_query*)arg; 570933707f3Ssthen /* fg query is done; exit comm base */ 571933707f3Ssthen comm_base_exit(q->w->base); 572933707f3Ssthen 5732308e98cSsthen libworker_fillup_fg(q, rcode, buf, s, why_bogus, was_ratelimited); 574933707f3Ssthen } 575933707f3Ssthen 576933707f3Ssthen /** setup qinfo and edns */ 577933707f3Ssthen static int 578933707f3Ssthen setup_qinfo_edns(struct libworker* w, struct ctx_query* q, 579933707f3Ssthen struct query_info* qinfo, struct edns_data* edns) 580933707f3Ssthen { 581933707f3Ssthen qinfo->qtype = (uint16_t)q->res->qtype; 582933707f3Ssthen qinfo->qclass = (uint16_t)q->res->qclass; 58377079be7Ssthen qinfo->local_alias = NULL; 5840b68ff31Ssthen qinfo->qname = sldns_str2wire_dname(q->res->qname, &qinfo->qname_len); 5850b68ff31Ssthen if(!qinfo->qname) { 586933707f3Ssthen return 0; 587933707f3Ssthen } 588933707f3Ssthen edns->edns_present = 1; 589933707f3Ssthen edns->ext_rcode = 0; 590933707f3Ssthen edns->edns_version = 0; 591933707f3Ssthen edns->bits = EDNS_DO; 592e21c60efSsthen edns->opt_list_in = NULL; 593e21c60efSsthen edns->opt_list_out = NULL; 594e21c60efSsthen edns->opt_list_inplace_cb_out = NULL; 5959982a05dSsthen edns->padding_block_size = 0; 5968b7325afSsthen edns->cookie_present = 0; 5978b7325afSsthen edns->cookie_valid = 0; 5980b68ff31Ssthen if(sldns_buffer_capacity(w->back->udp_buff) < 65535) 5990b68ff31Ssthen edns->udp_size = (uint16_t)sldns_buffer_capacity( 600933707f3Ssthen w->back->udp_buff); 601933707f3Ssthen else edns->udp_size = 65535; 602933707f3Ssthen return 1; 603933707f3Ssthen } 604933707f3Ssthen 605933707f3Ssthen int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q) 606933707f3Ssthen { 6070b68ff31Ssthen struct libworker* w = libworker_setup(ctx, 0, NULL); 608933707f3Ssthen uint16_t qflags, qid; 609933707f3Ssthen struct query_info qinfo; 610933707f3Ssthen struct edns_data edns; 611933707f3Ssthen if(!w) 612933707f3Ssthen return UB_INITFAIL; 613933707f3Ssthen if(!setup_qinfo_edns(w, q, &qinfo, &edns)) { 614933707f3Ssthen libworker_delete(w); 615933707f3Ssthen return UB_SYNTAX; 616933707f3Ssthen } 617933707f3Ssthen qid = 0; 618933707f3Ssthen qflags = BIT_RD; 619933707f3Ssthen q->w = w; 620933707f3Ssthen /* see if there is a fixed answer */ 6210b68ff31Ssthen sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid); 6220b68ff31Ssthen sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags); 62377079be7Ssthen if(local_zones_answer(ctx->local_zones, w->env, &qinfo, &edns, 62477079be7Ssthen w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0, 62577079be7Ssthen NULL, 0, NULL, 0, NULL)) { 626933707f3Ssthen regional_free_all(w->env->scratch); 627933707f3Ssthen libworker_fillup_fg(q, LDNS_RCODE_NOERROR, 6282308e98cSsthen w->back->udp_buff, sec_status_insecure, NULL, 0); 629933707f3Ssthen libworker_delete(w); 630933707f3Ssthen free(qinfo.qname); 631933707f3Ssthen return UB_NOERROR; 632933707f3Ssthen } 633938a3a5eSflorian if(ctx->env->auth_zones && auth_zones_answer(ctx->env->auth_zones, 6342308e98cSsthen w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) { 635938a3a5eSflorian regional_free_all(w->env->scratch); 636938a3a5eSflorian libworker_fillup_fg(q, LDNS_RCODE_NOERROR, 6372308e98cSsthen w->back->udp_buff, sec_status_insecure, NULL, 0); 638938a3a5eSflorian libworker_delete(w); 639938a3a5eSflorian free(qinfo.qname); 640938a3a5eSflorian return UB_NOERROR; 641938a3a5eSflorian } 642933707f3Ssthen /* process new query */ 643933707f3Ssthen if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, 6440bdb4f62Ssthen w->back->udp_buff, qid, libworker_fg_done_cb, q, 0)) { 645933707f3Ssthen free(qinfo.qname); 646933707f3Ssthen return UB_NOMEM; 647933707f3Ssthen } 648933707f3Ssthen free(qinfo.qname); 649933707f3Ssthen 650933707f3Ssthen /* wait for reply */ 651933707f3Ssthen comm_base_dispatch(w->base); 652933707f3Ssthen 653933707f3Ssthen libworker_delete(w); 654933707f3Ssthen return UB_NOERROR; 655933707f3Ssthen } 656933707f3Ssthen 6570b68ff31Ssthen void 6580b68ff31Ssthen libworker_event_done_cb(void* arg, int rcode, sldns_buffer* buf, 6592308e98cSsthen enum sec_status s, char* why_bogus, int was_ratelimited) 6600b68ff31Ssthen { 6610b68ff31Ssthen struct ctx_query* q = (struct ctx_query*)arg; 66220237c55Ssthen ub_event_callback_type cb = q->cb_event; 6630b68ff31Ssthen void* cb_arg = q->cb_arg; 6640b68ff31Ssthen int cancelled = q->cancelled; 6650b68ff31Ssthen 6660b68ff31Ssthen /* delete it now */ 6670b68ff31Ssthen struct ub_ctx* ctx = q->w->ctx; 6680b68ff31Ssthen lock_basic_lock(&ctx->cfglock); 6690b68ff31Ssthen (void)rbtree_delete(&ctx->queries, q->node.key); 6700b68ff31Ssthen ctx->num_async--; 6710b68ff31Ssthen context_query_delete(q); 6720b68ff31Ssthen lock_basic_unlock(&ctx->cfglock); 6730b68ff31Ssthen 6740b68ff31Ssthen if(!cancelled) { 6750b68ff31Ssthen /* call callback */ 6760b68ff31Ssthen int sec = 0; 6770b68ff31Ssthen if(s == sec_status_bogus) 6780b68ff31Ssthen sec = 1; 6790b68ff31Ssthen else if(s == sec_status_secure) 6800b68ff31Ssthen sec = 2; 6813150e5f6Ssthen (*cb)(cb_arg, rcode, (buf?(void*)sldns_buffer_begin(buf):NULL), 6823150e5f6Ssthen (buf?(int)sldns_buffer_limit(buf):0), sec, why_bogus, was_ratelimited); 6830b68ff31Ssthen } 6840b68ff31Ssthen } 6850b68ff31Ssthen 6860b68ff31Ssthen int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q, 6870b68ff31Ssthen int* async_id) 6880b68ff31Ssthen { 6890b68ff31Ssthen struct libworker* w = ctx->event_worker; 6900b68ff31Ssthen uint16_t qflags, qid; 6910b68ff31Ssthen struct query_info qinfo; 6920b68ff31Ssthen struct edns_data edns; 6930b68ff31Ssthen if(!w) 6940b68ff31Ssthen return UB_INITFAIL; 6950b68ff31Ssthen if(!setup_qinfo_edns(w, q, &qinfo, &edns)) 6960b68ff31Ssthen return UB_SYNTAX; 6970b68ff31Ssthen qid = 0; 6980b68ff31Ssthen qflags = BIT_RD; 6990b68ff31Ssthen q->w = w; 7000b68ff31Ssthen /* see if there is a fixed answer */ 7010b68ff31Ssthen sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid); 7020b68ff31Ssthen sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags); 70377079be7Ssthen if(local_zones_answer(ctx->local_zones, w->env, &qinfo, &edns, 70477079be7Ssthen w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0, 70577079be7Ssthen NULL, 0, NULL, 0, NULL)) { 7060b68ff31Ssthen regional_free_all(w->env->scratch); 7070b68ff31Ssthen free(qinfo.qname); 7080b68ff31Ssthen libworker_event_done_cb(q, LDNS_RCODE_NOERROR, 7092308e98cSsthen w->back->udp_buff, sec_status_insecure, NULL, 0); 7100b68ff31Ssthen return UB_NOERROR; 7110b68ff31Ssthen } 712938a3a5eSflorian if(ctx->env->auth_zones && auth_zones_answer(ctx->env->auth_zones, 7132308e98cSsthen w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) { 714938a3a5eSflorian regional_free_all(w->env->scratch); 715938a3a5eSflorian free(qinfo.qname); 716938a3a5eSflorian libworker_event_done_cb(q, LDNS_RCODE_NOERROR, 7172308e98cSsthen w->back->udp_buff, sec_status_insecure, NULL, 0); 718938a3a5eSflorian return UB_NOERROR; 719938a3a5eSflorian } 7200b68ff31Ssthen /* process new query */ 7210b68ff31Ssthen if(async_id) 7220b68ff31Ssthen *async_id = q->querynum; 7230b68ff31Ssthen if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, 7240bdb4f62Ssthen w->back->udp_buff, qid, libworker_event_done_cb, q, 0)) { 7250b68ff31Ssthen free(qinfo.qname); 7260b68ff31Ssthen return UB_NOMEM; 7270b68ff31Ssthen } 7280b68ff31Ssthen free(qinfo.qname); 7290b68ff31Ssthen return UB_NOERROR; 7300b68ff31Ssthen } 7310b68ff31Ssthen 732933707f3Ssthen /** add result to the bg worker result queue */ 733933707f3Ssthen static void 7340b68ff31Ssthen add_bg_result(struct libworker* w, struct ctx_query* q, sldns_buffer* pkt, 7352308e98cSsthen int err, char* reason, int was_ratelimited) 736933707f3Ssthen { 737933707f3Ssthen uint8_t* msg = NULL; 738933707f3Ssthen uint32_t len = 0; 739933707f3Ssthen 74020237c55Ssthen if(w->want_quit) { 74120237c55Ssthen context_query_delete(q); 74220237c55Ssthen return; 74320237c55Ssthen } 744933707f3Ssthen /* serialize and delete unneeded q */ 745933707f3Ssthen if(w->is_bg_thread) { 746933707f3Ssthen lock_basic_lock(&w->ctx->cfglock); 747933707f3Ssthen if(reason) 748933707f3Ssthen q->res->why_bogus = strdup(reason); 7492308e98cSsthen q->res->was_ratelimited = was_ratelimited; 750933707f3Ssthen if(pkt) { 7510b68ff31Ssthen q->msg_len = sldns_buffer_remaining(pkt); 7520b68ff31Ssthen q->msg = memdup(sldns_buffer_begin(pkt), q->msg_len); 7532308e98cSsthen if(!q->msg) { 7542308e98cSsthen msg = context_serialize_answer(q, UB_NOMEM, NULL, &len); 7552308e98cSsthen } else { 7562308e98cSsthen msg = context_serialize_answer(q, err, NULL, &len); 7572308e98cSsthen } 7582308e98cSsthen } else { 7592308e98cSsthen msg = context_serialize_answer(q, err, NULL, &len); 7602308e98cSsthen } 761933707f3Ssthen lock_basic_unlock(&w->ctx->cfglock); 762933707f3Ssthen } else { 763933707f3Ssthen if(reason) 764933707f3Ssthen q->res->why_bogus = strdup(reason); 7652308e98cSsthen q->res->was_ratelimited = was_ratelimited; 766933707f3Ssthen msg = context_serialize_answer(q, err, pkt, &len); 767933707f3Ssthen (void)rbtree_delete(&w->ctx->queries, q->node.key); 768933707f3Ssthen w->ctx->num_async--; 769933707f3Ssthen context_query_delete(q); 770933707f3Ssthen } 771933707f3Ssthen 772933707f3Ssthen if(!msg) { 773933707f3Ssthen log_err("out of memory for async answer"); 774933707f3Ssthen return; 775933707f3Ssthen } 776933707f3Ssthen if(!tube_queue_item(w->ctx->rr_pipe, msg, len)) { 777933707f3Ssthen log_err("out of memory for async answer"); 778933707f3Ssthen return; 779933707f3Ssthen } 780933707f3Ssthen } 781933707f3Ssthen 782933707f3Ssthen void 7830b68ff31Ssthen libworker_bg_done_cb(void* arg, int rcode, sldns_buffer* buf, enum sec_status s, 7842308e98cSsthen char* why_bogus, int was_ratelimited) 785933707f3Ssthen { 786933707f3Ssthen struct ctx_query* q = (struct ctx_query*)arg; 787933707f3Ssthen 7887191de28Ssthen if(q->cancelled || q->w->back->want_to_quit) { 789933707f3Ssthen if(q->w->is_bg_thread) { 790933707f3Ssthen /* delete it now */ 791933707f3Ssthen struct ub_ctx* ctx = q->w->ctx; 792933707f3Ssthen lock_basic_lock(&ctx->cfglock); 793933707f3Ssthen (void)rbtree_delete(&ctx->queries, q->node.key); 794933707f3Ssthen ctx->num_async--; 795933707f3Ssthen context_query_delete(q); 796933707f3Ssthen lock_basic_unlock(&ctx->cfglock); 797933707f3Ssthen } 798933707f3Ssthen /* cancelled, do not give answer */ 799933707f3Ssthen return; 800933707f3Ssthen } 801933707f3Ssthen q->msg_security = s; 8022308e98cSsthen if(!buf) { 803cebdf579Ssthen buf = q->w->env->scratch_buffer; 8042308e98cSsthen } 805933707f3Ssthen if(rcode != 0) { 806933707f3Ssthen error_encode(buf, rcode, NULL, 0, BIT_RD, NULL); 807933707f3Ssthen } 8082308e98cSsthen add_bg_result(q->w, q, buf, UB_NOERROR, why_bogus, was_ratelimited); 809933707f3Ssthen } 810933707f3Ssthen 811933707f3Ssthen 812933707f3Ssthen /** handle new query command for bg worker */ 813933707f3Ssthen static void 814933707f3Ssthen handle_newq(struct libworker* w, uint8_t* buf, uint32_t len) 815933707f3Ssthen { 816933707f3Ssthen uint16_t qflags, qid; 817933707f3Ssthen struct query_info qinfo; 818933707f3Ssthen struct edns_data edns; 819933707f3Ssthen struct ctx_query* q; 820933707f3Ssthen if(w->is_bg_thread) { 821933707f3Ssthen lock_basic_lock(&w->ctx->cfglock); 822933707f3Ssthen q = context_lookup_new_query(w->ctx, buf, len); 823933707f3Ssthen lock_basic_unlock(&w->ctx->cfglock); 824933707f3Ssthen } else { 825933707f3Ssthen q = context_deserialize_new_query(w->ctx, buf, len); 826933707f3Ssthen } 827933707f3Ssthen free(buf); 828933707f3Ssthen if(!q) { 829933707f3Ssthen log_err("failed to deserialize newq"); 830933707f3Ssthen return; 831933707f3Ssthen } 832933707f3Ssthen if(!setup_qinfo_edns(w, q, &qinfo, &edns)) { 8332308e98cSsthen add_bg_result(w, q, NULL, UB_SYNTAX, NULL, 0); 834933707f3Ssthen return; 835933707f3Ssthen } 836933707f3Ssthen qid = 0; 837933707f3Ssthen qflags = BIT_RD; 838933707f3Ssthen /* see if there is a fixed answer */ 8390b68ff31Ssthen sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid); 8400b68ff31Ssthen sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags); 84177079be7Ssthen if(local_zones_answer(w->ctx->local_zones, w->env, &qinfo, &edns, 84277079be7Ssthen w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0, 84377079be7Ssthen NULL, 0, NULL, 0, NULL)) { 844933707f3Ssthen regional_free_all(w->env->scratch); 845933707f3Ssthen q->msg_security = sec_status_insecure; 8462308e98cSsthen add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL, 0); 847933707f3Ssthen free(qinfo.qname); 848933707f3Ssthen return; 849933707f3Ssthen } 850938a3a5eSflorian if(w->ctx->env->auth_zones && auth_zones_answer(w->ctx->env->auth_zones, 8512308e98cSsthen w->env, &qinfo, &edns, NULL, w->back->udp_buff, w->env->scratch)) { 852938a3a5eSflorian regional_free_all(w->env->scratch); 853938a3a5eSflorian q->msg_security = sec_status_insecure; 8542308e98cSsthen add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL, 0); 855938a3a5eSflorian free(qinfo.qname); 856938a3a5eSflorian return; 857938a3a5eSflorian } 858933707f3Ssthen q->w = w; 859933707f3Ssthen /* process new query */ 860933707f3Ssthen if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, 8610bdb4f62Ssthen w->back->udp_buff, qid, libworker_bg_done_cb, q, 0)) { 8622308e98cSsthen add_bg_result(w, q, NULL, UB_NOMEM, NULL, 0); 863933707f3Ssthen } 864933707f3Ssthen free(qinfo.qname); 865933707f3Ssthen } 866933707f3Ssthen 867933707f3Ssthen void libworker_alloc_cleanup(void* arg) 868933707f3Ssthen { 869933707f3Ssthen struct libworker* w = (struct libworker*)arg; 870933707f3Ssthen slabhash_clear(&w->env->rrset_cache->table); 871933707f3Ssthen slabhash_clear(w->env->msg_cache); 872933707f3Ssthen } 873933707f3Ssthen 87477079be7Ssthen struct outbound_entry* libworker_send_query(struct query_info* qinfo, 87577079be7Ssthen uint16_t flags, int dnssec, int want_dnssec, int nocaps, 876e21c60efSsthen int check_ratelimit, 8772ee382b6Ssthen struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, 878e21c60efSsthen size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name, 879e21c60efSsthen struct module_qstate* q, int* was_ratelimited) 880933707f3Ssthen { 881933707f3Ssthen struct libworker* w = (struct libworker*)q->env->worker; 882933707f3Ssthen struct outbound_entry* e = (struct outbound_entry*)regional_alloc( 883933707f3Ssthen q->region, sizeof(*e)); 884933707f3Ssthen if(!e) 885933707f3Ssthen return NULL; 886933707f3Ssthen e->qstate = q; 88777079be7Ssthen e->qsent = outnet_serviced_query(w->back, qinfo, flags, dnssec, 888e21c60efSsthen want_dnssec, nocaps, check_ratelimit, tcp_upstream, ssl_upstream, 88920237c55Ssthen tls_auth_name, addr, addrlen, zone, zonelen, q, 890e21c60efSsthen libworker_handle_service_reply, e, w->back->udp_buff, q->env, 891e21c60efSsthen was_ratelimited); 892933707f3Ssthen if(!e->qsent) { 893933707f3Ssthen return NULL; 894933707f3Ssthen } 895933707f3Ssthen return e; 896933707f3Ssthen } 897933707f3Ssthen 898933707f3Ssthen int 899933707f3Ssthen libworker_handle_service_reply(struct comm_point* c, void* arg, int error, 900933707f3Ssthen struct comm_reply* reply_info) 901933707f3Ssthen { 902933707f3Ssthen struct outbound_entry* e = (struct outbound_entry*)arg; 903933707f3Ssthen struct libworker* lw = (struct libworker*)e->qstate->env->worker; 904933707f3Ssthen 905933707f3Ssthen if(error != 0) { 906933707f3Ssthen mesh_report_reply(lw->env->mesh, e, reply_info, error); 907933707f3Ssthen return 0; 908933707f3Ssthen } 909933707f3Ssthen /* sanity check. */ 9100b68ff31Ssthen if(!LDNS_QR_WIRE(sldns_buffer_begin(c->buffer)) 9110b68ff31Ssthen || LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) != 912933707f3Ssthen LDNS_PACKET_QUERY 9130b68ff31Ssthen || LDNS_QDCOUNT(sldns_buffer_begin(c->buffer)) > 1) { 914933707f3Ssthen /* error becomes timeout for the module as if this reply 915933707f3Ssthen * never arrived. */ 916933707f3Ssthen mesh_report_reply(lw->env->mesh, e, reply_info, 917933707f3Ssthen NETEVENT_TIMEOUT); 918933707f3Ssthen return 0; 919933707f3Ssthen } 920933707f3Ssthen mesh_report_reply(lw->env->mesh, e, reply_info, NETEVENT_NOERROR); 921933707f3Ssthen return 0; 922933707f3Ssthen } 923933707f3Ssthen 924933707f3Ssthen /* --- fake callbacks for fptr_wlist to work --- */ 925933707f3Ssthen void worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), 926933707f3Ssthen uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len), 927933707f3Ssthen int ATTR_UNUSED(error), void* ATTR_UNUSED(arg)) 928933707f3Ssthen { 929933707f3Ssthen log_assert(0); 930933707f3Ssthen } 931933707f3Ssthen 932933707f3Ssthen int worker_handle_request(struct comm_point* ATTR_UNUSED(c), 933933707f3Ssthen void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 934933707f3Ssthen struct comm_reply* ATTR_UNUSED(repinfo)) 935933707f3Ssthen { 936933707f3Ssthen log_assert(0); 937933707f3Ssthen return 0; 938933707f3Ssthen } 939933707f3Ssthen 940933707f3Ssthen int worker_handle_service_reply(struct comm_point* ATTR_UNUSED(c), 941933707f3Ssthen void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 942933707f3Ssthen struct comm_reply* ATTR_UNUSED(reply_info)) 943933707f3Ssthen { 944933707f3Ssthen log_assert(0); 945933707f3Ssthen return 0; 946933707f3Ssthen } 947933707f3Ssthen 948933707f3Ssthen int remote_accept_callback(struct comm_point* ATTR_UNUSED(c), 949933707f3Ssthen void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 950933707f3Ssthen struct comm_reply* ATTR_UNUSED(repinfo)) 951933707f3Ssthen { 952933707f3Ssthen log_assert(0); 953933707f3Ssthen return 0; 954933707f3Ssthen } 955933707f3Ssthen 956933707f3Ssthen int remote_control_callback(struct comm_point* ATTR_UNUSED(c), 957933707f3Ssthen void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 958933707f3Ssthen struct comm_reply* ATTR_UNUSED(repinfo)) 959933707f3Ssthen { 960933707f3Ssthen log_assert(0); 961933707f3Ssthen return 0; 962933707f3Ssthen } 963933707f3Ssthen 964933707f3Ssthen void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg)) 965933707f3Ssthen { 966933707f3Ssthen log_assert(0); 967933707f3Ssthen } 968933707f3Ssthen 96977079be7Ssthen struct outbound_entry* worker_send_query(struct query_info* ATTR_UNUSED(qinfo), 97077079be7Ssthen uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec), 97177079be7Ssthen int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps), 972e21c60efSsthen int ATTR_UNUSED(check_ratelimit), 97377079be7Ssthen struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), 974e21c60efSsthen uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), 97520237c55Ssthen int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name), 976e21c60efSsthen struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited)) 977933707f3Ssthen { 978933707f3Ssthen log_assert(0); 979933707f3Ssthen return 0; 980933707f3Ssthen } 981933707f3Ssthen 982933707f3Ssthen void 983933707f3Ssthen worker_alloc_cleanup(void* ATTR_UNUSED(arg)) 984933707f3Ssthen { 985933707f3Ssthen log_assert(0); 986933707f3Ssthen } 987933707f3Ssthen 988933707f3Ssthen void worker_stat_timer_cb(void* ATTR_UNUSED(arg)) 989933707f3Ssthen { 990933707f3Ssthen log_assert(0); 991933707f3Ssthen } 992933707f3Ssthen 993933707f3Ssthen void worker_probe_timer_cb(void* ATTR_UNUSED(arg)) 994933707f3Ssthen { 995933707f3Ssthen log_assert(0); 996933707f3Ssthen } 997933707f3Ssthen 998af4988b1Ssthen void worker_start_accept(void* ATTR_UNUSED(arg)) 999af4988b1Ssthen { 1000af4988b1Ssthen log_assert(0); 1001af4988b1Ssthen } 1002af4988b1Ssthen 1003af4988b1Ssthen void worker_stop_accept(void* ATTR_UNUSED(arg)) 1004af4988b1Ssthen { 1005af4988b1Ssthen log_assert(0); 1006af4988b1Ssthen } 1007af4988b1Ssthen 1008933707f3Ssthen int order_lock_cmp(const void* ATTR_UNUSED(e1), const void* ATTR_UNUSED(e2)) 1009933707f3Ssthen { 1010933707f3Ssthen log_assert(0); 1011933707f3Ssthen return 0; 1012933707f3Ssthen } 1013933707f3Ssthen 1014933707f3Ssthen int 1015933707f3Ssthen codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) 1016933707f3Ssthen { 1017933707f3Ssthen log_assert(0); 1018933707f3Ssthen return 0; 1019933707f3Ssthen } 1020933707f3Ssthen 1021933707f3Ssthen int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) 1022933707f3Ssthen { 1023933707f3Ssthen log_assert(0); 1024933707f3Ssthen return 0; 1025933707f3Ssthen } 1026933707f3Ssthen 1027933707f3Ssthen void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg)) 1028933707f3Ssthen { 1029933707f3Ssthen log_assert(0); 1030933707f3Ssthen } 1031933707f3Ssthen 1032933707f3Ssthen #ifdef UB_ON_WINDOWS 1033933707f3Ssthen void 1034933707f3Ssthen worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void* 1035933707f3Ssthen ATTR_UNUSED(arg)) { 1036933707f3Ssthen log_assert(0); 1037933707f3Ssthen } 1038933707f3Ssthen 1039933707f3Ssthen void 1040933707f3Ssthen wsvc_cron_cb(void* ATTR_UNUSED(arg)) 1041933707f3Ssthen { 1042933707f3Ssthen log_assert(0); 1043933707f3Ssthen } 1044933707f3Ssthen #endif /* UB_ON_WINDOWS */ 1045a3167c07Ssthen 1046a3167c07Ssthen #ifdef USE_DNSTAP 1047a3167c07Ssthen void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), 1048a3167c07Ssthen void* ATTR_UNUSED(arg)) 1049a3167c07Ssthen { 1050a3167c07Ssthen log_assert(0); 1051a3167c07Ssthen } 1052a3167c07Ssthen #endif 1053a3167c07Ssthen 1054a3167c07Ssthen #ifdef USE_DNSTAP 1055a3167c07Ssthen void dtio_mainfdcallback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), 1056a3167c07Ssthen void* ATTR_UNUSED(arg)) 1057a3167c07Ssthen { 1058a3167c07Ssthen log_assert(0); 1059a3167c07Ssthen } 1060a3167c07Ssthen #endif 1061