libworker.c revision 269257
1139825Simp/* 261926Smckusick * libunbound/worker.c - worker thread or process that resolves 336201Sjulian * 436206Sjulian * Copyright (c) 2007, NLnet Labs. All rights reserved. 536206Sjulian * 636206Sjulian * This software is open source. 736206Sjulian * 836201Sjulian * Redistribution and use in source and binary forms, with or without 961926Smckusick * modification, are permitted provided that the following conditions 1036201Sjulian * are met: 1161926Smckusick * 1261926Smckusick * Redistributions of source code must retain the above copyright notice, 1361926Smckusick * this list of conditions and the following disclaimer. 1436201Sjulian * 1536201Sjulian * Redistributions in binary form must reproduce the above copyright notice, 1636201Sjulian * this list of conditions and the following disclaimer in the documentation 1736201Sjulian * and/or other materials provided with the distribution. 1836201Sjulian * 1936201Sjulian * Neither the name of the NLNET LABS nor the names of its contributors may 2036201Sjulian * be used to endorse or promote products derived from this software without 2136201Sjulian * specific prior written permission. 2236201Sjulian * 2336201Sjulian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2436201Sjulian * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2536201Sjulian * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2636201Sjulian * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2736201Sjulian * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2836201Sjulian * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2936201Sjulian * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 3036201Sjulian * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 3136201Sjulian * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 3236201Sjulian * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3336201Sjulian * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3436201Sjulian */ 3536201Sjulian 3636201Sjulian/** 3736201Sjulian * \file 3861926Smckusick * 3950480Speter * This file contains the worker process or thread that performs 4036201Sjulian * the DNS resolving and validation. The worker is called by a procedure 4136201Sjulian * and if in the background continues until exit, if in the foreground 4236201Sjulian * returns from the procedure when done. 4336201Sjulian */ 4436201Sjulian#include "config.h" 4536201Sjulian#ifdef HAVE_SSL 4636201Sjulian#include <openssl/ssl.h> 4736201Sjulian#endif 4836201Sjulian#include "libunbound/libworker.h" 49208287Sjeff#include "libunbound/context.h" 50208287Sjeff#include "libunbound/unbound.h" 51208287Sjeff#include "libunbound/worker.h" 52208287Sjeff#include "libunbound/unbound-event.h" 5336201Sjulian#include "services/outside_network.h" 5436201Sjulian#include "services/mesh.h" 5536201Sjulian#include "services/localzone.h" 5636201Sjulian#include "services/cache/rrset.h" 57208287Sjeff#include "services/outbound_list.h" 58208287Sjeff#include "util/fptr_wlist.h" 59208287Sjeff#include "util/module.h" 60208287Sjeff#include "util/regional.h" 61208287Sjeff#include "util/random.h" 62208287Sjeff#include "util/config_file.h" 63208287Sjeff#include "util/netevent.h" 6436201Sjulian#include "util/storage/lookup3.h" 6536201Sjulian#include "util/storage/slabhash.h" 6636201Sjulian#include "util/net_help.h" 6736201Sjulian#include "util/data/dname.h" 68208287Sjeff#include "util/data/msgreply.h" 69208287Sjeff#include "util/data/msgencode.h" 70208287Sjeff#include "util/tube.h" 71208287Sjeff#include "iterator/iter_fwd.h" 72208287Sjeff#include "iterator/iter_hints.h" 73208287Sjeff#include "ldns/sbuffer.h" 74208287Sjeff#include "ldns/str2wire.h" 75208287Sjeff 76208287Sjeff/** handle new query command for bg worker */ 77208287Sjeffstatic void handle_newq(struct libworker* w, uint8_t* buf, uint32_t len); 78208287Sjeff 79208287Sjeff/** delete libworker env */ 80208287Sjeffstatic void 81208287Sjefflibworker_delete_env(struct libworker* w) 82208287Sjeff{ 83208287Sjeff if(w->env) { 84208287Sjeff outside_network_quit_prepare(w->back); 8536201Sjulian mesh_delete(w->env->mesh); 8636201Sjulian context_release_alloc(w->ctx, w->env->alloc, 8736201Sjulian !w->is_bg || w->is_bg_thread); 88208287Sjeff sldns_buffer_free(w->env->scratch_buffer); 89208287Sjeff regional_destroy(w->env->scratch); 90208287Sjeff forwards_delete(w->env->fwds); 91208287Sjeff hints_delete(w->env->hints); 92208287Sjeff ub_randfree(w->env->rnd); 93208287Sjeff free(w->env); 94208287Sjeff } 95208287Sjeff#ifdef HAVE_SSL 96208287Sjeff SSL_CTX_free(w->sslctx); 97208287Sjeff#endif 98208287Sjeff outside_network_delete(w->back); 99208287Sjeff} 100208287Sjeff 101208287Sjeff/** delete libworker struct */ 102208287Sjeffstatic void 103208287Sjefflibworker_delete(struct libworker* w) 104208287Sjeff{ 105208287Sjeff if(!w) return; 106208287Sjeff libworker_delete_env(w); 107208287Sjeff comm_base_delete(w->base); 108100344Smckusick free(w); 109100344Smckusick} 110212617Smckusick 111212617Smckusickvoid 112212617Smckusicklibworker_delete_event(struct libworker* w) 113212617Smckusick{ 114212617Smckusick if(!w) return; 115212617Smckusick libworker_delete_env(w); 116212617Smckusick comm_base_delete_no_base(w->base); 117212617Smckusick free(w); 118212617Smckusick} 11936201Sjulian 120207141Sjeff/** setup fresh libworker struct */ 121207141Sjeffstatic struct libworker* 122207141Sjefflibworker_setup(struct ub_ctx* ctx, int is_bg, struct event_base* eb) 123207141Sjeff{ 124207141Sjeff unsigned int seed; 125207141Sjeff struct libworker* w = (struct libworker*)calloc(1, sizeof(*w)); 126207141Sjeff struct config_file* cfg = ctx->env->cfg; 127207141Sjeff int* ports; 128207141Sjeff int numports; 129207141Sjeff if(!w) return NULL; 130222958Sjeff w->is_bg = is_bg; 131207141Sjeff w->ctx = ctx; 132207141Sjeff w->env = (struct module_env*)malloc(sizeof(*w->env)); 133207141Sjeff if(!w->env) { 134207141Sjeff free(w); 135258403Sjmg return NULL; 136207141Sjeff } 137207141Sjeff *w->env = *ctx->env; 138207141Sjeff w->env->alloc = context_obtain_alloc(ctx, !w->is_bg || w->is_bg_thread); 139207141Sjeff if(!w->env->alloc) { 140207141Sjeff libworker_delete(w); 141207141Sjeff return NULL; 142207141Sjeff } 14336201Sjulian w->thread_num = w->env->alloc->thread_num; 14436201Sjulian alloc_set_id_cleanup(w->env->alloc, &libworker_alloc_cleanup, w); 14536201Sjulian if(!w->is_bg || w->is_bg_thread) { 14636201Sjulian lock_basic_lock(&ctx->cfglock); 147256817Smckusick } 148256817Smckusick w->env->scratch = regional_create_custom(cfg->msg_buffer_size); 149256817Smckusick w->env->scratch_buffer = sldns_buffer_new(cfg->msg_buffer_size); 150256817Smckusick w->env->fwds = forwards_create(); 151256817Smckusick if(w->env->fwds && !forwards_apply_cfg(w->env->fwds, cfg)) { 152256817Smckusick forwards_delete(w->env->fwds); 153256817Smckusick w->env->fwds = NULL; 154256817Smckusick } 155256817Smckusick w->env->hints = hints_create(); 156256817Smckusick if(w->env->hints && !hints_apply_cfg(w->env->hints, cfg)) { 157256817Smckusick hints_delete(w->env->hints); 158256817Smckusick w->env->hints = NULL; 159256817Smckusick } 160256817Smckusick if(cfg->ssl_upstream) { 161256817Smckusick w->sslctx = connect_sslctx_create(NULL, NULL, NULL); 162256817Smckusick if(!w->sslctx) { 163256817Smckusick /* to make the setup fail after unlock */ 164256817Smckusick hints_delete(w->env->hints); 165256817Smckusick w->env->hints = NULL; 166256817Smckusick } 167256817Smckusick } 168256817Smckusick if(!w->is_bg || w->is_bg_thread) { 169256817Smckusick lock_basic_unlock(&ctx->cfglock); 170256817Smckusick } 171256817Smckusick if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds || 172256817Smckusick !w->env->hints) { 173256817Smckusick libworker_delete(w); 174256817Smckusick return NULL; 175256817Smckusick } 176256817Smckusick w->env->worker = (struct worker*)w; 177256817Smckusick w->env->probe_timer = NULL; 178256817Smckusick seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^ 179256817Smckusick (((unsigned int)w->thread_num)<<17); 18036201Sjulian seed ^= (unsigned int)w->env->alloc->next_id; 18136201Sjulian if(!w->is_bg || w->is_bg_thread) { 18236201Sjulian lock_basic_lock(&ctx->cfglock); 18336201Sjulian } 18436201Sjulian if(!(w->env->rnd = ub_initstate(seed, ctx->seed_rnd))) { 18536201Sjulian if(!w->is_bg || w->is_bg_thread) { 18636201Sjulian lock_basic_unlock(&ctx->cfglock); 18736201Sjulian } 18836201Sjulian seed = 0; 18936201Sjulian libworker_delete(w); 19036201Sjulian return NULL; 19160938Sjake } 19236201Sjulian if(!w->is_bg || w->is_bg_thread) { 19336201Sjulian lock_basic_unlock(&ctx->cfglock); 19436201Sjulian } 19536201Sjulian if(1) { 19636201Sjulian /* primitive lockout for threading: if it overwrites another 19736201Sjulian * thread it is like wiping the cache (which is likely empty 19836201Sjulian * at the start) */ 19936201Sjulian /* note we are holding the ctx lock in normal threaded 20036201Sjulian * cases so that is solved properly, it is only for many ctx 201207141Sjeff * in different threads that this may clash */ 202156203Sjeff static int done_raninit = 0; 203207141Sjeff if(!done_raninit) { 204207141Sjeff done_raninit = 1; 20536201Sjulian hash_set_raninit((uint32_t)ub_random(w->env->rnd)); 206262678Spfg } 207262678Spfg } 208262678Spfg seed = 0; 209262678Spfg 210207141Sjeff if(eb) 211262678Spfg w->base = comm_base_create_event(eb); 212262678Spfg else w->base = comm_base_create(0); 213262678Spfg if(!w->base) { 214262678Spfg libworker_delete(w); 215262678Spfg return NULL; 216262678Spfg } 217262678Spfg if(!w->is_bg || w->is_bg_thread) { 218262678Spfg lock_basic_lock(&ctx->cfglock); 219262678Spfg } 220262678Spfg numports = cfg_condense_ports(cfg, &ports); 221262678Spfg if(numports == 0) { 222207141Sjeff int locked = !w->is_bg || w->is_bg_thread; 223207141Sjeff libworker_delete(w); 224207141Sjeff if(locked) { 225207141Sjeff lock_basic_unlock(&ctx->cfglock); 226207141Sjeff } 227207141Sjeff return NULL; 228207141Sjeff } 229207141Sjeff w->back = outside_network_create(w->base, cfg->msg_buffer_size, 230207141Sjeff (size_t)cfg->outgoing_num_ports, cfg->out_ifs, 231222958Sjeff cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6, 232207141Sjeff cfg->do_tcp?cfg->outgoing_num_tcp:0, 233222958Sjeff w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id, 23436201Sjulian ports, numports, cfg->unwanted_threshold, 23536201Sjulian &libworker_alloc_cleanup, w, cfg->do_udp, w->sslctx, 23636201Sjulian cfg->delay_close); 23736201Sjulian if(!w->is_bg || w->is_bg_thread) { 23860938Sjake lock_basic_unlock(&ctx->cfglock); 23960938Sjake } 24060938Sjake free(ports); 24160938Sjake if(!w->back) { 24260938Sjake libworker_delete(w); 24360938Sjake return NULL; 24460938Sjake } 245207141Sjeff w->env->mesh = mesh_create(&ctx->mods, w->env); 246207141Sjeff if(!w->env->mesh) { 247207141Sjeff libworker_delete(w); 248207141Sjeff return NULL; 249207141Sjeff } 250222958Sjeff w->env->send_query = &libworker_send_query; 251207141Sjeff w->env->detach_subs = &mesh_detach_subs; 252222958Sjeff w->env->attach_sub = &mesh_attach_sub; 253207141Sjeff w->env->kill_sub = &mesh_state_delete; 254207141Sjeff w->env->detect_cycle = &mesh_detect_cycle; 255222958Sjeff comm_base_timept(w->base, &w->env->now, &w->env->now_tv); 25636201Sjulian return w; 25736201Sjulian} 25836201Sjulian 25936201Sjulianstruct libworker* libworker_create_event(struct ub_ctx* ctx, 26036201Sjulian struct event_base* eb) 26136201Sjulian{ 26236201Sjulian return libworker_setup(ctx, 0, eb); 26336201Sjulian} 26436201Sjulian 26536201Sjulian/** handle cancel command for bg worker */ 26636201Sjulianstatic void 26736201Sjulianhandle_cancel(struct libworker* w, uint8_t* buf, uint32_t len) 26836201Sjulian{ 26936201Sjulian struct ctx_query* q; 27036201Sjulian if(w->is_bg_thread) { 27136201Sjulian lock_basic_lock(&w->ctx->cfglock); 27236201Sjulian q = context_deserialize_cancel(w->ctx, buf, len); 27336201Sjulian lock_basic_unlock(&w->ctx->cfglock); 27436201Sjulian } else { 275262678Spfg q = context_deserialize_cancel(w->ctx, buf, len); 276262678Spfg } 27736201Sjulian if(!q) { 27836201Sjulian /* probably simply lookup failed, i.e. the message had been 27936201Sjulian * processed and answered before the cancel arrived */ 28060938Sjake return; 28136201Sjulian } 28236201Sjulian q->cancelled = 1; 283207141Sjeff free(buf); 28436201Sjulian} 28536201Sjulian 28636201Sjulian/** do control command coming into bg server */ 287207141Sjeffstatic void 28836201Sjulianlibworker_do_cmd(struct libworker* w, uint8_t* msg, uint32_t len) 28936201Sjulian{ 29036201Sjulian switch(context_serial_getcmd(msg, len)) { 29136201Sjulian default: 29236225Sjulian case UB_LIBCMD_ANSWER: 29336225Sjulian log_err("unknown command for bg worker %d", 29436225Sjulian (int)context_serial_getcmd(msg, len)); 29536225Sjulian /* and fall through to quit */ 29636225Sjulian case UB_LIBCMD_QUIT: 29736225Sjulian free(msg); 29836225Sjulian comm_base_exit(w->base); 29936225Sjulian break; 30036225Sjulian case UB_LIBCMD_NEWQUERY: 30136225Sjulian handle_newq(w, msg, len); 30236225Sjulian break; 30336225Sjulian case UB_LIBCMD_CANCEL: 30436225Sjulian handle_cancel(w, msg, len); 30536225Sjulian break; 30636201Sjulian } 30736201Sjulian} 30836225Sjulian 30936201Sjulian/** handle control command coming into server */ 31036201Sjulianvoid 31136225Sjulianlibworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), 31236225Sjulian uint8_t* msg, size_t len, int err, void* arg) 31336225Sjulian{ 31436201Sjulian struct libworker* w = (struct libworker*)arg; 31536201Sjulian 31636201Sjulian if(err != 0) { 31736225Sjulian free(msg); 31836225Sjulian /* it is of no use to go on, exit */ 31936225Sjulian comm_base_exit(w->base); 32036225Sjulian return; 32136225Sjulian } 32236225Sjulian libworker_do_cmd(w, msg, len); /* also frees the buf */ 32336225Sjulian} 32436201Sjulian 32536201Sjulian/** the background thread func */ 32636201Sjulianstatic void* 32736206Sjulianlibworker_dobg(void* arg) 32836225Sjulian{ 32936225Sjulian /* setup */ 33036225Sjulian uint32_t m; 33136206Sjulian struct libworker* w = (struct libworker*)arg; 33236206Sjulian struct ub_ctx* ctx; 33336206Sjulian if(!w) { 33436206Sjulian log_err("libunbound bg worker init failed, nomem"); 33536206Sjulian return NULL; 33636201Sjulian } 33736201Sjulian ctx = w->ctx; 33836201Sjulian log_thread_set(&w->thread_num); 33936201Sjulian#ifdef THREADS_DISABLED 34060938Sjake /* we are forked */ 341207141Sjeff w->is_bg_thread = 0; 34236201Sjulian /* close non-used parts of the pipes */ 34336201Sjulian tube_close_write(ctx->qq_pipe); 34436201Sjulian tube_close_read(ctx->rr_pipe); 345207141Sjeff#endif 34660938Sjake if(!tube_setup_bg_listen(ctx->qq_pipe, w->base, 347207141Sjeff libworker_handle_control_cmd, w)) { 348207141Sjeff log_err("libunbound bg worker init failed, no bglisten"); 349207141Sjeff return NULL; 350100344Smckusick } 35136201Sjulian if(!tube_setup_bg_write(ctx->rr_pipe, w->base)) { 352207141Sjeff log_err("libunbound bg worker init failed, no bgwrite"); 35336201Sjulian return NULL; 35436225Sjulian } 35536225Sjulian 35636201Sjulian /* do the work */ 35736201Sjulian comm_base_dispatch(w->base); 358100344Smckusick 359100344Smckusick /* cleanup */ 360222958Sjeff m = UB_LIBCMD_QUIT; 36198542Smckusick tube_remove_bg_listen(w->ctx->qq_pipe); 36298542Smckusick tube_remove_bg_write(w->ctx->rr_pipe); 36398542Smckusick libworker_delete(w); 36498542Smckusick (void)tube_write_msg(ctx->rr_pipe, (uint8_t*)&m, 36536201Sjulian (uint32_t)sizeof(m), 0); 366262678Spfg#ifdef THREADS_DISABLED 367262678Spfg /* close pipes from forked process before exit */ 36836201Sjulian tube_close_read(ctx->qq_pipe); 36936201Sjulian tube_close_write(ctx->rr_pipe); 37036201Sjulian#endif 37136201Sjulian return NULL; 37236201Sjulian} 37336201Sjulian 37436201Sjulianint libworker_bg(struct ub_ctx* ctx) 37536201Sjulian{ 37636201Sjulian struct libworker* w; 37736201Sjulian /* fork or threadcreate */ 37836201Sjulian lock_basic_lock(&ctx->cfglock); 37936201Sjulian if(ctx->dothread) { 38036201Sjulian lock_basic_unlock(&ctx->cfglock); 381207141Sjeff w = libworker_setup(ctx, 1, NULL); 382222958Sjeff if(!w) return UB_NOMEM; 383222958Sjeff w->is_bg_thread = 1; 384207141Sjeff#ifdef ENABLE_LOCK_CHECKS 38536201Sjulian w->thread_num = 1; /* for nicer DEBUG checklocks */ 38636201Sjulian#endif 387207141Sjeff ub_thread_create(&ctx->bg_tid, libworker_dobg, w); 38836201Sjulian } else { 389207141Sjeff lock_basic_unlock(&ctx->cfglock); 39036201Sjulian#ifndef HAVE_FORK 391207141Sjeff /* no fork on windows */ 39236201Sjulian return UB_FORKFAIL; 393207141Sjeff#else /* HAVE_FORK */ 394207141Sjeff switch((ctx->bg_pid=fork())) { 395207141Sjeff case 0: 396222958Sjeff w = libworker_setup(ctx, 1, NULL); 397222958Sjeff if(!w) fatal_exit("out of memory"); 39836201Sjulian /* close non-used parts of the pipes */ 39936201Sjulian tube_close_write(ctx->qq_pipe); 40036201Sjulian tube_close_read(ctx->rr_pipe); 401207141Sjeff (void)libworker_dobg(w); 402207141Sjeff exit(0); 403207141Sjeff break; 404207141Sjeff case -1: 405212617Smckusick return UB_FORKFAIL; 406212617Smckusick default: 407212617Smckusick /* close non-used parts, so that the worker 408207141Sjeff * bgprocess gets 'pipe closed' when the 409207141Sjeff * main process exits */ 410212617Smckusick tube_close_read(ctx->qq_pipe); 411207141Sjeff tube_close_write(ctx->rr_pipe); 412212617Smckusick break; 413212617Smckusick } 414207141Sjeff#endif /* HAVE_FORK */ 415212617Smckusick } 416212617Smckusick return UB_NOERROR; 417207141Sjeff} 418212617Smckusick 419207141Sjeff/** get msg reply struct (in temp region) */ 420212617Smckusickstatic struct reply_info* 421207141Sjeffparse_reply(sldns_buffer* pkt, struct regional* region, struct query_info* qi) 422207141Sjeff{ 423207141Sjeff struct reply_info* rep; 42436201Sjulian struct msg_parse* msg; 42536201Sjulian if(!(msg = regional_alloc(region, sizeof(*msg)))) { 42636201Sjulian return NULL; 42736201Sjulian } 42836201Sjulian memset(msg, 0, sizeof(*msg)); 42936201Sjulian sldns_buffer_set_position(pkt, 0); 43036201Sjulian if(parse_packet(pkt, msg, region) != 0) 43136201Sjulian return 0; 43236201Sjulian if(!parse_create_msg(pkt, msg, NULL, qi, &rep, region)) { 43336201Sjulian return 0; 43436201Sjulian } 43536201Sjulian return rep; 43636201Sjulian} 43736201Sjulian 43876724Smckusick/** insert canonname */ 43976724Smckusickstatic int 44076724Smckusickfill_canon(struct ub_result* res, uint8_t* s) 44176724Smckusick{ 44276724Smckusick char buf[255+2]; 44376724Smckusick dname_str(s, buf); 44476724Smckusick res->canonname = strdup(buf); 44576724Smckusick return res->canonname != 0; 44676724Smckusick} 44776724Smckusick 44876724Smckusick/** fill data into result */ 44936201Sjulianstatic int 45036201Sjulianfill_res(struct ub_result* res, struct ub_packed_rrset_key* answer, 451207141Sjeff uint8_t* finalcname, struct query_info* rq, struct reply_info* rep) 452256817Smckusick{ 453256817Smckusick size_t i; 45460938Sjake struct packed_rrset_data* data; 45536201Sjulian res->ttl = 0; 456207141Sjeff if(!answer) { 457207141Sjeff if(finalcname) { 458207141Sjeff if(!fill_canon(res, finalcname)) 459207141Sjeff return 0; /* out of memory */ 46036201Sjulian } 461207141Sjeff if(rep->rrset_count != 0) 462207141Sjeff res->ttl = (int)rep->ttl; 463207141Sjeff res->data = (char**)calloc(1, sizeof(char*)); 46436201Sjulian res->len = (int*)calloc(1, sizeof(int)); 46536201Sjulian return (res->data && res->len); 46636201Sjulian } 46736201Sjulian data = (struct packed_rrset_data*)answer->entry.data; 46836201Sjulian if(query_dname_compare(rq->qname, answer->rk.dname) != 0) { 46936201Sjulian if(!fill_canon(res, answer->rk.dname)) 47036201Sjulian return 0; /* out of memory */ 47136201Sjulian } else res->canonname = NULL; 47236201Sjulian res->data = (char**)calloc(data->count+1, sizeof(char*)); 47336201Sjulian res->len = (int*)calloc(data->count+1, sizeof(int)); 47436201Sjulian if(!res->data || !res->len) 47536201Sjulian return 0; /* out of memory */ 47636201Sjulian for(i=0; i<data->count; i++) { 47736201Sjulian /* remove rdlength from rdata */ 47836201Sjulian res->len[i] = (int)(data->rr_len[i] - 2); 47936201Sjulian res->data[i] = memdup(data->rr_data[i]+2, (size_t)res->len[i]); 48036201Sjulian if(!res->data[i]) 48136201Sjulian return 0; /* out of memory */ 48236201Sjulian } 48336201Sjulian /* ttl for positive answers, from CNAME and answer RRs */ 48436201Sjulian if(data->count != 0) { 485207141Sjeff size_t j; 486222958Sjeff res->ttl = (int)data->ttl; 487207141Sjeff for(j=0; j<rep->an_numrrsets; j++) { 48836201Sjulian struct packed_rrset_data* d = 489222958Sjeff (struct packed_rrset_data*)rep->rrsets[j]-> 490207141Sjeff entry.data; 491207141Sjeff if((int)d->ttl < res->ttl) 49236201Sjulian res->ttl = (int)d->ttl; 49336201Sjulian } 494222958Sjeff } 49536201Sjulian /* ttl for negative answers */ 49636201Sjulian if(data->count == 0 && rep->rrset_count != 0) 49736201Sjulian res->ttl = (int)rep->ttl; 49836201Sjulian res->data[data->count] = NULL; 49936201Sjulian res->len[data->count] = 0; 50036201Sjulian return 1; 50136201Sjulian} 50236201Sjulian 50336201Sjulian/** fill result from parsed message, on error fills servfail */ 50436201Sjulianvoid 50536201Sjulianlibworker_enter_result(struct ub_result* res, sldns_buffer* buf, 50636201Sjulian struct regional* temp, enum sec_status msg_security) 50736201Sjulian{ 50836201Sjulian struct query_info rq; 50936201Sjulian struct reply_info* rep; 51036201Sjulian res->rcode = LDNS_RCODE_SERVFAIL; 511207141Sjeff rep = parse_reply(buf, temp, &rq); 512207141Sjeff if(!rep) { 51360938Sjake log_err("cannot parse buf"); 51436201Sjulian return; /* error parsing buf, or out of memory */ 515207141Sjeff } 516222958Sjeff if(!fill_res(res, reply_find_answer_rrset(&rq, rep), 517207141Sjeff reply_find_final_cname_target(&rq, rep), &rq, rep)) 51836201Sjulian return; /* out of memory */ 519207141Sjeff /* rcode, havedata, nxdomain, secure, bogus */ 520207141Sjeff res->rcode = (int)FLAGS_GET_RCODE(rep->flags); 521207141Sjeff if(res->data && res->data[0]) 52236201Sjulian res->havedata = 1; 52336201Sjulian if(res->rcode == LDNS_RCODE_NXDOMAIN) 524207141Sjeff res->nxdomain = 1; 525207141Sjeff if(msg_security == sec_status_secure) 526207141Sjeff res->secure = 1; 527207141Sjeff if(msg_security == sec_status_bogus) 528207141Sjeff res->bogus = 1; 529207141Sjeff} 530207141Sjeff 531207141Sjeff/** fillup fg results */ 532207141Sjeffstatic void 533207141Sjefflibworker_fillup_fg(struct ctx_query* q, int rcode, sldns_buffer* buf, 53436201Sjulian enum sec_status s, char* why_bogus) 53536201Sjulian{ 53636201Sjulian if(why_bogus) 53736201Sjulian q->res->why_bogus = strdup(why_bogus); 538207141Sjeff if(rcode != 0) { 53936201Sjulian q->res->rcode = rcode; 54036201Sjulian q->msg_security = s; 54136201Sjulian return; 542207141Sjeff } 543220406Sjeff 544207141Sjeff q->res->rcode = LDNS_RCODE_SERVFAIL; 54598542Smckusick q->msg_security = 0; 54636201Sjulian q->msg = memdup(sldns_buffer_begin(buf), sldns_buffer_limit(buf)); 54736201Sjulian q->msg_len = sldns_buffer_limit(buf); 548223127Smckusick if(!q->msg) { 54936201Sjulian return; /* the error is in the rcode */ 55036201Sjulian } 55136201Sjulian 55236201Sjulian /* canonname and results */ 55336201Sjulian q->msg_security = s; 55436201Sjulian libworker_enter_result(q->res, buf, q->w->env->scratch, s); 555207141Sjeff} 556207141Sjeff 557207141Sjeffvoid 558207141Sjefflibworker_fg_done_cb(void* arg, int rcode, sldns_buffer* buf, enum sec_status s, 55936201Sjulian char* why_bogus) 56036201Sjulian{ 56136201Sjulian struct ctx_query* q = (struct ctx_query*)arg; 562148608Sups /* fg query is done; exit comm base */ 563222958Sjeff comm_base_exit(q->w->base); 564222958Sjeff 565207141Sjeff libworker_fillup_fg(q, rcode, buf, s, why_bogus); 566207141Sjeff} 567222958Sjeff 568222958Sjeff/** setup qinfo and edns */ 569222958Sjeffstatic int 570222958Sjeffsetup_qinfo_edns(struct libworker* w, struct ctx_query* q, 571222958Sjeff struct query_info* qinfo, struct edns_data* edns) 572222958Sjeff{ 573223772Sjeff qinfo->qtype = (uint16_t)q->res->qtype; 574222958Sjeff qinfo->qclass = (uint16_t)q->res->qclass; 575223127Smckusick qinfo->qname = sldns_str2wire_dname(q->res->qname, &qinfo->qname_len); 57698542Smckusick if(!qinfo->qname) { 577207141Sjeff return 0; 578222958Sjeff } 57936201Sjulian edns->edns_present = 1; 58036201Sjulian edns->ext_rcode = 0; 58136201Sjulian edns->edns_version = 0; 582207141Sjeff edns->bits = EDNS_DO; 583207141Sjeff if(sldns_buffer_capacity(w->back->udp_buff) < 65535) 584212617Smckusick edns->udp_size = (uint16_t)sldns_buffer_capacity( 585207141Sjeff w->back->udp_buff); 586207141Sjeff else edns->udp_size = 65535; 587207141Sjeff return 1; 588207141Sjeff} 589207141Sjeff 590207141Sjeffint libworker_fg(struct ub_ctx* ctx, struct ctx_query* q) 591212617Smckusick{ 592207141Sjeff struct libworker* w = libworker_setup(ctx, 0, NULL); 593222958Sjeff uint16_t qflags, qid; 594222958Sjeff struct query_info qinfo; 595222958Sjeff struct edns_data edns; 596207141Sjeff if(!w) 597207141Sjeff return UB_INITFAIL; 598222958Sjeff if(!setup_qinfo_edns(w, q, &qinfo, &edns)) { 599207141Sjeff libworker_delete(w); 600207141Sjeff return UB_SYNTAX; 601222958Sjeff } 602222958Sjeff qid = 0; 603222958Sjeff qflags = BIT_RD; 604222958Sjeff q->w = w; 605207141Sjeff /* see if there is a fixed answer */ 606207141Sjeff sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid); 607207141Sjeff sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags); 608207141Sjeff if(local_zones_answer(ctx->local_zones, &qinfo, &edns, 609207141Sjeff w->back->udp_buff, w->env->scratch)) { 610207141Sjeff regional_free_all(w->env->scratch); 611207141Sjeff libworker_fillup_fg(q, LDNS_RCODE_NOERROR, 612207141Sjeff w->back->udp_buff, sec_status_insecure, NULL); 613207141Sjeff libworker_delete(w); 614207141Sjeff free(qinfo.qname); 615212617Smckusick return UB_NOERROR; 616207141Sjeff } 617207141Sjeff /* process new query */ 618207141Sjeff if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, 619207141Sjeff w->back->udp_buff, qid, libworker_fg_done_cb, q)) { 62036201Sjulian free(qinfo.qname); 62136201Sjulian return UB_NOMEM; 62236201Sjulian } 62336201Sjulian free(qinfo.qname); 62436201Sjulian 62536201Sjulian /* wait for reply */ 62636201Sjulian comm_base_dispatch(w->base); 62736201Sjulian 62836201Sjulian libworker_delete(w); 62936201Sjulian return UB_NOERROR; 630207141Sjeff} 63136201Sjulian 63236201Sjulianvoid 63336201Sjulianlibworker_event_done_cb(void* arg, int rcode, sldns_buffer* buf, 63436201Sjulian enum sec_status s, char* why_bogus) 63536201Sjulian{ 63636201Sjulian struct ctx_query* q = (struct ctx_query*)arg; 63736201Sjulian ub_event_callback_t cb = (ub_event_callback_t)q->cb; 63836201Sjulian void* cb_arg = q->cb_arg; 63936201Sjulian int cancelled = q->cancelled; 64036201Sjulian 64136201Sjulian /* delete it now */ 64236201Sjulian struct ub_ctx* ctx = q->w->ctx; 64336201Sjulian lock_basic_lock(&ctx->cfglock); 64436201Sjulian (void)rbtree_delete(&ctx->queries, q->node.key); 64536201Sjulian ctx->num_async--; 64636201Sjulian context_query_delete(q); 64736201Sjulian lock_basic_unlock(&ctx->cfglock); 64836201Sjulian 64936201Sjulian if(!cancelled) { 65036201Sjulian /* call callback */ 65136201Sjulian int sec = 0; 65236201Sjulian if(s == sec_status_bogus) 65336201Sjulian sec = 1; 65436201Sjulian else if(s == sec_status_secure) 65536201Sjulian sec = 2; 65636201Sjulian (*cb)(cb_arg, rcode, (void*)sldns_buffer_begin(buf), 65736201Sjulian (int)sldns_buffer_limit(buf), sec, why_bogus); 65836201Sjulian } 65936201Sjulian} 66036201Sjulian 66136201Sjulianint libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q, 66236201Sjulian int* async_id) 663207141Sjeff{ 664207141Sjeff struct libworker* w = ctx->event_worker; 665207141Sjeff uint16_t qflags, qid; 666207141Sjeff struct query_info qinfo; 667207141Sjeff struct edns_data edns; 66836201Sjulian if(!w) 66936201Sjulian return UB_INITFAIL; 67036225Sjulian if(!setup_qinfo_edns(w, q, &qinfo, &edns)) 67136201Sjulian return UB_SYNTAX; 67260938Sjake qid = 0; 67336201Sjulian qflags = BIT_RD; 67436201Sjulian q->w = w; 67536201Sjulian /* see if there is a fixed answer */ 67636201Sjulian sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid); 67736201Sjulian sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags); 67836201Sjulian if(local_zones_answer(ctx->local_zones, &qinfo, &edns, 679207141Sjeff w->back->udp_buff, w->env->scratch)) { 68036201Sjulian regional_free_all(w->env->scratch); 681262678Spfg free(qinfo.qname); 682262678Spfg libworker_event_done_cb(q, LDNS_RCODE_NOERROR, 68336201Sjulian w->back->udp_buff, sec_status_insecure, NULL); 68436201Sjulian return UB_NOERROR; 68536201Sjulian } 68636201Sjulian /* process new query */ 68736201Sjulian if(async_id) 68836201Sjulian *async_id = q->querynum; 68936201Sjulian if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, 69036201Sjulian w->back->udp_buff, qid, libworker_event_done_cb, q)) { 69136201Sjulian free(qinfo.qname); 69236201Sjulian return UB_NOMEM; 69336201Sjulian } 69436201Sjulian free(qinfo.qname); 69536201Sjulian return UB_NOERROR; 69636201Sjulian} 69736201Sjulian 69836201Sjulian/** add result to the bg worker result queue */ 69936201Sjulianstatic void 70036201Sjulianadd_bg_result(struct libworker* w, struct ctx_query* q, sldns_buffer* pkt, 70136201Sjulian int err, char* reason) 70236201Sjulian{ 70336201Sjulian uint8_t* msg = NULL; 70436201Sjulian uint32_t len = 0; 70536201Sjulian 706207141Sjeff /* serialize and delete unneeded q */ 70736201Sjulian if(w->is_bg_thread) { 70836201Sjulian lock_basic_lock(&w->ctx->cfglock); 70936201Sjulian if(reason) 71036201Sjulian q->res->why_bogus = strdup(reason); 71136201Sjulian if(pkt) { 712207141Sjeff q->msg_len = sldns_buffer_remaining(pkt); 71346618Smckusick q->msg = memdup(sldns_buffer_begin(pkt), q->msg_len); 71460938Sjake if(!q->msg) 71536201Sjulian msg = context_serialize_answer(q, UB_NOMEM, 71636201Sjulian NULL, &len); 71736201Sjulian else msg = context_serialize_answer(q, err, 71836201Sjulian NULL, &len); 71936201Sjulian } else msg = context_serialize_answer(q, err, NULL, &len); 72036201Sjulian lock_basic_unlock(&w->ctx->cfglock); 72136201Sjulian } else { 72236201Sjulian if(reason) 72336201Sjulian q->res->why_bogus = strdup(reason); 72436201Sjulian msg = context_serialize_answer(q, err, pkt, &len); 72536201Sjulian (void)rbtree_delete(&w->ctx->queries, q->node.key); 72636201Sjulian w->ctx->num_async--; 72760938Sjake context_query_delete(q); 728207141Sjeff } 729207141Sjeff 73036201Sjulian if(!msg) { 731222958Sjeff log_err("out of memory for async answer"); 73236201Sjulian return; 73336201Sjulian } 73436201Sjulian if(!tube_queue_item(w->ctx->rr_pipe, msg, len)) { 73536201Sjulian log_err("out of memory for async answer"); 736207141Sjeff return; 73736201Sjulian } 738262678Spfg} 739262678Spfg 74076724Smckusickvoid 74176724Smckusicklibworker_bg_done_cb(void* arg, int rcode, sldns_buffer* buf, enum sec_status s, 74276724Smckusick char* why_bogus) 74376724Smckusick{ 74476724Smckusick struct ctx_query* q = (struct ctx_query*)arg; 74576724Smckusick 74676724Smckusick if(q->cancelled) { 74776724Smckusick if(q->w->is_bg_thread) { 74876724Smckusick /* delete it now */ 74976724Smckusick struct ub_ctx* ctx = q->w->ctx; 75076724Smckusick lock_basic_lock(&ctx->cfglock); 75176724Smckusick (void)rbtree_delete(&ctx->queries, q->node.key); 75276724Smckusick ctx->num_async--; 75376724Smckusick context_query_delete(q); 75476724Smckusick lock_basic_unlock(&ctx->cfglock); 75576724Smckusick } 75676724Smckusick /* cancelled, do not give answer */ 75776724Smckusick return; 758207141Sjeff } 759207141Sjeff q->msg_security = s; 760207141Sjeff if(!buf) 761207141Sjeff buf = q->w->env->scratch_buffer; 76276724Smckusick if(rcode != 0) { 76376724Smckusick error_encode(buf, rcode, NULL, 0, BIT_RD, NULL); 76476724Smckusick } 765222958Sjeff add_bg_result(q->w, q, buf, UB_NOERROR, why_bogus); 76676724Smckusick} 767207141Sjeff 76876724Smckusick 769207141Sjeff/** handle new query command for bg worker */ 770207141Sjeffstatic void 771207141Sjeffhandle_newq(struct libworker* w, uint8_t* buf, uint32_t len) 772207141Sjeff{ 773207141Sjeff uint16_t qflags, qid; 774207141Sjeff struct query_info qinfo; 775212617Smckusick struct edns_data edns; 776207141Sjeff struct ctx_query* q; 777207141Sjeff if(w->is_bg_thread) { 778212617Smckusick lock_basic_lock(&w->ctx->cfglock); 779207141Sjeff q = context_lookup_new_query(w->ctx, buf, len); 780207141Sjeff lock_basic_unlock(&w->ctx->cfglock); 781207141Sjeff } else { 782207141Sjeff q = context_deserialize_new_query(w->ctx, buf, len); 783207141Sjeff } 784207141Sjeff free(buf); 785207141Sjeff if(!q) { 786207141Sjeff log_err("failed to deserialize newq"); 787207141Sjeff return; 788207141Sjeff } 789207141Sjeff if(!setup_qinfo_edns(w, q, &qinfo, &edns)) { 790207141Sjeff add_bg_result(w, q, NULL, UB_SYNTAX, NULL); 791207141Sjeff return; 792207141Sjeff } 793207141Sjeff qid = 0; 794207141Sjeff qflags = BIT_RD; 795207141Sjeff /* see if there is a fixed answer */ 796207141Sjeff sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid); 797207141Sjeff sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags); 798207141Sjeff if(local_zones_answer(w->ctx->local_zones, &qinfo, &edns, 799207141Sjeff w->back->udp_buff, w->env->scratch)) { 800207141Sjeff regional_free_all(w->env->scratch); 801212617Smckusick q->msg_security = sec_status_insecure; 802212617Smckusick add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL); 803207141Sjeff free(qinfo.qname); 804207141Sjeff return; 805207141Sjeff } 806207141Sjeff q->w = w; 807207141Sjeff /* process new query */ 808207141Sjeff if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, 809207141Sjeff w->back->udp_buff, qid, libworker_bg_done_cb, q)) { 810207141Sjeff add_bg_result(w, q, NULL, UB_NOMEM, NULL); 811207141Sjeff } 812207141Sjeff free(qinfo.qname); 813207141Sjeff} 814207141Sjeff 815207141Sjeffvoid libworker_alloc_cleanup(void* arg) 816207141Sjeff{ 817207141Sjeff struct libworker* w = (struct libworker*)arg; 818207141Sjeff slabhash_clear(&w->env->rrset_cache->table); 819207141Sjeff slabhash_clear(w->env->msg_cache); 820207141Sjeff} 821207141Sjeff 822207141Sjeffstruct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen, 823207141Sjeff uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, 824212617Smckusick int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen, 825212617Smckusick uint8_t* zone, size_t zonelen, struct module_qstate* q) 826207141Sjeff{ 827212617Smckusick struct libworker* w = (struct libworker*)q->env->worker; 828207141Sjeff struct outbound_entry* e = (struct outbound_entry*)regional_alloc( 829207141Sjeff q->region, sizeof(*e)); 830207141Sjeff if(!e) 831212617Smckusick return NULL; 832212617Smckusick e->qstate = q; 833212617Smckusick e->qsent = outnet_serviced_query(w->back, qname, 834212617Smckusick qnamelen, qtype, qclass, flags, dnssec, want_dnssec, 835212617Smckusick q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr, 836212617Smckusick addrlen, zone, zonelen, libworker_handle_service_reply, e, 837212617Smckusick w->back->udp_buff); 838207141Sjeff if(!e->qsent) { 839212617Smckusick return NULL; 840212617Smckusick } 841212617Smckusick return e; 842212617Smckusick} 843212617Smckusick 844212617Smckusickint 845212617Smckusicklibworker_handle_reply(struct comm_point* c, void* arg, int error, 846207141Sjeff struct comm_reply* reply_info) 847207141Sjeff{ 848207141Sjeff struct module_qstate* q = (struct module_qstate*)arg; 849207141Sjeff struct libworker* lw = (struct libworker*)q->env->worker; 850207141Sjeff struct outbound_entry e; 851207141Sjeff e.qstate = q; 852207141Sjeff e.qsent = NULL; 853207141Sjeff 854207141Sjeff if(error != 0) { 855207141Sjeff mesh_report_reply(lw->env->mesh, &e, reply_info, error); 856207141Sjeff return 0; 857212617Smckusick } 858212617Smckusick /* sanity check. */ 859207141Sjeff if(!LDNS_QR_WIRE(sldns_buffer_begin(c->buffer)) 860207141Sjeff || LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) != 861212617Smckusick LDNS_PACKET_QUERY 862207141Sjeff || LDNS_QDCOUNT(sldns_buffer_begin(c->buffer)) > 1) { 863212617Smckusick /* error becomes timeout for the module as if this reply 864212617Smckusick * never arrived. */ 865220406Sjeff mesh_report_reply(lw->env->mesh, &e, reply_info, 866212617Smckusick NETEVENT_TIMEOUT); 867212617Smckusick return 0; 868222958Sjeff } 869212617Smckusick mesh_report_reply(lw->env->mesh, &e, reply_info, NETEVENT_NOERROR); 870212617Smckusick return 0; 871207141Sjeff} 872207141Sjeff 873207141Sjeffint 874222958Sjefflibworker_handle_service_reply(struct comm_point* c, void* arg, int error, 875222958Sjeff struct comm_reply* reply_info) 876222958Sjeff{ 877222958Sjeff struct outbound_entry* e = (struct outbound_entry*)arg; 878222958Sjeff struct libworker* lw = (struct libworker*)e->qstate->env->worker; 879222958Sjeff 880222958Sjeff if(error != 0) { 881222958Sjeff mesh_report_reply(lw->env->mesh, e, reply_info, error); 882222958Sjeff return 0; 883222958Sjeff } 884222958Sjeff /* sanity check. */ 885222958Sjeff if(!LDNS_QR_WIRE(sldns_buffer_begin(c->buffer)) 886207141Sjeff || LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) != 887207141Sjeff LDNS_PACKET_QUERY 888212617Smckusick || LDNS_QDCOUNT(sldns_buffer_begin(c->buffer)) > 1) { 889207141Sjeff /* error becomes timeout for the module as if this reply 890207141Sjeff * never arrived. */ 891222958Sjeff mesh_report_reply(lw->env->mesh, e, reply_info, 892212617Smckusick NETEVENT_TIMEOUT); 893212617Smckusick return 0; 894222958Sjeff } 895212617Smckusick mesh_report_reply(lw->env->mesh, e, reply_info, NETEVENT_NOERROR); 896207141Sjeff return 0; 897207141Sjeff} 898207141Sjeff 899207141Sjeff/* --- fake callbacks for fptr_wlist to work --- */ 900207141Sjeffvoid worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), 901207141Sjeff uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len), 902207141Sjeff int ATTR_UNUSED(error), void* ATTR_UNUSED(arg)) 903207141Sjeff{ 904212617Smckusick log_assert(0); 905207141Sjeff} 906212617Smckusick 907212617Smckusickint worker_handle_request(struct comm_point* ATTR_UNUSED(c), 908212617Smckusick void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 909212617Smckusick struct comm_reply* ATTR_UNUSED(repinfo)) 910222958Sjeff{ 911212617Smckusick log_assert(0); 912207141Sjeff return 0; 913207141Sjeff} 914207141Sjeff 915222958Sjeffint worker_handle_reply(struct comm_point* ATTR_UNUSED(c), 916207141Sjeff void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 917207141Sjeff struct comm_reply* ATTR_UNUSED(reply_info)) 918222958Sjeff{ 919222958Sjeff log_assert(0); 920222958Sjeff return 0; 921222958Sjeff} 922207141Sjeff 923207141Sjeffint worker_handle_service_reply(struct comm_point* ATTR_UNUSED(c), 924207141Sjeff void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 925222958Sjeff struct comm_reply* ATTR_UNUSED(reply_info)) 926222958Sjeff{ 927222958Sjeff log_assert(0); 928222958Sjeff return 0; 929222958Sjeff} 930222958Sjeff 931222958Sjeffint remote_accept_callback(struct comm_point* ATTR_UNUSED(c), 932222958Sjeff void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 933222958Sjeff struct comm_reply* ATTR_UNUSED(repinfo)) 934222958Sjeff{ 935222958Sjeff log_assert(0); 936207141Sjeff return 0; 937207141Sjeff} 938212617Smckusick 939212617Smckusickint remote_control_callback(struct comm_point* ATTR_UNUSED(c), 940207141Sjeff void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 941207141Sjeff struct comm_reply* ATTR_UNUSED(repinfo)) 942212617Smckusick{ 943207141Sjeff log_assert(0); 944212617Smckusick return 0; 945207141Sjeff} 946207141Sjeff 947207141Sjeffvoid worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg)) 948207141Sjeff{ 949212617Smckusick log_assert(0); 950207141Sjeff} 951212617Smckusick 952212617Smckusickstruct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname), 953212617Smckusick size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype), 954212617Smckusick uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags), 955207141Sjeff int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec), 956207141Sjeff struct sockaddr_storage* ATTR_UNUSED(addr), 957207141Sjeff socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone), 958207141Sjeff size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q)) 959207141Sjeff{ 960220511Sjeff log_assert(0); 961212617Smckusick return 0; 962207141Sjeff} 963207141Sjeff 964212617Smckusickvoid 965220511Sjeffworker_alloc_cleanup(void* ATTR_UNUSED(arg)) 966212617Smckusick{ 967212617Smckusick log_assert(0); 968212617Smckusick} 969207141Sjeff 970207141Sjeffvoid worker_stat_timer_cb(void* ATTR_UNUSED(arg)) 971207141Sjeff{ 972207141Sjeff log_assert(0); 973207141Sjeff} 974207141Sjeff 975207141Sjeffvoid worker_probe_timer_cb(void* ATTR_UNUSED(arg)) 976212617Smckusick{ 977212617Smckusick log_assert(0); 978207141Sjeff} 979207141Sjeff 980207141Sjeffvoid worker_start_accept(void* ATTR_UNUSED(arg)) 981207141Sjeff{ 982212617Smckusick log_assert(0); 983207141Sjeff} 984256817Smckusick 985256817Smckusickvoid worker_stop_accept(void* ATTR_UNUSED(arg)) 986256817Smckusick{ 987256817Smckusick log_assert(0); 988256817Smckusick} 989256817Smckusick 990256817Smckusickint order_lock_cmp(const void* ATTR_UNUSED(e1), const void* ATTR_UNUSED(e2)) 991256817Smckusick{ 992256817Smckusick log_assert(0); 993256817Smckusick return 0; 994256817Smckusick} 995256817Smckusick 996256817Smckusickint 997256817Smckusickcodeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) 998256817Smckusick{ 999256817Smckusick log_assert(0); 1000256817Smckusick return 0; 1001256817Smckusick} 1002256817Smckusick 1003256817Smckusickint replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) 1004256817Smckusick{ 1005256817Smckusick log_assert(0); 1006256817Smckusick return 0; 1007256817Smckusick} 1008256817Smckusick 1009256817Smckusickvoid remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg)) 1010256817Smckusick{ 1011256817Smckusick log_assert(0); 1012256817Smckusick} 1013256817Smckusick 1014256817Smckusick#ifdef UB_ON_WINDOWS 1015256817Smckusickvoid 1016256817Smckusickworker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void* 1017256817Smckusick ATTR_UNUSED(arg)) { 1018256817Smckusick log_assert(0); 1019256817Smckusick} 1020256817Smckusick 1021256817Smckusickvoid 1022256817Smckusickwsvc_cron_cb(void* ATTR_UNUSED(arg)) 1023256817Smckusick{ 1024256817Smckusick log_assert(0); 1025256817Smckusick} 1026256817Smckusick#endif /* UB_ON_WINDOWS */ 1027256817Smckusick